MTROPOLIS: Add hacks to handle several animations that are supposed to stay on-screen even though they've been removed

This commit is contained in:
elasota 2023-06-13 23:47:58 -04:00
parent 80a75d7236
commit 6c0a2ac382
4 changed files with 60 additions and 10 deletions

View File

@ -1583,6 +1583,9 @@ VThreadState MToonElement::stopPlayingTask(const StopPlayingTaskData &taskData)
taskData.runtime->sendMessageOnVThread(dispatch);
}
if (_hooks)
_hooks->onStopPlayingMToon(this, _visible, _isStopped);
return kVThreadReturn;
}

View File

@ -89,10 +89,10 @@ void ObsidianCorruptedAirTowerTransitionFix::onLoaded(Asset *asset, const Common
class ObsidianInventoryWindscreenHooks : public StructuralHooks {
public:
void onSetPosition(Runtime *runtime, Structural *structural, Common::Point &pt) override;
void onSetPosition(Runtime *runtime, Structural *structural, const Common::Point &oldPt, Common::Point &pt) override;
};
void ObsidianInventoryWindscreenHooks::onSetPosition(Runtime *runtime, Structural *structural, Common::Point &pt) {
void ObsidianInventoryWindscreenHooks::onSetPosition(Runtime *runtime, Structural *structural, const Common::Point &oldPt, Common::Point &pt) {
if (pt.y < 480) {
// Set direct to screen so it draws over cinematics
static_cast<VisualElement *>(structural)->setDirectToScreen(true);
@ -104,13 +104,13 @@ void ObsidianInventoryWindscreenHooks::onSetPosition(Runtime *runtime, Structura
class ObsidianSecurityFormWidescreenHooks : public StructuralHooks {
public:
void onSetPosition(Runtime *runtime, Structural *structural, Common::Point &pt) override;
void onSetPosition(Runtime *runtime, Structural *structural, const Common::Point &oldPt, Common::Point &pt) override;
private:
Common::Array<uint32> _hiddenCards;
};
void ObsidianSecurityFormWidescreenHooks::onSetPosition(Runtime *runtime, Structural *structural, Common::Point &pt) {
void ObsidianSecurityFormWidescreenHooks::onSetPosition(Runtime *runtime, Structural *structural, const Common::Point &oldPt, Common::Point &pt) {
bool cardVisibility = (pt.y > 480);
// Originally tried manipulating layer order but that's actually not a good solution because
@ -1023,16 +1023,51 @@ void addObsidianSaveMechanism(const MTropolisGameDescription &desc, Hacks &hacks
hacks.addSaveLoadMechanismHooks(mechanism);
}
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 onHidden(Structural *structural, bool &visible) override;
};
void MTIBuggyAnimationHooks::onSetPosition(Runtime *runtime, Structural *structural, const Common::Point &oldPt, Common::Point &pt) {
// Cancel out off-screen translation
if (pt.x < 0)
pt = oldPt;
}
void MTIBuggyAnimationHooks::onStopPlayingMToon(Structural *structural, bool &visible, bool &stopped) {
// Un-stop
visible = true;
stopped = false;
}
void MTIBuggyAnimationHooks::onHidden(Structural *structural, bool &visible) {
// Un-hide
visible = true;
}
class MTIStructuralHooks : public StructuralHooks {
public:
void onPostActivate(Structural *structural) override;
};
void MTIStructuralHooks::onPostActivate(Structural *structural) {
if (structural->getName() == "D15_0003.tun") {
const Common::String &name = structural->getName();
if (name == "D15_0003.tun") {
// Fix for intro not playing in Piggy's secret room. D15_0003.tun is on layer 7 but treasure layers are on top of it.
if (structural->isElement() && static_cast<Element *>(structural)->isVisual())
static_cast<VisualElement *>(structural)->setLayer(20);
} else if (name == "C01c0005.tun" || name == "C01c0005a.tun" || name == "A06_Xspot.tun" || name == "A08agp01.tun") {
// Several animations stop (which hides) and are moved off-screen when they stop, yet for some reason are supposed to
// continue to draw.
//
// Known cases:
// - Treasure map in Benbow (A06_Xspot.tun)
// - 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<StructuralHooks>(new MTIBuggyAnimationHooks()));
}
}

View File

@ -2979,7 +2979,13 @@ void StructuralHooks::onCreate(Structural *structural) {
void StructuralHooks::onPostActivate(Structural *structural) {
}
void StructuralHooks::onSetPosition(Runtime *runtime, Structural *structural, Common::Point &pt) {
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::onHidden(Structural *structural, bool &visible) {
}
ProjectPresentationSettings::ProjectPresentationSettings() : width(640), height(480), bitsPerPixel(8) {
@ -8121,6 +8127,10 @@ VThreadState VisualElement::consumeCommand(Runtime *runtime, const Common::Share
if (Event(EventIDs::kElementHide, 0).respondsTo(msg->getEvent())) {
if (_visible) {
_visible = false;
if (_hooks)
_hooks->onHidden(this, _visible);
runtime->setSceneGraphDirty();
}
@ -8559,7 +8569,7 @@ MiniscriptInstructionOutcome VisualElement::scriptSetPosition(MiniscriptThread *
Common::Point destPoint = value.getPoint();
if (_hooks)
_hooks->onSetPosition(thread->getRuntime(), this, destPoint);
_hooks->onSetPosition(thread->getRuntime(), this, Common::Point(_rect.left, _rect.top), destPoint);
int32 xDelta = destPoint.x - _rect.left;
int32 yDelta = destPoint.y - _rect.top;
@ -8582,7 +8592,7 @@ MiniscriptInstructionOutcome VisualElement::scriptSetPositionX(MiniscriptThread
Common::Point updatedPoint = Common::Point(asInteger, _rect.top);
if (_hooks)
_hooks->onSetPosition(thread->getRuntime(), this, updatedPoint);
_hooks->onSetPosition(thread->getRuntime(), this, Common::Point(_rect.left, _rect.top), updatedPoint);
int32 xDelta = updatedPoint.x - _rect.left;
int32 yDelta = updatedPoint.y - _rect.top;
@ -8599,7 +8609,7 @@ MiniscriptInstructionOutcome VisualElement::scriptSetPositionY(MiniscriptThread
Common::Point updatedPoint = Common::Point(_rect.left, asInteger);
if (_hooks)
_hooks->onSetPosition(thread->getRuntime(), this, updatedPoint);
_hooks->onSetPosition(thread->getRuntime(), this, Common::Point(_rect.left, _rect.top), updatedPoint);
int32 xDelta = updatedPoint.x - _rect.left;
int32 yDelta = updatedPoint.y - _rect.top;

View File

@ -2127,7 +2127,9 @@ public:
virtual void onCreate(Structural *structural);
virtual void onPostActivate(Structural *structural);
virtual void onSetPosition(Runtime *runtime, Structural *structural, Common::Point &pt);
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 onHidden(Structural *structural, bool &visible);
};
class Structural : public RuntimeObject, public IModifierContainer, public IMessageConsumer, public Debuggable {