[Scummvm-git-logs] scummvm master -> 97acf91d6dd9e2a20cb8d8e429e693cc5f6c8c12

elasota noreply at scummvm.org
Fri Jan 20 06:28:29 UTC 2023


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
97acf91d6d MTROPOLIS: Implement path motion modifier and fix white chroma key not working.


Commit: 97acf91d6dd9e2a20cb8d8e429e693cc5f6c8c12
    https://github.com/scummvm/scummvm/commit/97acf91d6dd9e2a20cb8d8e429e693cc5f6c8c12
Author: elasota (ejlasota at gmail.com)
Date: 2023-01-20T01:25:56-05:00

Commit Message:
MTROPOLIS: Implement path motion modifier and fix white chroma key not working.

Fixes the Obsidian bird poop easter egg.

Changed paths:
    engines/mtropolis/assets.cpp
    engines/mtropolis/assets.h
    engines/mtropolis/elements.cpp
    engines/mtropolis/modifiers.cpp
    engines/mtropolis/modifiers.h
    engines/mtropolis/runtime.cpp


diff --git a/engines/mtropolis/assets.cpp b/engines/mtropolis/assets.cpp
index af7ef3b68fe..658fc7513e5 100644
--- a/engines/mtropolis/assets.cpp
+++ b/engines/mtropolis/assets.cpp
@@ -787,12 +787,11 @@ const Common::Array<int> &MovieAsset::getDamagedFrames() const {
 }
 
 
