mirror of
https://github.com/ModOrganizer2/modorganizer-game_bethesda.git
synced 2026-07-27 14:08:44 -07:00
[game_morrowind] Merge pull request #31 from ModOrganizer2/dev/format-and-gh-actions
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
---
|
||||
# We'll use defaults from the LLVM style, but with 4 columns indentation.
|
||||
BasedOnStyle: LLVM
|
||||
IndentWidth: 2
|
||||
---
|
||||
Language: Cpp
|
||||
DeriveLineEnding: false
|
||||
UseCRLF: true
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
AlignConsecutiveAssignments: true
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: Empty
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AccessModifierOffset: -2
|
||||
AlignTrailingComments: true
|
||||
SpacesBeforeTrailingComments: 2
|
||||
NamespaceIndentation: Inner
|
||||
MaxEmptyLinesToKeep: 1
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: true
|
||||
AfterControlStatement: false
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: true
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: true
|
||||
ColumnLimit: 88
|
||||
ForEachMacros: ['Q_FOREACH', 'foreach']
|
||||
@@ -0,0 +1 @@
|
||||
ee98ea2db30bca29fc57d7abc96039ba7fe7ef94
|
||||
@@ -0,0 +1,7 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files you want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.cpp text eol=crlf
|
||||
*.h text eol=crlf
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
name: Build Morrowind Plugin
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- name: Build Morrowind Plugin
|
||||
uses: ModOrganizer2/build-with-mob-action@master
|
||||
with:
|
||||
mo2-dependencies: cmake_common uibase game_gamebryo
|
||||
@@ -0,0 +1,16 @@
|
||||
name: Lint Morrowind Plugin
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check format
|
||||
uses: ModOrganizer2/check-formatting-action@master
|
||||
with:
|
||||
check-path: "."
|
||||
@@ -1,40 +0,0 @@
|
||||
version: 1.0.{build}
|
||||
skip_branch_with_pr: true
|
||||
image: Visual Studio 2019
|
||||
environment:
|
||||
WEBHOOK_URL:
|
||||
secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw=
|
||||
build_script:
|
||||
- pwsh: >-
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella
|
||||
|
||||
New-Item -ItemType Directory -Path c:\projects\modorganizer-build
|
||||
|
||||
cd c:\projects\modorganizer-umbrella
|
||||
|
||||
($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH)
|
||||
|
||||
git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch}
|
||||
|
||||
C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME}
|
||||
|
||||
if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) }
|
||||
artifacts:
|
||||
- path: vsbuild\src\RelWithDebInfo\game_morrowind.dll
|
||||
name: game_morrowind_dll
|
||||
- path: vsbuild\src\RelWithDebInfo\game_morrowind.pdb
|
||||
name: game_morrowind_pdb
|
||||
- path: vsbuild\src\RelWithDebInfo\game_morrowind.lib
|
||||
name: game_morrowind_lib
|
||||
on_success:
|
||||
- ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER
|
||||
- ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1
|
||||
- ps: ./send.ps1 success $env:WEBHOOK_URL
|
||||
on_failure:
|
||||
- ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER
|
||||
- ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log
|
||||
- ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log
|
||||
- ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1
|
||||
- ps: ./send.ps1 failure $env:WEBHOOK_URL
|
||||
@@ -4,10 +4,10 @@
|
||||
#include "morrowinddataarchives.h"
|
||||
#include "morrowindgameplugins.h"
|
||||
#include "morrowindlocalsavegames.h"
|
||||
#include "morrowindsavegame.h"
|
||||
#include "morrowindsavegameinfo.h"
|
||||
#include "morrowindmoddatachecker.h"
|
||||
#include "morrowindmoddatacontent.h"
|
||||
#include "morrowindsavegame.h"
|
||||
#include "morrowindsavegameinfo.h"
|
||||
|
||||
#include "executableinfo.h"
|
||||
#include "pluginsetting.h"
|
||||
@@ -32,23 +32,22 @@
|
||||
|
||||
using namespace MOBase;
|
||||
|
||||
GameMorrowind::GameMorrowind()
|
||||
{
|
||||
}
|
||||
GameMorrowind::GameMorrowind() {}
|
||||
|
||||
bool GameMorrowind::init(IOrganizer *moInfo)
|
||||
bool GameMorrowind::init(IOrganizer* moInfo)
|
||||
{
|
||||
if (!GameGamebryo::init(moInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
auto dataArchives = std::make_shared<MorrowindDataArchives>(this);
|
||||
registerFeature(dataArchives);
|
||||
registerFeature(std::make_shared<MorrowindBSAInvalidation>(dataArchives.get(), this));
|
||||
registerFeature(std::make_shared<MorrowindSaveGameInfo>(this));
|
||||
registerFeature(std::make_shared<MorrowindLocalSavegames>(this));
|
||||
registerFeature(std::make_shared<MorrowindModDataChecker>(this));
|
||||
registerFeature(std::make_shared<MorrowindModDataContent>(m_Organizer->gameFeatures()));
|
||||
registerFeature(
|
||||
std::make_shared<MorrowindModDataContent>(m_Organizer->gameFeatures()));
|
||||
registerFeature(std::make_shared<MorrowindGamePlugins>(moInfo));
|
||||
registerFeature(std::make_shared<GamebryoUnmangedMods>(this));
|
||||
|
||||
@@ -83,12 +82,13 @@ QDir GameMorrowind::documentsDirectory() const
|
||||
QList<ExecutableInfo> GameMorrowind::executables() const
|
||||
{
|
||||
return QList<ExecutableInfo>()
|
||||
<< ExecutableInfo("MWSE (Launcher Method)", findInGameFolder("MWSE Launcher.exe"))
|
||||
<< ExecutableInfo("Morrowind", findInGameFolder(binaryName()))
|
||||
<< ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName()))
|
||||
<< ExecutableInfo("MGE XE", findInGameFolder("MGEXEgui.exe"))
|
||||
<< ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Morrowind\"")
|
||||
;
|
||||
<< ExecutableInfo("MWSE (Launcher Method)",
|
||||
findInGameFolder("MWSE Launcher.exe"))
|
||||
<< ExecutableInfo("Morrowind", findInGameFolder(binaryName()))
|
||||
<< ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName()))
|
||||
<< ExecutableInfo("MGE XE", findInGameFolder("MGEXEgui.exe"))
|
||||
<< ExecutableInfo("LOOT", QFileInfo(getLootPath()))
|
||||
.withArgument("--game=\"Morrowind\"");
|
||||
}
|
||||
|
||||
QList<ExecutableForcedLoadSetting> GameMorrowind::executableForcedLoads() const
|
||||
@@ -106,7 +106,6 @@ QString GameMorrowind::localizedName() const
|
||||
return tr("Morrowind Support Plugin");
|
||||
}
|
||||
|
||||
|
||||
QString GameMorrowind::author() const
|
||||
{
|
||||
return "Schilduin & MO2 Team";
|
||||
@@ -115,7 +114,8 @@ QString GameMorrowind::author() const
|
||||
QString GameMorrowind::description() const
|
||||
{
|
||||
return tr("Adds support for the game Morrowind.\n"
|
||||
"Splash by %1").arg("AnyOldName3");
|
||||
"Splash by %1")
|
||||
.arg("AnyOldName3");
|
||||
}
|
||||
|
||||
MOBase::VersionInfo GameMorrowind::version() const
|
||||
@@ -128,7 +128,7 @@ QList<PluginSetting> GameMorrowind::settings() const
|
||||
return QList<PluginSetting>();
|
||||
}
|
||||
|
||||
void GameMorrowind::initializeProfile(const QDir &path, ProfileSettings settings) const
|
||||
void GameMorrowind::initializeProfile(const QDir& path, ProfileSettings settings) const
|
||||
{
|
||||
if (settings.testFlag(IPluginGame::MODS)) {
|
||||
copyToProfile(localAppFolder() + "/Morrowind", path, "plugins.txt");
|
||||
@@ -149,7 +149,8 @@ QString GameMorrowind::savegameSEExtension() const
|
||||
return "mwse";
|
||||
}
|
||||
|
||||
std::shared_ptr<const GamebryoSaveGame> GameMorrowind::makeSaveGame(QString filePath) const
|
||||
std::shared_ptr<const GamebryoSaveGame>
|
||||
GameMorrowind::makeSaveGame(QString filePath) const
|
||||
{
|
||||
return std::make_shared<const MorrowindSaveGame>(filePath, this);
|
||||
}
|
||||
@@ -161,7 +162,7 @@ QString GameMorrowind::steamAPPId() const
|
||||
|
||||
QStringList GameMorrowind::primaryPlugins() const
|
||||
{
|
||||
return { "morrowind.esm" };
|
||||
return {"morrowind.esm"};
|
||||
}
|
||||
|
||||
QString GameMorrowind::binaryName() const
|
||||
@@ -179,15 +180,14 @@ QString GameMorrowind::gameNexusName() const
|
||||
return "Morrowind";
|
||||
}
|
||||
|
||||
|
||||
QStringList GameMorrowind::iniFiles() const
|
||||
{
|
||||
return { "morrowind.ini" };
|
||||
return {"morrowind.ini"};
|
||||
}
|
||||
|
||||
QStringList GameMorrowind::DLCPlugins() const
|
||||
{
|
||||
return { "Tribunal.esm", "Bloodmoon.esm" };
|
||||
return {"Tribunal.esm", "Bloodmoon.esm"};
|
||||
}
|
||||
|
||||
MOBase::IPluginGame::SortMechanism GameMorrowind::sortMechanism() const
|
||||
@@ -195,15 +195,16 @@ MOBase::IPluginGame::SortMechanism GameMorrowind::sortMechanism() const
|
||||
return SortMechanism::LOOT;
|
||||
}
|
||||
|
||||
namespace {
|
||||
//Note: This is ripped off from shared/util. And in an upcoming move, the fomod
|
||||
//installer requires something similar. I suspect I should abstract this out
|
||||
//into gamebryo (or lower level)
|
||||
namespace
|
||||
{
|
||||
// Note: This is ripped off from shared/util. And in an upcoming move, the fomod
|
||||
// installer requires something similar. I suspect I should abstract this out
|
||||
// into gamebryo (or lower level)
|
||||
|
||||
VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName)
|
||||
VS_FIXEDFILEINFO GetFileVersion(const std::wstring& fileName)
|
||||
{
|
||||
DWORD handle = 0UL;
|
||||
DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle);
|
||||
DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle);
|
||||
if (size == 0) {
|
||||
throw std::runtime_error("failed to determine file version info size");
|
||||
}
|
||||
@@ -214,7 +215,7 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName)
|
||||
throw std::runtime_error("failed to determine file version info");
|
||||
}
|
||||
|
||||
void *versionInfoPtr = nullptr;
|
||||
void* versionInfoPtr = nullptr;
|
||||
UINT versionInfoLength = 0;
|
||||
if (!::VerQueryValue(buffer.data(), L"\\", &versionInfoPtr, &versionInfoLength)) {
|
||||
throw std::runtime_error("failed to determine file version");
|
||||
@@ -223,7 +224,7 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName)
|
||||
return *static_cast<VS_FIXEDFILEINFO*>(versionInfoPtr);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int GameMorrowind::nexusModOrganizerID() const
|
||||
{
|
||||
|
||||
@@ -9,29 +9,29 @@
|
||||
class GameMorrowind : public GameGamebryo
|
||||
{
|
||||
Q_OBJECT
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
Q_PLUGIN_METADATA(IID "com.schilduin.GameMorrowind" FILE "gamemorrowind.json")
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
Q_PLUGIN_METADATA(IID "com.schilduin.GameMorrowind" FILE "gamemorrowind.json")
|
||||
#endif
|
||||
|
||||
friend class MorrowindSaveGameInfo;
|
||||
friend class MorrowindSaveGameInfoWidget;
|
||||
|
||||
public:
|
||||
|
||||
GameMorrowind();
|
||||
|
||||
virtual bool init(MOBase::IOrganizer *moInfo) override;
|
||||
|
||||
public: // IPluginGame interface
|
||||
virtual bool init(MOBase::IOrganizer* moInfo) override;
|
||||
|
||||
public: // IPluginGame interface
|
||||
virtual QString gameName() const override;
|
||||
virtual QString getLauncherName() const override;
|
||||
virtual QDir dataDirectory() const override;
|
||||
virtual QDir savesDirectory() const override;
|
||||
virtual QDir documentsDirectory() const override;
|
||||
virtual QList<MOBase::ExecutableInfo> executables() const override;
|
||||
virtual QList<MOBase::ExecutableForcedLoadSetting> executableForcedLoads() const override;
|
||||
virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override;
|
||||
virtual QList<MOBase::ExecutableForcedLoadSetting>
|
||||
executableForcedLoads() const override;
|
||||
virtual void initializeProfile(const QDir& path,
|
||||
ProfileSettings settings) const override;
|
||||
virtual QString steamAPPId() const override;
|
||||
virtual QStringList primaryPlugins() const override;
|
||||
virtual QString binaryName() const override;
|
||||
@@ -44,8 +44,7 @@ public: // IPluginGame interface
|
||||
virtual int nexusGameID() const override;
|
||||
virtual QString identifyGamePath() const;
|
||||
|
||||
public: // IPlugin interface
|
||||
|
||||
public: // IPlugin interface
|
||||
virtual QString name() const override;
|
||||
virtual QString localizedName() const override;
|
||||
virtual QString author() const override;
|
||||
@@ -54,12 +53,10 @@ public: // IPlugin interface
|
||||
virtual QList<MOBase::PluginSetting> settings() const override;
|
||||
|
||||
protected:
|
||||
|
||||
virtual QString savegameExtension() const override;
|
||||
virtual QString savegameSEExtension() const override;
|
||||
virtual std::shared_ptr<const GamebryoSaveGame> makeSaveGame(QString filepath) const override;
|
||||
virtual std::shared_ptr<const GamebryoSaveGame>
|
||||
makeSaveGame(QString filepath) const override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // GAMEMORROWIND_H
|
||||
#endif // GAMEMORROWIND_H
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "morrowindbsainvalidation.h"
|
||||
|
||||
MorrowindBSAInvalidation::MorrowindBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game)
|
||||
: GamebryoBSAInvalidation(dataArchives, "morrowind.ini", game)
|
||||
{
|
||||
}
|
||||
MorrowindBSAInvalidation::MorrowindBSAInvalidation(MOBase::DataArchives* dataArchives,
|
||||
MOBase::IPluginGame const* game)
|
||||
: GamebryoBSAInvalidation(dataArchives, "morrowind.ini", game)
|
||||
{}
|
||||
|
||||
QString MorrowindBSAInvalidation::invalidationBSAName() const
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef MORROWINDBSAINVALIDATION_H
|
||||
#define MORROWINDBSAINVALIDATION_H
|
||||
|
||||
|
||||
#include "gamebryobsainvalidation.h"
|
||||
#include "morrowinddataarchives.h"
|
||||
|
||||
@@ -10,14 +9,12 @@
|
||||
class MorrowindBSAInvalidation : public GamebryoBSAInvalidation
|
||||
{
|
||||
public:
|
||||
|
||||
MorrowindBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game);
|
||||
MorrowindBSAInvalidation(MOBase::DataArchives* dataArchives,
|
||||
MOBase::IPluginGame const* game);
|
||||
|
||||
private:
|
||||
|
||||
virtual QString invalidationBSAName() const override;
|
||||
virtual unsigned long bsaVersion() const override;
|
||||
|
||||
};
|
||||
|
||||
#endif // MORROWINDBSAINVALIDATION_H
|
||||
#endif // MORROWINDBSAINVALIDATION_H
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
#include "morrowinddataarchives.h"
|
||||
#include <utility.h>
|
||||
#include "registry.h"
|
||||
#include <utility.h>
|
||||
|
||||
MorrowindDataArchives::MorrowindDataArchives(const MOBase::IPluginGame *game)
|
||||
: GamebryoDataArchives(QDir()) // m_LocalGameDir is not used as it's determined too soon
|
||||
, m_GamePlugin(game)
|
||||
{
|
||||
}
|
||||
MorrowindDataArchives::MorrowindDataArchives(const MOBase::IPluginGame* game)
|
||||
: GamebryoDataArchives(
|
||||
QDir()) // m_LocalGameDir is not used as it's determined too soon
|
||||
,
|
||||
m_GamePlugin(game)
|
||||
{}
|
||||
|
||||
QStringList MorrowindDataArchives::vanillaArchives() const
|
||||
{
|
||||
return { "Morrowind.bsa" };
|
||||
return {"Morrowind.bsa"};
|
||||
}
|
||||
|
||||
QStringList MorrowindDataArchives::getArchives(const QString &iniFile) const
|
||||
QStringList MorrowindDataArchives::getArchives(const QString& iniFile) const
|
||||
{
|
||||
wchar_t buffer[256];
|
||||
QStringList result;
|
||||
@@ -22,42 +23,52 @@ QStringList MorrowindDataArchives::getArchives(const QString &iniFile) const
|
||||
errno = 0;
|
||||
|
||||
QString key = "Archive ";
|
||||
int i=0;
|
||||
while (::GetPrivateProfileStringW(L"Archives", (key+QString::number(i)).toStdWString().c_str(),
|
||||
L"", buffer, 256, iniFileW.c_str()) != 0) {
|
||||
int i = 0;
|
||||
while (::GetPrivateProfileStringW(L"Archives",
|
||||
(key + QString::number(i)).toStdWString().c_str(),
|
||||
L"", buffer, 256, iniFileW.c_str()) != 0) {
|
||||
result.append(QString::fromStdWString(buffer).trimmed());
|
||||
i++;
|
||||
i++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MorrowindDataArchives::setArchives(const QString &iniFile, const QStringList &list)
|
||||
void MorrowindDataArchives::setArchives(const QString& iniFile, const QStringList& list)
|
||||
{
|
||||
::WritePrivateProfileSectionW(L"Archives", NULL, iniFile.toStdWString().c_str());
|
||||
|
||||
QString key = "Archive ";
|
||||
QString key = "Archive ";
|
||||
int writtenCount = 0;
|
||||
foreach(const QString &value, list) {
|
||||
if (!MOBase::WriteRegistryValue(L"Archives", (key+QString::number(writtenCount)).toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) {
|
||||
foreach (const QString& value, list) {
|
||||
if (!MOBase::WriteRegistryValue(
|
||||
L"Archives", (key + QString::number(writtenCount)).toStdWString().c_str(),
|
||||
value.toStdWString().c_str(), iniFile.toStdWString().c_str())) {
|
||||
qWarning("failed to set archives in \"%s\"", qUtf8Printable(iniFile));
|
||||
}
|
||||
++writtenCount;
|
||||
++writtenCount;
|
||||
}
|
||||
}
|
||||
|
||||
QStringList MorrowindDataArchives::archives(const MOBase::IProfile *profile) const
|
||||
QStringList MorrowindDataArchives::archives(const MOBase::IProfile* profile) const
|
||||
{
|
||||
QStringList result;
|
||||
|
||||
QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini");
|
||||
QString iniFile =
|
||||
profile->localSettingsEnabled()
|
||||
? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini")
|
||||
: m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini");
|
||||
result.append(getArchives(iniFile));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MorrowindDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before)
|
||||
void MorrowindDataArchives::writeArchiveList(MOBase::IProfile* profile,
|
||||
const QStringList& before)
|
||||
{
|
||||
QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini");
|
||||
QString iniFile =
|
||||
profile->localSettingsEnabled()
|
||||
? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini")
|
||||
: m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini");
|
||||
setArchives(iniFile, before);
|
||||
}
|
||||
|
||||
@@ -1,36 +1,32 @@
|
||||
#ifndef MORROWINDDATAARCHIVES_H
|
||||
#define MORROWINDDATAARCHIVES_H
|
||||
|
||||
|
||||
#include <gamebryodataarchives.h>
|
||||
#include <iprofile.h>
|
||||
#include <iplugingame.h>
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QDir>
|
||||
#include <gamebryodataarchives.h>
|
||||
#include <iplugingame.h>
|
||||
#include <iprofile.h>
|
||||
|
||||
class MorrowindDataArchives : public GamebryoDataArchives
|
||||
{
|
||||
|
||||
public:
|
||||
MorrowindDataArchives(const MOBase::IPluginGame *game);
|
||||
MorrowindDataArchives(const MOBase::IPluginGame* game);
|
||||
|
||||
public:
|
||||
|
||||
virtual QStringList vanillaArchives() const override;
|
||||
virtual QStringList archives(const MOBase::IProfile *profile) const override;
|
||||
virtual QStringList archives(const MOBase::IProfile* profile) const override;
|
||||
|
||||
protected:
|
||||
QStringList getArchives(const QString& iniFile) const;
|
||||
void setArchives(const QString& iniFile, const QStringList& list);
|
||||
|
||||
QStringList getArchives(const QString &iniFile) const;
|
||||
void setArchives(const QString &iniFile, const QStringList &list);
|
||||
|
||||
private:
|
||||
virtual void writeArchiveList(MOBase::IProfile* profile,
|
||||
const QStringList& before) override;
|
||||
|
||||
virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override;
|
||||
|
||||
const MOBase::IPluginGame *m_GamePlugin;
|
||||
|
||||
const MOBase::IPluginGame* m_GamePlugin;
|
||||
};
|
||||
|
||||
#endif // MORROWINDDATAARCHIVES_H
|
||||
#endif // MORROWINDDATAARCHIVES_H
|
||||
|
||||
@@ -1,44 +1,41 @@
|
||||
#include "morrowindgameplugins.h"
|
||||
#include <Windows.h>
|
||||
#include <utility.h>
|
||||
#include <report.h>
|
||||
#include <ipluginlist.h>
|
||||
#include <iplugingame.h>
|
||||
#include <imodinterface.h>
|
||||
#include <scopeguard.h>
|
||||
#include "registry.h"
|
||||
#include <Windows.h>
|
||||
#include <imodinterface.h>
|
||||
#include <iplugingame.h>
|
||||
#include <ipluginlist.h>
|
||||
#include <report.h>
|
||||
#include <scopeguard.h>
|
||||
#include <utility.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QStringList>
|
||||
#include <QString>
|
||||
#include <QStringEncoder>
|
||||
#include <QDateTime>
|
||||
#include <QStringList>
|
||||
|
||||
using MOBase::IOrganizer;
|
||||
using MOBase::IPluginList;
|
||||
using MOBase::reportError;
|
||||
|
||||
MorrowindGamePlugins::MorrowindGamePlugins(IOrganizer *organizer) :
|
||||
GamebryoGamePlugins(organizer)
|
||||
{
|
||||
}
|
||||
MorrowindGamePlugins::MorrowindGamePlugins(IOrganizer* organizer)
|
||||
: GamebryoGamePlugins(organizer)
|
||||
{}
|
||||
|
||||
void MorrowindGamePlugins::writePluginLists(const IPluginList *pluginList) {
|
||||
void MorrowindGamePlugins::writePluginLists(const IPluginList* pluginList)
|
||||
{
|
||||
if (!m_LastRead.isValid()) {
|
||||
// attempt to write uninitialized plugin lists
|
||||
return;
|
||||
}
|
||||
|
||||
if (organizer()->profile()->localSettingsEnabled()) {
|
||||
writePluginList(
|
||||
pluginList,
|
||||
organizer()->profile()->absolutePath() + "/Morrowind.ini"
|
||||
);
|
||||
writePluginList(pluginList,
|
||||
organizer()->profile()->absolutePath() + "/Morrowind.ini");
|
||||
} else {
|
||||
writePluginList(
|
||||
pluginList,
|
||||
organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini"
|
||||
);
|
||||
writePluginList(pluginList,
|
||||
organizer()->managedGame()->gameDirectory().absolutePath() +
|
||||
"/Morrowind.ini");
|
||||
}
|
||||
|
||||
writeLoadOrderList(pluginList,
|
||||
@@ -47,20 +44,20 @@ void MorrowindGamePlugins::writePluginLists(const IPluginList *pluginList) {
|
||||
m_LastRead = QDateTime::currentDateTime();
|
||||
}
|
||||
|
||||
void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) {
|
||||
QString loadOrderPath =
|
||||
organizer()->profile()->absolutePath() + "/loadorder.txt";
|
||||
void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList* pluginList)
|
||||
{
|
||||
QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt";
|
||||
|
||||
QString pluginsPath = organizer()->profile()->absolutePath() + "/Morrowind.ini";
|
||||
if (!organizer()->profile()->localSettingsEnabled()) {
|
||||
pluginsPath = organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini";
|
||||
pluginsPath =
|
||||
organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini";
|
||||
}
|
||||
|
||||
bool loadOrderIsNew = !m_LastRead.isValid() ||
|
||||
!QFileInfo(loadOrderPath).exists() ||
|
||||
QFileInfo(loadOrderPath).lastModified() > m_LastRead;
|
||||
bool pluginsIsNew = !m_LastRead.isValid() ||
|
||||
QFileInfo(pluginsPath).lastModified() > m_LastRead;
|
||||
bool loadOrderIsNew = !m_LastRead.isValid() || !QFileInfo(loadOrderPath).exists() ||
|
||||
QFileInfo(loadOrderPath).lastModified() > m_LastRead;
|
||||
bool pluginsIsNew =
|
||||
!m_LastRead.isValid() || QFileInfo(pluginsPath).lastModified() > m_LastRead;
|
||||
|
||||
if (loadOrderIsNew || !pluginsIsNew) {
|
||||
// read both files if they are both new or both older than the last read
|
||||
@@ -68,7 +65,8 @@ void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) {
|
||||
pluginList->setLoadOrder(loadOrder);
|
||||
readPluginList(pluginList);
|
||||
} else {
|
||||
// If the plugins is new but not loadorder, we must reparse the load order from the plugin files
|
||||
// If the plugins is new but not loadorder, we must reparse the load order from the
|
||||
// plugin files
|
||||
QStringList loadOrder = readPluginList(pluginList);
|
||||
pluginList->setLoadOrder(loadOrder);
|
||||
}
|
||||
@@ -76,35 +74,41 @@ void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) {
|
||||
m_LastRead = QDateTime::currentDateTime();
|
||||
}
|
||||
|
||||
void MorrowindGamePlugins::writePluginList(const MOBase::IPluginList *pluginList,
|
||||
const QString &filePath) {
|
||||
void MorrowindGamePlugins::writePluginList(const MOBase::IPluginList* pluginList,
|
||||
const QString& filePath)
|
||||
{
|
||||
return writeList(pluginList, filePath, false);
|
||||
}
|
||||
|
||||
void MorrowindGamePlugins::writeList(const IPluginList *pluginList,
|
||||
const QString &filePath, bool loadOrder) {
|
||||
QStringEncoder encoder = loadOrder ? QStringEncoder(QStringConverter::Encoding::Utf8) : QStringEncoder(QStringConverter::Encoding::System);
|
||||
void MorrowindGamePlugins::writeList(const IPluginList* pluginList,
|
||||
const QString& filePath, bool loadOrder)
|
||||
{
|
||||
QStringEncoder encoder = loadOrder
|
||||
? QStringEncoder(QStringConverter::Encoding::Utf8)
|
||||
: QStringEncoder(QStringConverter::Encoding::System);
|
||||
|
||||
::WritePrivateProfileSectionW(L"Game Files", NULL, filePath.toStdWString().c_str());
|
||||
|
||||
bool invalidFileNames = false;
|
||||
int writtenCount = 0;
|
||||
int writtenCount = 0;
|
||||
|
||||
QStringList plugins = pluginList->pluginNames();
|
||||
std::sort(plugins.begin(), plugins.end(),
|
||||
[pluginList](const QString &lhs, const QString &rhs) {
|
||||
[pluginList](const QString& lhs, const QString& rhs) {
|
||||
return pluginList->priority(lhs) < pluginList->priority(rhs);
|
||||
});
|
||||
QString key = "GameFile";
|
||||
for (const QString &pluginName : plugins) {
|
||||
if (loadOrder ||
|
||||
(pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) {
|
||||
for (const QString& pluginName : plugins) {
|
||||
if (loadOrder || (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) {
|
||||
auto result = encoder.encode(pluginName);
|
||||
if (encoder.hasError()) {
|
||||
invalidFileNames = true;
|
||||
qCritical("invalid plugin name %s", qUtf8Printable(pluginName));
|
||||
} else {
|
||||
if (!MOBase::WriteRegistryValue(L"Game Files", (key+QString::number(writtenCount)).toStdWString().c_str(), pluginName.toStdWString().c_str(), filePath.toStdWString().c_str())) {
|
||||
if (!MOBase::WriteRegistryValue(
|
||||
L"Game Files",
|
||||
(key + QString::number(writtenCount)).toStdWString().c_str(),
|
||||
pluginName.toStdWString().c_str(), filePath.toStdWString().c_str())) {
|
||||
qWarning("failed to set game files in \"%s\"", qUtf8Printable(filePath));
|
||||
}
|
||||
}
|
||||
@@ -125,15 +129,17 @@ void MorrowindGamePlugins::writeList(const IPluginList *pluginList,
|
||||
}
|
||||
}
|
||||
|
||||
QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList) {
|
||||
QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList* pluginList)
|
||||
{
|
||||
QStringList primary = organizer()->managedGame()->primaryPlugins();
|
||||
for (const QString &pluginName : primary) {
|
||||
for (const QString& pluginName : primary) {
|
||||
if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) {
|
||||
pluginList->setState(pluginName, IPluginList::STATE_ACTIVE);
|
||||
}
|
||||
}
|
||||
QStringList plugins = pluginList->pluginNames();
|
||||
// Do not sort the primary plugins. Their load order should be locked as defined in "primaryPlugins".
|
||||
// Do not sort the primary plugins. Their load order should be locked as defined in
|
||||
// "primaryPlugins".
|
||||
const QStringList pluginsClone(plugins);
|
||||
for (QString plugin : pluginsClone) {
|
||||
if (primary.contains(plugin, Qt::CaseInsensitive))
|
||||
@@ -141,24 +147,27 @@ QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList
|
||||
}
|
||||
|
||||
// Always use filetime loadorder to get the actual load order
|
||||
std::sort(plugins.begin(), plugins.end(), [&](const QString &lhs, const QString &rhs) {
|
||||
MOBase::IModInterface *lhm = organizer()->modList()->getMod(pluginList->origin(lhs));
|
||||
MOBase::IModInterface *rhm = organizer()->modList()->getMod(pluginList->origin(rhs));
|
||||
QDir lhd = organizer()->managedGame()->dataDirectory();
|
||||
QDir rhd = organizer()->managedGame()->dataDirectory();
|
||||
if (lhm != nullptr)
|
||||
lhd = lhm->absolutePath();
|
||||
if (rhm != nullptr)
|
||||
rhd = rhm->absolutePath();
|
||||
QString lhp = lhd.absoluteFilePath(lhs);
|
||||
QString rhp = rhd.absoluteFilePath(rhs);
|
||||
return QFileInfo(lhp).lastModified() <
|
||||
QFileInfo(rhp).lastModified();
|
||||
});
|
||||
std::sort(plugins.begin(), plugins.end(),
|
||||
[&](const QString& lhs, const QString& rhs) {
|
||||
MOBase::IModInterface* lhm =
|
||||
organizer()->modList()->getMod(pluginList->origin(lhs));
|
||||
MOBase::IModInterface* rhm =
|
||||
organizer()->modList()->getMod(pluginList->origin(rhs));
|
||||
QDir lhd = organizer()->managedGame()->dataDirectory();
|
||||
QDir rhd = organizer()->managedGame()->dataDirectory();
|
||||
if (lhm != nullptr)
|
||||
lhd = lhm->absolutePath();
|
||||
if (rhm != nullptr)
|
||||
rhd = rhm->absolutePath();
|
||||
QString lhp = lhd.absoluteFilePath(lhs);
|
||||
QString rhp = rhd.absoluteFilePath(rhs);
|
||||
return QFileInfo(lhp).lastModified() < QFileInfo(rhp).lastModified();
|
||||
});
|
||||
|
||||
QString filePath = organizer()->profile()->absolutePath() + "/Morrowind.ini";
|
||||
if (!organizer()->profile()->localSettingsEnabled()) {
|
||||
filePath = organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini";
|
||||
filePath =
|
||||
organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini";
|
||||
}
|
||||
wchar_t buffer[256];
|
||||
QStringList result;
|
||||
@@ -169,9 +178,10 @@ QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList
|
||||
QStringList activePlugins;
|
||||
QStringList inactivePlugins;
|
||||
QString key = "GameFile";
|
||||
int i = 0;
|
||||
while (::GetPrivateProfileStringW(L"Game Files", (key + QString::number(i)).toStdWString().c_str(),
|
||||
L"", buffer, 256, iniFileW.c_str()) != 0) {
|
||||
int i = 0;
|
||||
while (::GetPrivateProfileStringW(L"Game Files",
|
||||
(key + QString::number(i)).toStdWString().c_str(),
|
||||
L"", buffer, 256, iniFileW.c_str()) != 0) {
|
||||
QString pluginName;
|
||||
pluginName = QString::fromStdWString(buffer).trimmed();
|
||||
pluginList->setState(pluginName, IPluginList::STATE_ACTIVE);
|
||||
@@ -180,11 +190,11 @@ QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList
|
||||
}
|
||||
|
||||
// we removed each plugin found in the file, so what's left are inactive mods
|
||||
for (const QString &pluginName : plugins)
|
||||
for (const QString& pluginName : plugins)
|
||||
if (!activePlugins.contains(pluginName))
|
||||
inactivePlugins.push_back(pluginName);
|
||||
|
||||
for (const QString &pluginName : inactivePlugins)
|
||||
for (const QString& pluginName : inactivePlugins)
|
||||
pluginList->setState(pluginName, IPluginList::STATE_INACTIVE);
|
||||
|
||||
return primary + plugins;
|
||||
|
||||
@@ -7,22 +7,22 @@ class MorrowindGamePlugins : public GamebryoGamePlugins
|
||||
{
|
||||
|
||||
public:
|
||||
MorrowindGamePlugins(MOBase::IOrganizer *organizer);
|
||||
|
||||
virtual void writePluginLists(const MOBase::IPluginList *pluginList) override;
|
||||
virtual void readPluginLists(MOBase::IPluginList *pluginList) override;
|
||||
|
||||
MorrowindGamePlugins(MOBase::IOrganizer* organizer);
|
||||
|
||||
virtual void writePluginLists(const MOBase::IPluginList* pluginList) override;
|
||||
virtual void readPluginLists(MOBase::IPluginList* pluginList) override;
|
||||
|
||||
protected:
|
||||
virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override;
|
||||
virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override;
|
||||
|
||||
virtual void writePluginList(const MOBase::IPluginList* pluginList,
|
||||
const QString& filePath) override;
|
||||
virtual QStringList readPluginList(MOBase::IPluginList* pluginList) override;
|
||||
|
||||
private:
|
||||
virtual void writeList(const MOBase::IPluginList *pluginList, const QString &filePath,
|
||||
bool loadOrder);
|
||||
virtual void writeList(const MOBase::IPluginList* pluginList, const QString& filePath,
|
||||
bool loadOrder);
|
||||
|
||||
private:
|
||||
QDateTime m_LastRead;
|
||||
|
||||
};
|
||||
|
||||
#endif // MORROWINDGAMEPLUGINS_H
|
||||
#endif // MORROWINDGAMEPLUGINS_H
|
||||
|
||||
@@ -16,20 +16,18 @@ License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "morrowindlocalsavegames.h"
|
||||
#include <iprofile.h>
|
||||
#include <QtDebug>
|
||||
#include <windows.h>
|
||||
#include <iprofile.h>
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
MorrowindLocalSavegames::MorrowindLocalSavegames(const MOBase::IPluginGame *game)
|
||||
: m_GamePlugin(game)
|
||||
MorrowindLocalSavegames::MorrowindLocalSavegames(const MOBase::IPluginGame* game)
|
||||
: m_GamePlugin(game)
|
||||
{}
|
||||
|
||||
bool MorrowindLocalSavegames::prepareProfile(MOBase::IProfile *profile)
|
||||
bool MorrowindLocalSavegames::prepareProfile(MOBase::IProfile* profile)
|
||||
{
|
||||
bool dirty = false;
|
||||
|
||||
@@ -52,13 +50,8 @@ bool MorrowindLocalSavegames::prepareProfile(MOBase::IProfile *profile)
|
||||
return dirty;
|
||||
}
|
||||
|
||||
|
||||
MappingType MorrowindLocalSavegames::mappings(const QDir &profileSaveDir) const
|
||||
MappingType MorrowindLocalSavegames::mappings(const QDir& profileSaveDir) const
|
||||
{
|
||||
return {{
|
||||
profileSaveDir.absolutePath(),
|
||||
m_GamePlugin->gameDirectory().absoluteFilePath("Saves"),
|
||||
true,
|
||||
true
|
||||
}};
|
||||
}
|
||||
return {{profileSaveDir.absolutePath(),
|
||||
m_GamePlugin->gameDirectory().absoluteFilePath("Saves"), true, true}};
|
||||
}
|
||||
|
||||
@@ -16,31 +16,26 @@ License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MORROWINDLOCALSAVEGAMES_H
|
||||
#define MORROWINDLOCALSAVEGAMES_H
|
||||
|
||||
|
||||
#include <localsavegames.h>
|
||||
|
||||
#include "iplugingame.h"
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include "iplugingame.h"
|
||||
|
||||
class MorrowindLocalSavegames : public MOBase::LocalSavegames
|
||||
{
|
||||
|
||||
public:
|
||||
MorrowindLocalSavegames(const MOBase::IPluginGame *game);
|
||||
MorrowindLocalSavegames(const MOBase::IPluginGame* game);
|
||||
|
||||
virtual MappingType mappings(const QDir &profileSaveDir) const override;
|
||||
virtual bool prepareProfile(MOBase::IProfile *profile) override;
|
||||
virtual MappingType mappings(const QDir& profileSaveDir) const override;
|
||||
virtual bool prepareProfile(MOBase::IProfile* profile) override;
|
||||
|
||||
private:
|
||||
|
||||
const MOBase::IPluginGame *m_GamePlugin;
|
||||
|
||||
const MOBase::IPluginGame* m_GamePlugin;
|
||||
};
|
||||
|
||||
|
||||
#endif // MORROWINDLOCALSAVEGAMES_H
|
||||
#endif // MORROWINDLOCALSAVEGAMES_H
|
||||
|
||||
@@ -9,19 +9,18 @@ public:
|
||||
using GamebryoModDataChecker::GamebryoModDataChecker;
|
||||
|
||||
protected:
|
||||
virtual const FileNameSet& possibleFolderNames() const override {
|
||||
static FileNameSet result{
|
||||
"fonts", "meshes", "music", "shaders", "sound", "textures", "video",
|
||||
"mwse", "distantland", "mits", "icons", "bookart", "splash"
|
||||
};
|
||||
virtual const FileNameSet& possibleFolderNames() const override
|
||||
{
|
||||
static FileNameSet result{"fonts", "meshes", "music", "shaders", "sound",
|
||||
"textures", "video", "mwse", "distantland", "mits",
|
||||
"icons", "bookart", "splash"};
|
||||
return result;
|
||||
}
|
||||
virtual const FileNameSet& possibleFileExtensions() const override {
|
||||
static FileNameSet result{
|
||||
"esp", "esm", "bsa", "modgroups"
|
||||
};
|
||||
virtual const FileNameSet& possibleFileExtensions() const override
|
||||
{
|
||||
static FileNameSet result{"esp", "esm", "bsa", "modgroups"};
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // MORROWIND_MODATACHECKER_H
|
||||
#endif // MORROWIND_MODATACHECKER_H
|
||||
|
||||
@@ -4,20 +4,21 @@
|
||||
#include <gamebryomoddatacontent.h>
|
||||
#include <ifiletree.h>
|
||||
|
||||
class MorrowindModDataContent : public GamebryoModDataContent {
|
||||
class MorrowindModDataContent : public GamebryoModDataContent
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
MorrowindModDataContent(MOBase::IGameFeatures const* gameFeatures) : GamebryoModDataContent(gameFeatures) {
|
||||
MorrowindModDataContent(MOBase::IGameFeatures const* gameFeatures)
|
||||
: GamebryoModDataContent(gameFeatures)
|
||||
{
|
||||
// Just need to disable some contents:
|
||||
m_Enabled[CONTENT_MCM] = false;
|
||||
m_Enabled[CONTENT_SKYPROC] = false;
|
||||
m_Enabled[CONTENT_MCM] = false;
|
||||
m_Enabled[CONTENT_SKYPROC] = false;
|
||||
m_Enabled[CONTENT_INTERFACE] = false;
|
||||
m_Enabled[CONTENT_SCRIPT] = false;
|
||||
m_Enabled[CONTENT_SCRIPT] = false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MORROWIND_MODDATACONTENT_H
|
||||
#endif // MORROWIND_MODDATACONTENT_H
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include "morrowindsavegame.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <QPixmap>
|
||||
#include <QRegularExpression>
|
||||
#include <Windows.h>
|
||||
#include <filesystem>
|
||||
|
||||
MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, GameMorrowind const *game) :
|
||||
GamebryoSaveGame(fileName, game)
|
||||
MorrowindSaveGame::MorrowindSaveGame(QString const& fileName, GameMorrowind const* game)
|
||||
: GamebryoSaveGame(fileName, game)
|
||||
{
|
||||
std::filesystem::path realFile(fileName.toStdWString());
|
||||
QString realFileName = QString::fromStdWString(realFile.filename().wstring());
|
||||
@@ -14,16 +14,13 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, GameMorrowind cons
|
||||
|
||||
FileWrapper file(fileName, "TES3");
|
||||
QStringList dummyPlugins;
|
||||
fetchInformationFields(file, m_SaveName, dummyPlugins,
|
||||
m_PCCurrentHealth, m_PCCMaxHealth, m_PCLocation, m_GameDays, m_PCName);
|
||||
fetchInformationFields(file, m_SaveName, dummyPlugins, m_PCCurrentHealth,
|
||||
m_PCCMaxHealth, m_PCLocation, m_GameDays, m_PCName);
|
||||
}
|
||||
|
||||
QString MorrowindSaveGame::getName() const
|
||||
{
|
||||
return QString("%1, #%2, %3")
|
||||
.arg(m_PCName)
|
||||
.arg(m_SaveNumber)
|
||||
.arg(m_PCLocation);
|
||||
return QString("%1, #%2, %3").arg(m_PCName).arg(m_SaveNumber).arg(m_PCLocation);
|
||||
}
|
||||
|
||||
unsigned short MorrowindSaveGame::getPCLevel() const
|
||||
@@ -31,53 +28,53 @@ unsigned short MorrowindSaveGame::getPCLevel() const
|
||||
return dynamic_cast<MorrowindDataFields*>(m_DataFields.value().get())->PCLevel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Fetch easy-to-access information.
|
||||
void MorrowindSaveGame::fetchInformationFields(FileWrapper& file,
|
||||
QString& saveName,
|
||||
QStringList& plugins,
|
||||
float& playerCurrentHealth,
|
||||
float& playerMaxHealth,
|
||||
QString& playerLocation,
|
||||
float& gameDays,
|
||||
QString& playerName) const
|
||||
void MorrowindSaveGame::fetchInformationFields(FileWrapper& file, QString& saveName,
|
||||
QStringList& plugins,
|
||||
float& playerCurrentHealth,
|
||||
float& playerMaxHealth,
|
||||
QString& playerLocation, float& gameDays,
|
||||
QString& playerName) const
|
||||
{
|
||||
file.skip<uint32_t>(3); // data size
|
||||
file.skip<unsigned char>(4); // HEDR tag
|
||||
file.skip<uint32_t>(); // header size
|
||||
file.skip<float>(); // header version
|
||||
file.skip<uint32_t>(); // following data chunk size? seems to be 9 groupings of 32 bytes
|
||||
file.skip<unsigned char>(32); // Author empty for save files
|
||||
std::vector<char> saveNameBuffer(256); // 31 char save name with a null terminator
|
||||
file.skip<uint32_t>(3); // data size
|
||||
file.skip<unsigned char>(4); // HEDR tag
|
||||
file.skip<uint32_t>(); // header size
|
||||
file.skip<float>(); // header version
|
||||
file.skip<uint32_t>(); // following data chunk size? seems to be 9 groupings of 32
|
||||
// bytes
|
||||
file.skip<unsigned char>(32); // Author empty for save files
|
||||
std::vector<char> saveNameBuffer(256); // 31 char save name with a null terminator
|
||||
file.read(saveNameBuffer.data(), 256);
|
||||
saveName = QString::fromLatin1(saveNameBuffer.data(), 256).trimmed(); // The defined save name. This is technically the description, but is likely only 31+\0 chars max.
|
||||
file.skip<uint32_t>(); // NumRecords (for the entire save)
|
||||
saveName = QString::fromLatin1(saveNameBuffer.data(), 256)
|
||||
.trimmed(); // The defined save name. This is technically the
|
||||
// description, but is likely only 31+\0 chars max.
|
||||
file.skip<uint32_t>(); // NumRecords (for the entire save)
|
||||
std::vector<char> buffer(255);
|
||||
file.read(buffer.data(), 4);
|
||||
// Parse the MAST/DATA records
|
||||
while (QString::fromLatin1(buffer.data(), 4) == "MAST") {
|
||||
uint32_t len;
|
||||
file.read(len); // Length of master name
|
||||
file.read(buffer.data(), len); // Name of master
|
||||
file.read(len); // Length of master name
|
||||
file.read(buffer.data(), len); // Name of master
|
||||
QString name = QString::fromLatin1(buffer.data(), len - 1);
|
||||
file.skip<unsigned char>(4); // DATA record
|
||||
file.read(len); // Length
|
||||
file.skip<unsigned char>(len); // Typically size 8 - contains length of master data for version checking
|
||||
file.skip<unsigned char>(4); // DATA record
|
||||
file.read(len); // Length
|
||||
file.skip<unsigned char>(
|
||||
len); // Typically size 8 - contains length of master data for version checking
|
||||
|
||||
file.read(buffer.data(), 4); // Get next record type
|
||||
file.read(buffer.data(), 4); // Get next record type
|
||||
plugins.push_back(name);
|
||||
}
|
||||
|
||||
// Start of GMDT
|
||||
file.skip<uint32_t>(); // size of record
|
||||
file.skip<uint32_t>(); // size of record
|
||||
|
||||
file.read(playerCurrentHealth);
|
||||
file.read(playerMaxHealth);
|
||||
|
||||
file.skip<double>(); // current stam?
|
||||
file.skip<double>(); // max stam?
|
||||
//file.skip<double>(2); // unknown values
|
||||
file.skip<double>(); // current stam?
|
||||
file.skip<double>(); // max stam?
|
||||
// file.skip<double>(2); // unknown values
|
||||
|
||||
file.read(buffer.data(), 64);
|
||||
playerLocation = QString::fromLatin1(buffer.data(), 64).trimmed();
|
||||
@@ -100,29 +97,29 @@ std::unique_ptr<GamebryoSaveGame::DataFields> MorrowindSaveGame::fetchDataFields
|
||||
{
|
||||
QString dummy;
|
||||
float dummyF;
|
||||
fetchInformationFields(file, dummy, fields->Plugins,
|
||||
dummyF, dummyF, dummy, dummyF, dummy);
|
||||
fetchInformationFields(file, dummy, fields->Plugins, dummyF, dummyF, dummy, dummyF,
|
||||
dummy);
|
||||
}
|
||||
|
||||
file.skip<unsigned char>(28); // Skip the SCRD
|
||||
// I believe this tells the engine what color each pixel represents and the bitness of the image
|
||||
file.skip<unsigned char>(28); // Skip the SCRD
|
||||
// I believe this tells the engine what color each pixel represents and the bitness of
|
||||
// the image
|
||||
|
||||
// Start of screenshot
|
||||
file.skip<unsigned char>(4); // SCRS
|
||||
file.skip<uint32_t>(); // Size of screenshot always 65536 (128x128x4) RGBA8888
|
||||
file.skip<unsigned char>(4); // SCRS
|
||||
file.skip<uint32_t>(); // Size of screenshot always 65536 (128x128x4) RGBA8888
|
||||
|
||||
QImage image = readImageBGRA(file, 128, 128, 0, 1);
|
||||
QImage image = readImageBGRA(file, 128, 128, 0, 1);
|
||||
fields->Screenshot = image.scaled(252, 192);
|
||||
|
||||
//definitively have to use another method to access the player level
|
||||
//it is stored in the fifth byte of the NPDT subrecord of the first NPC_ record
|
||||
// definitively have to use another method to access the player level
|
||||
// it is stored in the fifth byte of the NPDT subrecord of the first NPC_ record
|
||||
|
||||
//Globals, Scripts, Regions
|
||||
//file.skip<unsigned char>();
|
||||
// Globals, Scripts, Regions
|
||||
// file.skip<unsigned char>();
|
||||
std::vector<char> buff(4);
|
||||
file.read(buff.data(), 4);
|
||||
while (QString::fromLatin1(buff.data(), 4) != "NPC_")
|
||||
{
|
||||
while (QString::fromLatin1(buff.data(), 4) != "NPC_") {
|
||||
uint32_t len;
|
||||
file.read(len);
|
||||
file.skip<unsigned char>(8 + len);
|
||||
@@ -137,8 +134,7 @@ std::unique_ptr<GamebryoSaveGame::DataFields> MorrowindSaveGame::fetchDataFields
|
||||
file.read(buffer.data(), len);
|
||||
if (QString::fromLatin1(buffer.data(), len - 1) == "player") {
|
||||
file.read(buff.data(), 4);
|
||||
while (QString::fromLatin1(buff.data(), 4) != "NPDT")
|
||||
{
|
||||
while (QString::fromLatin1(buff.data(), 4) != "NPDT") {
|
||||
uint32_t len;
|
||||
file.read(len);
|
||||
file.skip<unsigned char>(len);
|
||||
@@ -146,9 +142,7 @@ std::unique_ptr<GamebryoSaveGame::DataFields> MorrowindSaveGame::fetchDataFields
|
||||
}
|
||||
file.skip<unsigned long>();
|
||||
file.read(fields->PCLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
file.skip<unsigned char>(size - len - 8);
|
||||
}
|
||||
}
|
||||
@@ -156,7 +150,9 @@ std::unique_ptr<GamebryoSaveGame::DataFields> MorrowindSaveGame::fetchDataFields
|
||||
return fields;
|
||||
}
|
||||
|
||||
QImage MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper &file, unsigned long width, unsigned long height, int scale = 0, bool alpha = false) const
|
||||
QImage MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper& file,
|
||||
unsigned long width, unsigned long height,
|
||||
int scale = 0, bool alpha = false) const
|
||||
{
|
||||
QImage image(width, height, QImage::Format_RGBA8888);
|
||||
for (unsigned long h = 0; h < width; h++) {
|
||||
@@ -178,4 +174,4 @@ QImage MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper &file, uns
|
||||
return image.copy().scaledToWidth(scale);
|
||||
else
|
||||
return image.copy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,17 @@
|
||||
#include "gamebryosavegame.h"
|
||||
#include "gamemorrowind.h"
|
||||
|
||||
namespace MOBase { class IPluginGame; }
|
||||
namespace MOBase
|
||||
{
|
||||
class IPluginGame;
|
||||
}
|
||||
|
||||
class MorrowindSaveGame : public GamebryoSaveGame
|
||||
{
|
||||
public:
|
||||
MorrowindSaveGame(QString const &fileName, GameMorrowind const *game);
|
||||
|
||||
public: // ISaveGame interface
|
||||
MorrowindSaveGame(QString const& fileName, GameMorrowind const* game);
|
||||
|
||||
public: // ISaveGame interface
|
||||
// We need to override getName() because we do not read the level at
|
||||
// the beginning.
|
||||
virtual QString getName() const override;
|
||||
@@ -21,7 +23,7 @@ public: // ISaveGame interface
|
||||
unsigned short getPCLevel() const override;
|
||||
|
||||
public:
|
||||
//Simple getters
|
||||
// Simple getters
|
||||
QString getSaveName() const { return m_SaveName; }
|
||||
float getPCCurrentHealth() const { return m_PCCurrentHealth; }
|
||||
float getPCMaxHealth() const { return m_PCCMaxHealth; }
|
||||
@@ -34,28 +36,22 @@ protected:
|
||||
float m_GameDays;
|
||||
|
||||
protected:
|
||||
QImage readImageBGRA(
|
||||
GamebryoSaveGame::FileWrapper &file, unsigned long width,
|
||||
unsigned long height, int scale, bool alpha) const;
|
||||
QImage readImageBGRA(GamebryoSaveGame::FileWrapper& file, unsigned long width,
|
||||
unsigned long height, int scale, bool alpha) const;
|
||||
|
||||
// We need to add the PC level here.
|
||||
struct MorrowindDataFields : public DataFields {
|
||||
struct MorrowindDataFields : public DataFields
|
||||
{
|
||||
unsigned short PCLevel = 0;
|
||||
};
|
||||
|
||||
// Fetch easy-to-access information.
|
||||
void fetchInformationFields(
|
||||
FileWrapper& file,
|
||||
QString& saveName,
|
||||
QStringList& plugins,
|
||||
float& playerCurrentHealth,
|
||||
float& playerMaxHealth,
|
||||
QString& playerLocation,
|
||||
float& gameDays,
|
||||
QString& playerName) const;
|
||||
void fetchInformationFields(FileWrapper& file, QString& saveName,
|
||||
QStringList& plugins, float& playerCurrentHealth,
|
||||
float& playerMaxHealth, QString& playerLocation,
|
||||
float& gameDays, QString& playerName) const;
|
||||
|
||||
std::unique_ptr<DataFields> fetchDataFields() const override;
|
||||
|
||||
};
|
||||
|
||||
#endif // MORROWINDSAVEGAME_H
|
||||
#endif // MORROWINDSAVEGAME_H
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user