1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
#ifndef GAMEGAMEBRYO_H
#define GAMEGAMEBRYO_H
#include "iplugingame.h"
class BSAInvalidation;
class DataArchives;
class LocalSavegames;
class SaveGameInfo;
class BSAInvalidation;
class LocalSavegames;
class ScriptExtender;
class GamePlugins;
class UnmanagedMods;
#include <QObject>
#include <QString>
#ifdef _WIN32
#include <ShlObj.h>
#include <dbghelp.h>
#endif
#include <ipluginfilemapper.h>
#include <iplugingame.h>
#include <memory>
#include "gamebryosavegame.h"
#include "igamefeatures.h"
class GameGamebryo : public MOBase::IPluginGame, public MOBase::IPluginFileMapper
{
Q_OBJECT
Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame MOBase::IPluginFileMapper)
friend class GamebryoScriptExtender;
friend class GamebryoSaveGameInfo;
friend class GamebryoSaveGameInfoWidget;
friend class GamebryoSaveGame;
/**
* Some Bethesda games do not have a valid file version but a valid product
* version. If the file version starts with FALLBACK_GAME_VERSION, the product
* version will be tried.
*/
static constexpr const char* FALLBACK_GAME_VERSION = "1.0.0";
public:
GameGamebryo();
void detectGame() override;
bool init(MOBase::IOrganizer* moInfo) override;
public: // IPluginGame interface
// getName
// initializeProfile
virtual std::vector<std::shared_ptr<const MOBase::ISaveGame>>
listSaves(QDir folder) const override;
virtual bool isInstalled() const override;
virtual QIcon gameIcon() const override;
virtual QDir gameDirectory() const override;
virtual QDir dataDirectory() const override;
// secondaryDataDirectories
virtual void setGamePath(const QString& path) override;
virtual QDir documentsDirectory() const override;
virtual QDir savesDirectory() const override;
// executables
// steamAPPId
// primaryPlugins
// enabledPlugins
// gameVariants
virtual void setGameVariant(const QString& variant) override;
virtual QString binaryName() const override;
// gameShortName
// primarySources
// validShortNames
// iniFiles
// DLCPlugins
// CCPlugins
virtual LoadOrderMechanism loadOrderMechanism() const override;
virtual SortMechanism sortMechanism() const override;
// nexusModOrganizerID
// nexusGameID
virtual bool looksValid(QDir const&) const override;
virtual QString gameVersion() const override;
virtual QString getLauncherName() const override;
public: // IPluginFileMapper interface
virtual MappingType mappings() const;
public: // Other (e.g. for game features)
QString myGamesPath() const;
// Returns the folder name used by the game under AppData/Local
// (e.g. "FalloutNV", "Skyrim Special Edition"). Defaults to the
// My Games subfolder name. Override in games where these differ
// (e.g. Enderal uses lowercase "enderal" in AppData but "Enderal"
// in My Games).
virtual QString localAppName() const;
protected:
// Retrieve the saves extension for the game.
virtual QString savegameExtension() const = 0;
virtual QString savegameSEExtension() const = 0;
// Create a save game.
virtual std::shared_ptr<const GamebryoSaveGame>
makeSaveGame(QString filepath) const = 0;
QFileInfo findInGameFolder(const QString& relativePath) const;
QString selectedVariant() const;
static QString localAppFolder();
// Arguably this shouldn't really be here but every gamebryo program seems to
// use it
static QString getLootPath();
// This function is not terribly well named as it copies exactly where it's told
// to, irrespective of whether it's in the profile...
static void copyToProfile(const QString& sourcePath, const QDir& destinationDirectory,
const QString& sourceFileName);
static void copyToProfile(const QString& sourcePath, const QDir& destinationDirectory,
const QString& sourceFileName,
const QString& destinationFileName);
virtual QString identifyGamePath() const;
virtual bool prepareIni(const QString& exec);
public:
// Ensure all game INI files exist with adequate content in the given
// base path. On Linux, seeds missing/stub INIs from the game's default
// INI templates and creates case-matching symlinks if needed.
void ensureIniFilesExist(const QString& basePath);
protected:
#ifdef _WIN32
static std::unique_ptr<BYTE[]> getRegValue(HKEY key, LPCWSTR path, LPCWSTR value,
DWORD flags, LPDWORD type);
static QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value);
static QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault);
static QString getSpecialPath(const QString& name);
#endif
WORD getArch(QString const& program) const;
// createIfMissing=false is the safe default: the per-game plugin ctor
// calls this for every installed Bethesda game and we don't want to
// spam `Documents/My Games/<GameName>` directories for games the user
// isn't actually managing (see issue #55). Pass true only when we
// know the game is installed and likely to be used.
static QString determineMyGamesPath(const QString& gameName,
bool createIfMissing = false);
static QString parseEpicGamesLocation(const QStringList& manifests);
static QString parseSteamLocation(const QString& appid, const QString& directoryName);
public: // Cross-platform INI file utilities (used by game features)
// Read a value from a Bethesda-style INI file using QSettings
static QString readIniValue(const QString& iniFile, const QString& section,
const QString& key, const QString& defaultValue = QString());
protected:
void registerFeature(std::shared_ptr<MOBase::GameFeature> feature);
protected:
// to access organizer for game features, avoid having to pass it to all saves since
// we already pass the game
friend class GamebryoSaveGame;
QString m_GamePath;
QString m_MyGamesPath;
QString m_GameVariant;
MOBase::IOrganizer* m_Organizer;
};
#endif // GAMEGAMEBRYO_H
|