From baeff6a73609e22adcb27e18aa78bed5b12a308d Mon Sep 17 00:00:00 2001 From: elasota Date: Wed, 14 Jun 2023 00:48:35 -0400 Subject: [PATCH] MTROPOLIS: Add hack to get MTI molasses wipe-off section working --- engines/mtropolis/elements.cpp | 2 +- engines/mtropolis/hacks.cpp | 131 ++++++++++++++++++++++++++++++++- engines/mtropolis/runtime.cpp | 7 +- engines/mtropolis/runtime.h | 2 +- 4 files changed, 135 insertions(+), 7 deletions(-) diff --git a/engines/mtropolis/elements.cpp b/engines/mtropolis/elements.cpp index b8e90754651..ffaeec4bf97 100644 --- a/engines/mtropolis/elements.cpp +++ b/engines/mtropolis/elements.cpp @@ -1584,7 +1584,7 @@ VThreadState MToonElement::stopPlayingTask(const StopPlayingTaskData &taskData) } if (_hooks) - _hooks->onStopPlayingMToon(this, _visible, _isStopped); + _hooks->onStopPlayingMToon(this, _visible, _isStopped, _renderSurface.get()); return kVThreadReturn; } diff --git a/engines/mtropolis/hacks.cpp b/engines/mtropolis/hacks.cpp index 382351f7f29..bed680d7d0b 100644 --- a/engines/mtropolis/hacks.cpp +++ b/engines/mtropolis/hacks.cpp @@ -1023,10 +1023,119 @@ void addObsidianSaveMechanism(const MTropolisGameDescription &desc, Hacks &hacks hacks.addSaveLoadMechanismHooks(mechanism); } +class MTIMolassesHandler : public IPostEffect { +public: + void setFullScreenSurface(const Graphics::ManagedSurface &srcSurf); + void wipeRect(const Common::Rect &rect); + void setInitialRect(const Common::Rect &rect); + + void release(); + + void renderPostEffect(Graphics::ManagedSurface &surface) const override; + +private: + Graphics::ManagedSurface _surf; + Common::Rect _initialRect; +}; + +void MTIMolassesHandler::setFullScreenSurface(const Graphics::ManagedSurface &srcSurf) { + _surf.copyFrom(srcSurf); + wipeRect(_initialRect); +} + +void MTIMolassesHandler::wipeRect(const Common::Rect &rect) { + _surf.fillRect(rect, 0); +} + +void MTIMolassesHandler::setInitialRect(const Common::Rect &rect) { + _initialRect = rect; +} + +void MTIMolassesHandler::release() { + _surf.free(); +} + +void MTIMolassesHandler::renderPostEffect(Graphics::ManagedSurface &surface) const { + surface.transBlitFrom(_surf, Common::Point(0, 0), 0); +} + +class MTIMolassesFullscreenHooks : public StructuralHooks { +public: + explicit MTIMolassesFullscreenHooks(const Common::SharedPtr &molassesHandler); + + void onStopPlayingMToon(Structural *structural, bool &hide, bool &stopped, Graphics::ManagedSurface *lastSurf) override; + +private: + Common::SharedPtr _molassesHandler; +}; + +MTIMolassesFullscreenHooks::MTIMolassesFullscreenHooks(const Common::SharedPtr &molassesHandler) : _molassesHandler(molassesHandler) { +} + +void MTIMolassesFullscreenHooks::onStopPlayingMToon(Structural *structural, bool &hide, bool &stopped, Graphics::ManagedSurface *lastSurf) { + _molassesHandler->setFullScreenSurface(*lastSurf); +} + +class MTIMolassesSpongeHooks : public StructuralHooks { +public: + explicit MTIMolassesSpongeHooks(const Common::SharedPtr &molassesHandler); + + void onPostActivate(Structural *structural) override; + void onSetPosition(Runtime *runtime, Structural *structural, const Common::Point &oldPt, Common::Point &pt) override; + +private: + Common::SharedPtr _molassesHandler; +}; + +MTIMolassesSpongeHooks::MTIMolassesSpongeHooks(const Common::SharedPtr &molassesHandler) : _molassesHandler(molassesHandler) { +} + +void MTIMolassesSpongeHooks::onPostActivate(Structural *structural) { + VisualElement *visual = static_cast(structural); + + _molassesHandler->setInitialRect(visual->getRelativeRect()); +} + +void MTIMolassesSpongeHooks::onSetPosition(Runtime *runtime, Structural *structural, const Common::Point &oldPt, Common::Point &pt) { + const Common::Rect relRect = static_cast(structural)->getRelativeRect(); + + int16 w = relRect.width(); + int16 h = relRect.height(); + + Common::Rect wipeRect = Common::Rect(pt.x, pt.y, pt.x + w, pt.y + h); + + _molassesHandler->wipeRect(wipeRect); +} + +class MTIMolassesSceneTransitionHooks : public SceneTransitionHooks { +public: + explicit MTIMolassesSceneTransitionHooks(const Common::SharedPtr &molassesHandler); + + void onSceneTransitionSetup(Runtime *runtime, const Common::WeakPtr &oldScene, const Common::WeakPtr &newScene) override; + +private: + Common::SharedPtr _molassesHandler; +}; + +MTIMolassesSceneTransitionHooks::MTIMolassesSceneTransitionHooks(const Common::SharedPtr &molassesHandler) : _molassesHandler(molassesHandler) { +} + +void MTIMolassesSceneTransitionHooks::onSceneTransitionSetup(Runtime *runtime, const Common::WeakPtr &oldScene, const Common::WeakPtr &newScene) { + Structural *oldScenePtr = oldScene.lock().get(); + Structural *newScenePtr = newScene.lock().get(); + + const char *molassesSceneName = "B01c: Molasses"; + + if (oldScenePtr && oldScenePtr->getName() == molassesSceneName) + runtime->removePostEffect(_molassesHandler.get()); + else if (newScenePtr && newScenePtr->getName() == molassesSceneName) + runtime->addPostEffect(_molassesHandler.get()); +} + class MTIBuggyAnimationHooks : public StructuralHooks { public: void onSetPosition(Runtime *runtime, Structural *structural, const Common::Point &oldPt, Common::Point &pt) override; - void onStopPlayingMToon(Structural *structural, bool &hide, bool &stopped) override; + void onStopPlayingMToon(Structural *structural, bool &hide, bool &stopped, Graphics::ManagedSurface *lastSurf) override; void onHidden(Structural *structural, bool &visible) override; }; @@ -1036,7 +1145,7 @@ void MTIBuggyAnimationHooks::onSetPosition(Runtime *runtime, Structural *structu pt = oldPt; } -void MTIBuggyAnimationHooks::onStopPlayingMToon(Structural *structural, bool &visible, bool &stopped) { +void MTIBuggyAnimationHooks::onStopPlayingMToon(Structural *structural, bool &visible, bool &stopped, Graphics::ManagedSurface *lastSurf) { // Un-stop visible = true; stopped = false; @@ -1049,9 +1158,17 @@ void MTIBuggyAnimationHooks::onHidden(Structural *structural, bool &visible) { class MTIStructuralHooks : public StructuralHooks { public: + explicit MTIStructuralHooks(const Common::SharedPtr &molassesHandler); + void onPostActivate(Structural *structural) override; + +private: + Common::SharedPtr _molassesHandler; }; +MTIStructuralHooks::MTIStructuralHooks(const Common::SharedPtr &molassesHandler) : _molassesHandler(molassesHandler) { +} + void MTIStructuralHooks::onPostActivate(Structural *structural) { const Common::String &name = structural->getName(); @@ -1068,6 +1185,11 @@ void MTIStructuralHooks::onPostActivate(Structural *structural) { // - Molasses when leaving Benbow (A08agp01.tun) // - Long John Silver in the life boat when disembarking the Hispaniola (C01c0005.tun and C01c0005a.tun) structural->setHooks(Common::SharedPtr(new MTIBuggyAnimationHooks())); + } else if (name == "B01cgp01.tun") { + structural->setHooks(Common::SharedPtr(new MTIMolassesFullscreenHooks(_molassesHandler))); + } else if (name == "B01c_newsponge.tun") { + structural->setHooks(Common::SharedPtr(new MTIMolassesSpongeHooks(_molassesHandler))); + structural->getHooks()->onPostActivate(structural); } } @@ -1108,7 +1230,10 @@ void addMTIQuirks(const MTropolisGameDescription &desc, Hacks &hacks) { // which causes an integrity check failure when disembarking the Hispaniola. hacks.mtiHispaniolaDamagedStringHack = true; - hacks.defaultStructuralHooks.reset(new MTIStructuralHooks()); + Common::SharedPtr molassesHandler(new MTIMolassesHandler()); + + hacks.defaultStructuralHooks.reset(new MTIStructuralHooks(molassesHandler)); + hacks.addSceneTransitionHooks(Common::SharedPtr(new MTIMolassesSceneTransitionHooks(molassesHandler))); } } // End of namespace HackSuites diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp index 371f612cca4..b4b66a55c47 100644 --- a/engines/mtropolis/runtime.cpp +++ b/engines/mtropolis/runtime.cpp @@ -2982,7 +2982,7 @@ void StructuralHooks::onPostActivate(Structural *structural) { void StructuralHooks::onSetPosition(Runtime *runtime, Structural *structural, const Common::Point &oldPt, Common::Point &pt) { } -void StructuralHooks::onStopPlayingMToon(Structural *structural, bool &visible, bool &stopped) { +void StructuralHooks::onStopPlayingMToon(Structural *structural, bool &visible, bool &stopped, Graphics::ManagedSurface *lastSurf) { } void StructuralHooks::onHidden(Structural *structural, bool &visible) { @@ -8447,6 +8447,9 @@ void VisualElement::handleDragMotion(Runtime *runtime, const Common::Point &init if (targetPoint.y > maxY) targetPoint.y = maxY; + if (_hooks) + _hooks->onSetPosition(runtime, this, Common::Point(_rect.left, _rect.top), targetPoint); + offsetTranslate(targetPoint.x - _rect.left, targetPoint.y - _rect.top, false); } } @@ -9398,7 +9401,7 @@ void VariableModifier::debugInspect(IDebugInspectionReport *report) const { Modifier::debugInspect(report); if (report->declareStatic("storage")) - report->declareStaticContents(Common::String::format("%p", (void *)_storage.get())); + report->declareStaticContents(Common::String::format("%p", static_cast(_storage.get()))); } #endif diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h index 32117380a6a..6129694b9e3 100644 --- a/engines/mtropolis/runtime.h +++ b/engines/mtropolis/runtime.h @@ -2128,7 +2128,7 @@ public: virtual void onCreate(Structural *structural); virtual void onPostActivate(Structural *structural); virtual void onSetPosition(Runtime *runtime, Structural *structural, const Common::Point &oldPt, Common::Point &pt); - virtual void onStopPlayingMToon(Structural *structural, bool &visible, bool &stopped); + virtual void onStopPlayingMToon(Structural *structural, bool &visible, bool &stopped, Graphics::ManagedSurface *lastSurf); virtual void onHidden(Structural *structural, bool &visible); };