-CachedImage::CachedImage() : _colorDepth(kColorDepthModeInvalid), _isOptimized(false) {
+CachedImage::CachedImage() : _colorDepth(kColorDepthModeInvalid) {
 }
 
 void CachedImage::resetSurface(ColorDepthMode colorDepth, const Common::SharedPtr<Graphics::ManagedSurface> &surface) {
 	_optimizedSurface.reset();
-	_isOptimized = false;
 
 	_colorDepth = colorDepth;
 	_surface = surface;
diff --git a/engines/mtropolis/assets.h b/engines/mtropolis/assets.h
index fa2ccc16890..2c076cad766 100644
--- a/engines/mtropolis/assets.h
+++ b/engines/mtropolis/assets.h
@@ -243,7 +243,6 @@ private:
 	Common::SharedPtr<Graphics::ManagedSurface> _optimizedSurface;
 
 	ColorDepthMode _colorDepth;
-	bool _isOptimized;
 };
 
 class ImageAsset : public Asset {
diff --git a/engines/mtropolis/elements.cpp b/engines/mtropolis/elements.cpp
index 512641d0658..35a9fc02ef9 100644
--- a/engines/mtropolis/elements.cpp
+++ b/engines/mtropolis/elements.cpp
@@ -1110,7 +1110,8 @@ void ImageElement::render(Window *window) {
 
 		if (inkMode == VisualElementRenderProperties::kInkModeBackgroundMatte || inkMode == VisualElementRenderProperties::kInkModeBackgroundTransparent) {
 			const ColorRGB8 transColorRGB8 = _renderProps.getBackColor();
-			uint32 transColor = optimized->format.ARGBToColor(255, transColorRGB8.r, transColorRGB8.g, transColorRGB8.b);
+			uint32 transColor = optimized->format.ARGBToColor(0, transColorRGB8.r, transColorRGB8.g, transColorRGB8.b);
+
 			window->getSurface()->transBlitFrom(*optimized, srcRect, destRect, transColor, false, 0, alpha);
 		} else if (inkMode == VisualElementRenderProperties::kInkModeDefault || inkMode == VisualElementRenderProperties::kInkModeCopy) {
 			if (alpha != 255) {
diff --git a/engines/mtropolis/modifiers.cpp b/engines/mtropolis/modifiers.cpp
index a48bd86a97e..a6f159dcd21 100644
--- a/engines/mtropolis/modifiers.cpp
+++ b/engines/mtropolis/modifiers.cpp
@@ -139,10 +139,10 @@ VThreadState BehaviorModifier::consumeMessage(Runtime *runtime, const Common::Sh
 			DisableTaskData *disableTask = runtime->getVThread().pushTask("BehaviorModifier::disableTask", this, &BehaviorModifier::disableTask);
 			disableTask->runtime = runtime;
 
-			SwitchTaskData *taskData = runtime->getVThread().pushTask("BehaviorModifier::switchTask", this, &BehaviorModifier::switchTask);
-			taskData->targetState = false;
-			taskData->eventID = EventIDs::kParentDisabled;
-			taskData->runtime = runtime;
+			SwitchTaskData *switchTask = runtime->getVThread().pushTask("BehaviorModifier::switchTask", this, &BehaviorModifier::switchTask);
+			switchTask->targetState = false;
+			switchTask->eventID = EventIDs::kParentDisabled;
+			switchTask->runtime = runtime;
 		}
 		if (_enableWhen.respondsTo(msg->getEvent())) {
 			SwitchTaskData *taskData = runtime->getVThread().pushTask("BehaviorModifier::switchTask", this, &BehaviorModifier::switchTask);
@@ -825,7 +825,14 @@ PathMotionModifier::PointDef::PointDef() : frame(0), useFrame(false) {
 
 PathMotionModifier::PathMotionModifier()
 	: _reverse(false), _loop(false), _alternate(false),
-	  _startAtBeginning(false), _frameDurationTimes10Million(0) {
+	  _startAtBeginning(false), _frameDurationDUSec(1), _isAlternatingDirection(false), _lastPointTimeDUSec(0), _currentPointIndex(0) {
+}
+
+PathMotionModifier::~PathMotionModifier() {
+	if (_scheduledEvent) {
+		_scheduledEvent->cancel();
+		_scheduledEvent.reset();
+	}
 }
 
 bool PathMotionModifier::load(ModifierLoaderContext &context, const Data::PathMotionModifier &data) {
@@ -840,7 +847,10 @@ bool PathMotionModifier::load(ModifierLoaderContext &context, const Data::PathMo
 	_alternate = ((data.flags & Data::PathMotionModifier::kFlagAlternate) != 0);
 	_startAtBeginning = ((data.flags & Data::PathMotionModifier::kFlagStartAtBeginning) != 0);
 
-	_frameDurationTimes10Million = data.frameDurationTimes10Million;
+	_frameDurationDUSec = data.frameDurationTimes10Million;
+
+	if (_frameDurationDUSec == 0)
+		_frameDurationDUSec = 1; // Maybe set this to 1/60?  It seems like subframe movement is possible though.
 
 	_points.resize(data.numPoints);
 
@@ -849,7 +859,7 @@ bool PathMotionModifier::load(ModifierLoaderContext &context, const Data::PathMo
 		PointDef &outPoint = _points[i];
 
 		outPoint.frame = inPoint.frame;
-		outPoint.useFrame = ((inPoint.frameFlags & Data::PathMotionModifier::PointDef::kFrameFlagPlaySequentially) != 0);
+		outPoint.useFrame = ((inPoint.frameFlags & Data::PathMotionModifier::PointDef::kFrameFlagPlaySequentially) == 0);
 		if (!inPoint.point.toScummVMPoint(outPoint.point))
 			return false;
 
@@ -870,33 +880,272 @@ bool PathMotionModifier::respondsToEvent(const Event &evt) const {
 }
 
 VThreadState PathMotionModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	if (_terminateWhen.respondsTo(msg->getEvent())) {
+		TerminateTaskData *terminateTask = runtime->getVThread().pushTask("PathMotionModifier::terminateTask", this, &PathMotionModifier::terminateTask);
+		terminateTask->runtime = runtime;
+
+		return kVThreadReturn;
+	}
 	if (_executeWhen.respondsTo(msg->getEvent())) {
-#ifdef MTROPOLIS_DEBUG_ENABLE
-		if (Debugger *debugger = runtime->debugGetDebugger())
-			debugger->notify(kDebugSeverityWarning, "Path motion modifier was supposed to execute, but this isn't implemented yet");
-#endif
+		ExecuteTaskData *executeTask = runtime->getVThread().pushTask("PathMotionModifier::executeTask", this, &PathMotionModifier::executeTask);
+		executeTask->runtime = runtime;
+
 		_incomingData = msg->getValue();
+		_triggerSource = msg->getSource();
 
 		return kVThreadReturn;
 	}
-	if (_terminateWhen.respondsTo(msg->getEvent())) {
-		disable(runtime);
+
+	return kVThreadReturn;
+}
+
+void PathMotionModifier::disable(Runtime *runtime) {
+	if (_scheduledEvent) {
+		_scheduledEvent->cancel();
+		_scheduledEvent.reset();
+	}
+}
+
+void PathMotionModifier::linkInternalReferences(ObjectLinkingScope *scope) {
+	for (PointDef &point : _points)
+		point.sendSpec.linkInternalReferences(scope);
+}
+
+void PathMotionModifier::visitInternalReferences(IStructuralReferenceVisitor *visitor) {
+	for (PointDef &point : _points)
+		point.sendSpec.visitInternalReferences(visitor);
+}
+
+VThreadState PathMotionModifier::executeTask(const ExecuteTaskData &taskData) {
+	if (_points.size() == 0)
+		return kVThreadError;
+
+	Runtime *runtime = taskData.runtime;
+
+	uint64 timeMSec = runtime->getPlayTime();
+
+	uint prevPointIndex = _currentPointIndex;
+	uint newPointIndex = _reverse ? _points.size() - 1 : 0;
+
+	_lastPointTimeDUSec = timeMSec * 10000u;
+	_isAlternatingDirection = false;
+
+	if (_scheduledEvent) {
+		_scheduledEvent->cancel();
+		_scheduledEvent.reset();
+	}
+
+	scheduleNextAdvance(runtime, _lastPointTimeDUSec);
+
+	ChangePointsTaskData *changePointsTask = runtime->getVThread().pushTask("PathMotionModifier::changePoints", this, &PathMotionModifier::changePointsTask);
+	changePointsTask->runtime = runtime;
+	changePointsTask->prevPoint = (_startAtBeginning ? prevPointIndex : newPointIndex);
+	changePointsTask->newPoint = newPointIndex;
+	changePointsTask->isTerminal = (_loop == false && _points.size() == 1);
+
+	SendMessageToParentTaskData *sendMessageToParentTask = runtime->getVThread().pushTask("PathMotionModifier::sendMessageToParent", this, &PathMotionModifier::sendMessageToParentTask);
+	sendMessageToParentTask->runtime = runtime;
+	sendMessageToParentTask->eventID = EventIDs::kMotionStarted;
+
+	return kVThreadReturn;
+}
+
+VThreadState PathMotionModifier::changePointsTask(const ChangePointsTaskData &taskData) {
+	Runtime *runtime = taskData.runtime;
+
+	_currentPointIndex = taskData.newPoint;
+
+	// TODO: Figure out if this is the correct order.  These are pushed tasks so order is reversed: We set position first,
+	// then set cel, then fire the message if any.  I don't think the cel or position change have side effects.
+	if (_points[_currentPointIndex].sendSpec.destination != kMessageDestNone) {
+		TriggerMessageTaskData *triggerMessageTask = runtime->getVThread().pushTask("PathMotionModifier::triggerMessage", this, &PathMotionModifier::triggerMessageTask);
+		triggerMessageTask->runtime = runtime;
+		triggerMessageTask->pointIndex = _currentPointIndex;
+	}
+
+	// However, we DO need to fire Motion Ended events BEFORE we fire the last point's message.
+	if (taskData.isTerminal) {
+		SendMessageToParentTaskData *sendToParentTask = runtime->getVThread().pushTask("PathMotionModifier::sendMessageToParent", this, &PathMotionModifier::sendMessageToParentTask);
+		sendToParentTask->runtime = runtime;
+		sendToParentTask->eventID = EventIDs::kMotionEnded;
+	}
+
+	if (_points[_currentPointIndex].useFrame) {
+		ChangeCelTaskData *changeCelTask = runtime->getVThread().pushTask("PathMotionModifier::changeCel", this, &PathMotionModifier::changeCelTask);
+		changeCelTask->runtime = runtime;
+		changeCelTask->pointIndex = _currentPointIndex;
+	}
+
+	Common::Point positionDelta = _points[taskData.newPoint].point - _points[taskData.prevPoint].point;
+	if (positionDelta != Common::Point(0, 0)) {
+		ChangePositionTaskData *changePositionTask = runtime->getVThread().pushTask("PathMotionModifier::changePosition", this, &PathMotionModifier::changePositionTask);
+		changePositionTask->runtime = runtime;
+		changePositionTask->positionDelta = positionDelta;
+	}
+
+	return kVThreadReturn;
+}
+
+VThreadState PathMotionModifier::triggerMessageTask(const TriggerMessageTaskData &taskData) {
+	_points[taskData.pointIndex].sendSpec.sendFromMessenger(taskData.runtime, this, _triggerSource.lock().get(), _incomingData, nullptr);
+
+	return kVThreadReturn;
+}
+
+VThreadState PathMotionModifier::sendMessageToParentTask(const SendMessageToParentTaskData &taskData) {
+	Structural *owner = this->findStructuralOwner();
+
+	if (owner) {
+		Common::SharedPtr<MessageProperties> props(new MessageProperties(Event(taskData.eventID, 0), DynamicValue(), this->getSelfReference()));
+		Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(props, owner, true, true, false));
+
+		// Send immediately
+		taskData.runtime->sendMessageOnVThread(dispatch);
+	}
+
+	return kVThreadReturn;
+}
+
+VThreadState PathMotionModifier::changeCelTask(const ChangeCelTaskData &taskData) {
+	if (_points[taskData.pointIndex].useFrame) {
+		Structural *structural = findStructuralOwner();
+
+		if (structural) {
+			MiniscriptThread thread(taskData.runtime, nullptr, nullptr, nullptr, this);
+			DynamicValueWriteProxy proxy;
+
+			MiniscriptInstructionOutcome writeRefOutcome = structural->writeRefAttribute(&thread, proxy, "cel");
+			if (writeRefOutcome == kMiniscriptInstructionOutcomeContinue) {
+				DynamicValue cel;
+				cel.setInt(_points[taskData.pointIndex].frame + 1);
+				(void) proxy.pod.ifc->write(&thread, cel, proxy.pod.objectRef, proxy.pod.ptrOrOffset);
+			}
+		}
+	}
+
+	return kVThreadReturn;
+}
+
+VThreadState PathMotionModifier::changePositionTask(const ChangePositionTaskData &taskData) {
+	Structural *structural = findStructuralOwner();
+
+	if (structural && structural->isElement() && static_cast<Element *>(structural)->isVisual()) {
+		VisualElement *visual = static_cast<VisualElement *>(structural);
+		VisualElement::OffsetTranslateTaskData *offsetTranslateTask = taskData.runtime->getVThread().pushTask("VisualElement::offsetTranslate", visual, &VisualElement::offsetTranslateTask);
+		offsetTranslateTask->dx = taskData.positionDelta.x;
+		offsetTranslateTask->dy = taskData.positionDelta.y;
+	}
+
+	return kVThreadReturn;
+}
+
+VThreadState PathMotionModifier::advanceFrameTask(const AdvanceFrameTaskData &taskData) {
+	// Check what the new time will be and if it's in the future.  This also handles the case where the current time was changed
+	// due to a triggered message re-executing the modifier: In that case, this will prevent any subframe advances that would have happened.
+	uint64 newTime = _lastPointTimeDUSec + _frameDurationDUSec;
+	if (newTime >= taskData.terminationTimeDUSec)
 		return kVThreadReturn;
+
+	_lastPointTimeDUSec = newTime;
+
+	bool isPlayingForward = (_reverse == _isAlternatingDirection);
+	bool isAtLastPoint = isPlayingForward ? (_currentPointIndex == _points.size() - 1) : (_currentPointIndex == 0);
+
+	if (isAtLastPoint) {
+		// If this isn't looping, we're done
+		if (_loop == false) {
+			if (_scheduledEvent) {
+				_scheduledEvent->cancel();
+				_scheduledEvent.reset();
+			}
+			return kVThreadReturn;
+		}
+
+		// Otherwise, check for alternation and trigger it
+		if (_alternate) {
+			isPlayingForward = !isPlayingForward;
+			_isAlternatingDirection = !_isAlternatingDirection;
+		}
 	}
 
+	uint prevPointIndex = _currentPointIndex;
+
+	// If the path only has one point, we still act like it's advancing, messages
+	uint nextPointIndex = 0;
+	if (isPlayingForward) {
+		nextPointIndex = _currentPointIndex + 1;
+		if (nextPointIndex > _points.size())
+			nextPointIndex = 0;
+	} else {
+		if (_currentPointIndex == 0)
+			nextPointIndex = _points.size() - 1;
+		else
+			nextPointIndex = _currentPointIndex - 1;
+	}
+
+	bool isTerminal = false;
+	if (!_loop) {
+		isTerminal = isPlayingForward ? (nextPointIndex == _points.size() - 1) : (nextPointIndex == 0);
+		if (isTerminal && _scheduledEvent) {
+			_scheduledEvent->cancel();
+			_scheduledEvent.reset();
+		}
+	}
+
+	// Push the next frame advance for this advancement
+	AdvanceFrameTaskData *advanceFrameTask = taskData.runtime->getVThread().pushTask("PathMotionModifier::advanceFrame", this, &PathMotionModifier::advanceFrameTask);
+	advanceFrameTask->runtime = taskData.runtime;
+	advanceFrameTask->terminationTimeDUSec = taskData.terminationTimeDUSec;
+
+	// Push this frame advance
+	ChangePointsTaskData *changePointsTask = taskData.runtime->getVThread().pushTask("PathMotionModifier::changePoints", this, &PathMotionModifier::changePointsTask);
+	changePointsTask->runtime = taskData.runtime;
+	changePointsTask->prevPoint = prevPointIndex;
+	changePointsTask->newPoint = nextPointIndex;
+	changePointsTask->isTerminal = isTerminal;
+
 	return kVThreadReturn;
 }
 
-void PathMotionModifier::disable(Runtime *runtime) {
-#ifdef MTROPOLIS_DEBUG_ENABLE
-	if (Debugger *debugger = runtime->debugGetDebugger())
-		debugger->notify(kDebugSeverityWarning, "Path motion modifier was supposed to terminate, but this isn't implemented yet");
-#endif
+void PathMotionModifier::scheduleNextAdvance(Runtime *runtime, uint64 startingFromTimeDUSec) {
+	assert(_scheduledEvent.get() == nullptr);
+
+	uint64 nextFrameTimeMSec = (startingFromTimeDUSec + _frameDurationDUSec + 9999u) / 10000u;
+	_scheduledEvent = runtime->getScheduler().scheduleMethod<PathMotionModifier, &PathMotionModifier::advance>(nextFrameTimeMSec, this);
+}
+
+void PathMotionModifier::advance(Runtime *runtime) {
+	_scheduledEvent.reset();
+
+	uint64 currentTimeDUSec = runtime->getPlayTime() * 10000u;
+
+	uint64 framesToAdvance = (currentTimeDUSec - _lastPointTimeDUSec) / _frameDurationDUSec;
+	uint64 nextFrameDUSec = _lastPointTimeDUSec + framesToAdvance * _frameDurationDUSec;
+
+	// Schedule the next advance now, since the advance may be cancelled by a message triggered by one of the advances
+	scheduleNextAdvance(runtime, nextFrameDUSec);
+
+	AdvanceFrameTaskData *advanceFrameTask = runtime->getVThread().pushTask("PathMotionModifier::advanceFrame", this, &PathMotionModifier::advanceFrameTask);
+	advanceFrameTask->runtime = runtime;
+	advanceFrameTask->terminationTimeDUSec = currentTimeDUSec;
+}
+
+VThreadState PathMotionModifier::terminateTask(const TerminateTaskData &taskData) {
+	if (_scheduledEvent) {
+		SendMessageToParentTaskData *sendToParentTask = taskData.runtime->getVThread().pushTask("PathMotionModifier::endMotion", this, &PathMotionModifier::sendMessageToParentTask);
+		sendToParentTask->runtime = taskData.runtime;
+		sendToParentTask->eventID = EventIDs::kMotionEnded;
+	}
+
+	disable(taskData.runtime);
+
+	return kVThreadReturn;
 }
 
 Common::SharedPtr<Modifier> PathMotionModifier::shallowClone() const {
 	Common::SharedPtr<PathMotionModifier> clone(new PathMotionModifier(*this));
 	clone->_incomingData = DynamicValue();
+	clone->_scheduledEvent.reset();
 	return clone;
 }
 
@@ -904,7 +1153,6 @@ const char *PathMotionModifier::getDefaultName() const {
 	return "Path Motion Modifier";
 }
 
-
 SimpleMotionModifier::SimpleMotionModifier() : _motionType(kMotionTypeIntoScene), _directionFlags(0), _steps(0), _delayMSecTimes4800(0) {
 }
 
diff --git a/engines/mtropolis/modifiers.h b/engines/mtropolis/modifiers.h
index d6f1ee2ee1f..ab1f6cd24c0 100644
--- a/engines/mtropolis/modifiers.h
+++ b/engines/mtropolis/modifiers.h
@@ -353,6 +353,7 @@ private:
 class PathMotionModifier : public Modifier {
 public:
 	PathMotionModifier();
+	~PathMotionModifier();
 
 	bool load(ModifierLoaderContext &context, const Data::PathMotionModifier &data);
 
@@ -360,6 +361,9 @@ public:
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
 	void disable(Runtime *runtime) override;
 
+	void linkInternalReferences(ObjectLinkingScope *scope) override;
+	void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Path Motion Modifier"; }
 	SupportStatus debugGetSupportStatus() const override { return kSupportStatusPartial; }
@@ -376,6 +380,74 @@ private:
 		MessengerSendSpec sendSpec;
 	};
 
+	struct ExecuteTaskData {
+		ExecuteTaskData() : runtime(nullptr) {}
+
+		Runtime *runtime;
+	};
+
+	struct TerminateTaskData {
+		TerminateTaskData() : runtime(nullptr) {}
+
+		Runtime *runtime;
+	};
+
+	struct ChangePointsTaskData {
+		ChangePointsTaskData() : runtime(nullptr), prevPoint(0), newPoint(0), isTerminal(false) {}
+
+		Runtime *runtime;
+		uint prevPoint;
+		uint newPoint;
+		bool isTerminal;
+	};
+
+	struct TriggerMessageTaskData {
+		TriggerMessageTaskData() : runtime(nullptr), pointIndex(0) {}
+
+		Runtime *runtime;
+		uint pointIndex;
+	};
+
+	struct SendMessageToParentTaskData {
+		SendMessageToParentTaskData() : runtime(nullptr), eventID(EventIDs::kNothing) {}
+
+		Runtime *runtime;
+		EventIDs::EventID eventID;
+	};
+
+	struct ChangeCelTaskData {
+		ChangeCelTaskData() : runtime(nullptr), pointIndex(0) {}
+
+		Runtime *runtime;
+		uint pointIndex;
+	};
+
+	struct ChangePositionTaskData {
+		ChangePositionTaskData() : runtime(nullptr) {}
+
+		Runtime *runtime;
+		Common::Point positionDelta;
+	};
+
+	struct AdvanceFrameTaskData {
+		AdvanceFrameTaskData() : runtime(nullptr), terminationTimeDUSec(0) {}
+
+		Runtime *runtime;
+		uint64 terminationTimeDUSec;
+	};
+
+	VThreadState executeTask(const ExecuteTaskData &taskData);
+	VThreadState terminateTask(const TerminateTaskData &taskData);
+	VThreadState changePointsTask(const ChangePointsTaskData &taskData);
+	VThreadState triggerMessageTask(const TriggerMessageTaskData &taskData);
+	VThreadState sendMessageToParentTask(const SendMessageToParentTaskData &taskData);
+	VThreadState changeCelTask(const ChangeCelTaskData &taskData);
+	VThreadState changePositionTask(const ChangePositionTaskData &taskData);
+	VThreadState advanceFrameTask(const AdvanceFrameTaskData &taskData);
+
+	void scheduleNextAdvance(Runtime *runtime, uint64 startingFromTimeDUSec);
+	void advance(Runtime *runtime);
+
 	Common::SharedPtr<Modifier> shallowClone() const override;
 	const char *getDefaultName() const override;
 
@@ -387,11 +459,17 @@ private:
 	bool _alternate;
 	bool _startAtBeginning;
 
-	uint32 _frameDurationTimes10Million;
+	uint64 _frameDurationDUSec;
 
 	Common::Array<PointDef> _points;
 
 	DynamicValue _incomingData;
+
+	Common::WeakPtr<RuntimeObject> _triggerSource;
+	Common::SharedPtr<ScheduledEvent> _scheduledEvent;
+	bool _isAlternatingDirection;
+	uint _currentPointIndex;
+	uint64 _lastPointTimeDUSec;
 };
 
 class SimpleMotionModifier : public Modifier {
diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index 92235ba1687..1bf6bb88f23 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -5237,6 +5237,12 @@ void Runtime::loadScene(const Common::SharedPtr<Structural>& scene) {
 }
 
 void Runtime::sendMessageOnVThread(const Common::SharedPtr<MessageDispatch> &dispatch) {
+	EventIDs::EventID eventID = dispatch->getMsg()->getEvent().eventType;
+
+	// 0 is normally not produced and is invalid, 1 is "None" and is an invalid message
+	if (eventID == 1 || eventID == 0)
+		return;
+
 #ifndef DISABLE_TEXT_CONSOLE
 	const int msgDebugLevel = 3;
 
@@ -5315,7 +5321,7 @@ void Runtime::sendMessageOnVThread(const Common::SharedPtr<MessageDispatch> &dis
 				break;
 
 			case EventIDs::kMotionStarted:
-				extType = "Motion Ended";
+				extType = "Motion Started";
 				break;
 			case EventIDs::kMotionEnded:
 				extType = "Motion Started";




More information about the Scummvm-git-logs mailing list