MTROPOLIS: More variable reference linking hacks to get MTI save games working properly.

This commit is contained in:
elasota 2022-12-28 22:47:10 -05:00
parent f7188eb26d
commit 94fd0060b3
9 changed files with 96 additions and 44 deletions

View File

@ -881,10 +881,10 @@ void ObsidianAutoSaveSceneTransitionHooks::onSceneTransitionEnded(Runtime *runti
if (saveVar && saveVar->isModifier()) {
Modifier *modifier = static_cast<Modifier *>(saveVar.get());
Common::SharedPtr<ModifierSaveLoad> saveLoad = modifier->getSaveLoad();
Common::SharedPtr<ModifierSaveLoad> saveLoad = modifier->getSaveLoad(runtime);
if (saveLoad) {
CompoundVarSaver saver(saveVar.get());
CompoundVarSaver saver(runtime, saveVar.get());
_autoSaveProvider->autoSave(&saver);
_varsState->resyncAllVars(runtime);
@ -1010,8 +1010,8 @@ Common::SharedPtr<ISaveWriter> ObsidianSaveLoadMechanism::createSaveWriter(Runti
if (!cgstCompoundVar)
return nullptr;
if (cgstCompoundVar->getSaveLoad())
return Common::SharedPtr<CompoundVarSaver>(new CompoundVarSaver(cgstCompoundVar));
if (cgstCompoundVar->getSaveLoad(runtime))
return Common::SharedPtr<CompoundVarSaver>(new CompoundVarSaver(runtime, cgstCompoundVar));
return nullptr;
}

View File

@ -37,15 +37,16 @@ namespace MTropolis {
class CompoundVarLoader : public ISaveReader {
public:
explicit CompoundVarLoader(RuntimeObject *object);
CompoundVarLoader(Runtime *runtime, RuntimeObject *object);
bool readSave(Common::ReadStream *stream, uint32 saveFileVersion) override;
private:
Runtime *_runtime;
RuntimeObject *_object;
};
CompoundVarLoader::CompoundVarLoader(RuntimeObject *object) : _object(object) {
CompoundVarLoader::CompoundVarLoader(Runtime *runtime, RuntimeObject *object) : _runtime(runtime), _object(object) {
}
bool CompoundVarLoader::readSave(Common::ReadStream *stream, uint32 saveFileVersion) {
@ -53,7 +54,7 @@ bool CompoundVarLoader::readSave(Common::ReadStream *stream, uint32 saveFileVers
return false;
Modifier *modifier = static_cast<Modifier *>(_object);
Common::SharedPtr<ModifierSaveLoad> saveLoad = modifier->getSaveLoad();
Common::SharedPtr<ModifierSaveLoad> saveLoad = modifier->getSaveLoad(_runtime);
if (!saveLoad)
return false;
@ -403,7 +404,7 @@ VThreadState SaveAndRestoreModifier::consumeMessage(Runtime *runtime, const Comm
bool isPrompt = (_filePath == "Ask User");
if (_saveWhen.respondsTo(msg->getEvent())) {
CompoundVarSaver saver(obj);
CompoundVarSaver saver(runtime, obj);
const Graphics::ManagedSurface *screenshotOverrideManaged = runtime->getSaveScreenshotOverride().get();
const Graphics::Surface *screenshotOverride = nullptr;
@ -423,7 +424,7 @@ VThreadState SaveAndRestoreModifier::consumeMessage(Runtime *runtime, const Comm
}
return kVThreadReturn;
} else if (_restoreWhen.respondsTo(msg->getEvent())) {
CompoundVarLoader loader(obj);
CompoundVarLoader loader(runtime, obj);
bool succeeded = false;
if (isPrompt)
@ -2337,8 +2338,8 @@ void CompoundVariableModifier::disable(Runtime *runtime) {
// Do nothing I guess, no variables can be disabled
}
Common::SharedPtr<ModifierSaveLoad> CompoundVariableModifier::getSaveLoad() {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
Common::SharedPtr<ModifierSaveLoad> CompoundVariableModifier::getSaveLoad(Runtime *runtime) {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(runtime, this));
}
IModifierContainer *CompoundVariableModifier::getChildContainer() {
@ -2426,9 +2427,55 @@ Modifier *CompoundVariableModifier::findChildByName(Runtime *runtime, const Comm
CompoundVariableModifier::SaveLoad::ChildSaveLoad::ChildSaveLoad() : modifier(nullptr) {
}
CompoundVariableModifier::SaveLoad::SaveLoad(CompoundVariableModifier *modifier) /* : _modifier(modifier) */ {
CompoundVariableModifier::SaveLoad::SaveLoad(Runtime *runtime, CompoundVariableModifier *modifier) /* : _modifier(modifier) */ {
// Gross hacks for MTI save games.
//
// This looks like it's due to some kind of divergence between mTropolis 1.1 and whatever
// MTI shipped with. MTI's saves are done using a compound variable named "MTI" in the Load/Save scene
// which contains aliases to compound vars a, b, c, d, and g. While these are aliases to the same globals
// as are used elsewhere (unlike the "billyState" hack), mTropolis 1.1 will DUPLICATE compound variables children
// unless the children themselves are aliases, which is not the case in MTI.
//
// Consequently, the default behavior here is that the compounds in the Load/Save menu will not reference the
// children of the aliases compound. So, we need to patch those references here.
bool isMTIHackG = false;
bool isMTIHackGlobalContainer = false;
if (runtime->getHacks().mtiVariableReferencesHack) {
const Common::String &name = modifier->getName();
if (name == "g") {
isMTIHackG = true;
} else if (name == "a" || name == "b" || name == "c" || name == "d") {
isMTIHackGlobalContainer = true;
}
}
if (isMTIHackG) {
// For "g" use the "g" in the project instead
for (const Common::SharedPtr<Modifier> &projChild : runtime->getProject()->getModifiers()) {
if (projChild->getName() == "g" && projChild->isCompoundVariable()) {
modifier = static_cast<CompoundVariableModifier *>(projChild.get());
break;
}
}
}
for (const Common::SharedPtr<Modifier> &child : modifier->_children) {
Common::SharedPtr<ModifierSaveLoad> childSL = child->getSaveLoad();
if (isMTIHackGlobalContainer) {
Common::SharedPtr<Modifier> globalVarModifier = runtime->getProject()->findGlobalVarWithName(child->getName());
if (globalVarModifier) {
Common::SharedPtr<ModifierSaveLoad> childSL = globalVarModifier->getSaveLoad(runtime);
ChildSaveLoad childSaveLoad;
childSaveLoad.saveLoad = childSL;
childSaveLoad.modifier = globalVarModifier.get();
_childrenSaveLoad.push_back(childSaveLoad);
continue;
}
}
Common::SharedPtr<ModifierSaveLoad> childSL = child->getSaveLoad(runtime);
if (childSL) {
ChildSaveLoad childSaveLoad;
childSaveLoad.saveLoad = childSL;
@ -2518,7 +2565,7 @@ const char *BooleanVariableModifier::getDefaultName() const {
BooleanVariableStorage::BooleanVariableStorage() : _value(false) {
}
Common::SharedPtr<ModifierSaveLoad> BooleanVariableStorage::getSaveLoad() {
Common::SharedPtr<ModifierSaveLoad> BooleanVariableStorage::getSaveLoad(Runtime *runtime) {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}
@ -2562,7 +2609,7 @@ bool IntegerVariableModifier::load(ModifierLoaderContext& context, const Data::I
IntegerVariableStorage::IntegerVariableStorage() : _value(0) {
}
Common::SharedPtr<ModifierSaveLoad> IntegerVariableStorage::getSaveLoad() {
Common::SharedPtr<ModifierSaveLoad> IntegerVariableStorage::getSaveLoad(Runtime *runtime) {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}
@ -2698,7 +2745,7 @@ const char *IntegerRangeVariableModifier::getDefaultName() const {
IntegerRangeVariableStorage::IntegerRangeVariableStorage() {
}
Common::SharedPtr<ModifierSaveLoad> IntegerRangeVariableStorage::getSaveLoad() {
Common::SharedPtr<ModifierSaveLoad> IntegerRangeVariableStorage::getSaveLoad(Runtime *runtime) {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}
@ -2811,7 +2858,7 @@ const char *VectorVariableModifier::getDefaultName() const {
VectorVariableStorage::VectorVariableStorage() {
}
Common::SharedPtr<ModifierSaveLoad> VectorVariableStorage::getSaveLoad() {
Common::SharedPtr<ModifierSaveLoad> VectorVariableStorage::getSaveLoad(Runtime *runtime) {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}
@ -2926,7 +2973,7 @@ const char *PointVariableModifier::getDefaultName() const {
PointVariableStorage::PointVariableStorage() {
}
Common::SharedPtr<ModifierSaveLoad> PointVariableStorage::getSaveLoad() {
Common::SharedPtr<ModifierSaveLoad> PointVariableStorage::getSaveLoad(Runtime *runtime) {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}
@ -3010,7 +3057,7 @@ const char *FloatingPointVariableModifier::getDefaultName() const {
FloatingPointVariableStorage::FloatingPointVariableStorage() : _value(0.0) {
}
Common::SharedPtr<ModifierSaveLoad> FloatingPointVariableStorage::getSaveLoad() {
Common::SharedPtr<ModifierSaveLoad> FloatingPointVariableStorage::getSaveLoad(Runtime *runtime) {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}
@ -3092,7 +3139,7 @@ const char *StringVariableModifier::getDefaultName() const {
StringVariableStorage::StringVariableStorage() {
}
Common::SharedPtr<ModifierSaveLoad> StringVariableStorage::getSaveLoad() {
Common::SharedPtr<ModifierSaveLoad> StringVariableStorage::getSaveLoad(Runtime *runtime) {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}
@ -3188,7 +3235,7 @@ const char *ObjectReferenceVariableModifierV1::getDefaultName() const {
ObjectReferenceVariableV1Storage::ObjectReferenceVariableV1Storage() {
}
Common::SharedPtr<ModifierSaveLoad> ObjectReferenceVariableV1Storage::getSaveLoad() {
Common::SharedPtr<ModifierSaveLoad> ObjectReferenceVariableV1Storage::getSaveLoad(Runtime *runtime) {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}

View File

@ -964,7 +964,7 @@ public:
void disable(Runtime *runtime) override;
Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) override;
IModifierContainer *getChildContainer() override;
@ -978,7 +978,7 @@ public:
private:
class SaveLoad : public ModifierSaveLoad {
public:
explicit SaveLoad(CompoundVariableModifier *modifier);
SaveLoad(Runtime *runtime, CompoundVariableModifier *modifier);
void saveInternal(Common::WriteStream *stream) const override;
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
@ -1040,7 +1040,7 @@ public:
BooleanVariableStorage();
Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) override;
Common::SharedPtr<VariableStorage> clone() const override;
@ -1087,7 +1087,7 @@ public:
IntegerVariableStorage();
Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) override;
Common::SharedPtr<VariableStorage> clone() const override;
@ -1137,7 +1137,7 @@ public:
IntegerRangeVariableStorage();
Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) override;
Common::SharedPtr<VariableStorage> clone() const override;
@ -1186,7 +1186,7 @@ class VectorVariableStorage : public VariableStorage {
VectorVariableStorage();
Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) override;
Common::SharedPtr<VariableStorage> clone() const override;
@ -1236,7 +1236,7 @@ public:
PointVariableStorage();
Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) override;
Common::SharedPtr<VariableStorage> clone() const override;
@ -1283,7 +1283,7 @@ public:
FloatingPointVariableStorage();
Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) override;
Common::SharedPtr<VariableStorage> clone() const override;
@ -1330,7 +1330,7 @@ public:
StringVariableStorage();
Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) override;
Common::SharedPtr<VariableStorage> clone() const override;
@ -1382,7 +1382,7 @@ public:
ObjectReferenceVariableV1Storage();
Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) override;
Common::SharedPtr<VariableStorage> clone() const override;

View File

@ -2327,7 +2327,7 @@ ObjectReferenceVariableStorage::SaveLoad::SaveLoad(ObjectReferenceVariableStorag
ObjectReferenceVariableStorage::ObjectReferenceVariableStorage() {
}
Common::SharedPtr<ModifierSaveLoad> ObjectReferenceVariableStorage::getSaveLoad() {
Common::SharedPtr<ModifierSaveLoad> ObjectReferenceVariableStorage::getSaveLoad(Runtime *runtime) {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}
@ -3056,7 +3056,7 @@ const char *ListVariableModifier::getDefaultName() const {
ListVariableStorage::ListVariableStorage() : _preferredContentType(DynamicValueTypes::kInteger), _list(new DynamicList()) {
}
Common::SharedPtr<ModifierSaveLoad> ListVariableStorage::getSaveLoad() {
Common::SharedPtr<ModifierSaveLoad> ListVariableStorage::getSaveLoad(Runtime *runtime) {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}

View File

@ -218,7 +218,7 @@ public:
ObjectReferenceVariableStorage();
Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) override;
Common::SharedPtr<VariableStorage> clone() const override;
@ -335,7 +335,7 @@ public:
ListVariableStorage();
Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) override;
Common::SharedPtr<VariableStorage> clone() const override;

View File

@ -3489,6 +3489,8 @@ void Structural::debugInspect(IDebugInspectionReport *report) const {
report->declareStaticContents(debugGetTypeName());
if (report->declareStatic("guid"))
report->declareStaticContents(Common::String::format("%x", getStaticGUID()));
if (report->declareStatic("runtimeID"))
report->declareStaticContents(Common::String::format("%x", getRuntimeGUID()));
}
void Structural::debugSkipMovies() {
@ -8723,7 +8725,7 @@ bool Modifier::isKeyboardMessenger() const {
return false;
}
Common::SharedPtr<ModifierSaveLoad> Modifier::getSaveLoad() {
Common::SharedPtr<ModifierSaveLoad> Modifier::getSaveLoad(Runtime *runtime) {
return nullptr;
}
@ -8819,6 +8821,8 @@ void Modifier::debugInspect(IDebugInspectionReport *report) const {
report->declareStaticContents(debugGetTypeName());
if (report->declareStatic("guid"))
report->declareStaticContents(Common::String::format("%x", getStaticGUID()));
if (report->declareStatic("runtimeID"))
report->declareStaticContents(Common::String::format("%x", getRuntimeGUID()));
}
#endif /* MTROPOLIS_DEBUG_ENABLE */
@ -8841,8 +8845,8 @@ bool VariableModifier::isListVariable() const {
}
Common::SharedPtr<ModifierSaveLoad> VariableModifier::getSaveLoad() {
return _storage->getSaveLoad();
Common::SharedPtr<ModifierSaveLoad> VariableModifier::getSaveLoad(Runtime *runtime) {
return _storage->getSaveLoad(runtime);
}
const Common::SharedPtr<VariableStorage> &VariableModifier::getStorage() const {

View File

@ -2859,7 +2859,7 @@ public:
virtual bool isBehavior() const;
virtual bool isCompoundVariable() const;
virtual bool isKeyboardMessenger() const;
virtual Common::SharedPtr<ModifierSaveLoad> getSaveLoad();
virtual Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime);
bool isModifier() const override;
@ -2925,7 +2925,7 @@ protected:
class VariableStorage {
public:
virtual ~VariableStorage();
virtual Common::SharedPtr<ModifierSaveLoad> getSaveLoad() = 0;
virtual Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) = 0;
virtual Common::SharedPtr<VariableStorage> clone() const = 0;
};
@ -2938,7 +2938,7 @@ public:
virtual bool isVariable() const override;
virtual bool isListVariable() const;
virtual Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override final;
virtual Common::SharedPtr<ModifierSaveLoad> getSaveLoad(Runtime *runtime) override final;
const Common::SharedPtr<VariableStorage> &getStorage() const;
void setStorage(const Common::SharedPtr<VariableStorage> &storage);

View File

@ -33,7 +33,7 @@
namespace MTropolis {
CompoundVarSaver::CompoundVarSaver(RuntimeObject *object) : _object(object) {
CompoundVarSaver::CompoundVarSaver(Runtime *runtime, RuntimeObject *object) : _runtime(runtime), _object(object) {
}
bool CompoundVarSaver::writeSave(Common::WriteStream *stream) {
@ -41,7 +41,7 @@ bool CompoundVarSaver::writeSave(Common::WriteStream *stream) {
return false;
Modifier *modifier = static_cast<Modifier *>(_object);
Common::SharedPtr<ModifierSaveLoad> saveLoad = modifier->getSaveLoad();
Common::SharedPtr<ModifierSaveLoad> saveLoad = modifier->getSaveLoad(_runtime);
if (!saveLoad)
return false;

View File

@ -67,11 +67,12 @@ struct IAutoSaveProvider : public IInterfaceBase {
class CompoundVarSaver : public ISaveWriter {
public:
explicit CompoundVarSaver(RuntimeObject *object);
CompoundVarSaver(Runtime *runtime, RuntimeObject *object);
bool writeSave(Common::WriteStream *stream) override;
private:
Runtime *_runtime;
RuntimeObject *_object;
};