Opened 9 months ago

Closed 2 months ago

#10873 closed defect (wontfix)

QFG4 CD: Hero stutters when running

Reported by: Vhati Owned by: sluicebox
Priority: normal Component: Engine: SCI
Keywords: SCI32 Cc:
Game: Quest for Glory 4

Description

ScummVM 2.1.0git4278-gd31e37683c (Dec 13 2018 04:20:25)
Windows 7 64bit
QFG4 CD (English)

Hero runs funny, intermittently switching to a standing pose during movement. Sneaking and walking are affected, too.

It's most obvious in diagonal movement. Horizontal is mostly smooth.


In the CD edition's original interpreter, this manifests as lunges (suddenly covering more ground). No glimpses of the standing gait.

File - 5kb MD5 - Full MD5
RESOURCE.000 - 263dce4aa34c49d3ad29bec889007b1c - 1364ba69e3c0abb68cc0170650a56692
RESOURCE.AUD - c39521bffb1d8b19a57394866184a0ca - 71098b9e97e20c8941c0e4812d5f906f
RESOURCE.MAP - aba367f2102e81782d961b14fbe3d630 - 801a04cc6aa5d437681a2dd0b6545248
RESOURCE.SFX - 3cf95e09dab8b11d675e0537e18b499a - 7c858d7253f86dab4cc6066013c5ecec

Change History (6)

comment:1 by Vhati, 9 months ago

In the floppy edition under ScummVM, this manifests as pauses in the cycle. No glimpses of the standing gait.

In the floppy edition's original interpreter, this manifests as lunges, but they're so subtle as to not be a problem.


QFG4 Floppy 1.1a + note patch (English)

File - 5kb MD5 - Full MD5
RESOURCE.000 - f64fd6aa3977939a86ff30783dd677e1 - ff42260a665995a85aeb277ad80aac8a
RESOURCE.MAP - d10a4cc177d2091d744e2ad8c049b0ae - 3695b1b0a1d15f3d324ea9f0cc325245
RESOURCE.SFX - 3cf95e09dab8b11d675e0537e18b499a - 7c858d7253f86dab4cc6066013c5ecec

comment:2 by Vhati, 9 months ago

Quick and dirty way to reproduce.

  • Create a new character.
    • If non-rogue, put points in stealth (or cheat: vv g 255 300) to be able to sneak.
  • Teleport somewhere with lots of walkable space.
    • room 626 (castle hallway)
    • room 565 (forest 1S 1W from town)
  • From the verb bar, click the spiral icon, then run (1st icon) or sneak (2nd icon).
    • FOOT reverts to walking.
  • Just run around.



This reliably occurs at the far end of the castle hallway. In other rooms, I've seen it get pretty ridiculous sometimes.

Last edited 9 months ago by Vhati (previous) (diff)

comment:3 by Vhati, 9 months ago

"bp_write hero::cycler log" reports that the cycler is repeatedly being nulled and replaced.


Script 64977 - Grooper::doit()

# ...
(client
	cycler: 0
	mover: 0
	setMotion: 0
	setCycle: Grycler self temp0
)

I'm still unclear about Grooper's purpose. I looked further up the backtrace...


Floppy edition, script 64998 - Actor::doit()

(if script (script doit:))
(if code (code doit: self))
(if (& signal notUpd)
	(if viewer (viewer doit: self))
	(if avoider (avoider doit:))
	(if mover
		(if
		(and (& scaleSignal $0001) (not (& scaleSignal $0004)))
			(= temp5 (>> origStep $0008))
			(= temp6 (& origStep $00ff))
			(= temp3
				(if (= temp7 (/ (* temp5 scaleX) 128)) else 1)
			)
			(= temp4
				(if (= temp7 (/ (* temp6 scaleY) 128)) else 1)
			)
			(if (or (!= temp3 xStep) (!= temp4 yStep))
				(self setStep: temp3 temp4 1)
			)
		)
		(if mover (mover doit:))
	)
	(if scaler (scaler doit:))
	(if cycler
		(= temp1 brLeft)
		(= temp2 brRight)
		(cycler doit:)
		(cond 
			((not (& signal $0020)))
			(baseSetter (baseSetter doit: self))
			(else (BaseSetter self))
		)
	)
)
(= xLast x)
(= yLast y)
(if (and (& -info- $0008) (self isNotHidden:))
	(UpdateScreenItem self)
)



CD edition, script 64998 - Actor::doit()

(if robot (robot doit:))
(if script (script doit:))
(if code (code doit: self))
(if (& signal notUpd)
	(if viewer (viewer doit: self))
	(if avoider (avoider doit:))
	(if mover (mover doit:))
	(if cycler (cycler doit:))
	(if (& -info- $0008)
		(if scaler (scaler doit:))
		(= xLast x)
		(= yLast y)
		(if (self isNotHidden:) (UpdateScreenItem self))
		(if
			(and
				(& scaleSignal $0001)
				(not (& scaleSignal $0004))
				(!= scaleX oldScaleX)
			)
			(= oldScaleX scaleX)
			(= temp2
				(if
					(= temp4
						(>> (+ (* (>> origStep $0008) scaleX) 64) $0007)
					)
				else
					1
				)
			)
			(= temp3
				(if
					(= temp4
						(>> (+ (* (& origStep $00ff) scaleY) 64) $0007)
					)
				else
					1
				)
			)
			(if (or (!= temp2 xStep) (!= temp3 yStep))
				(self setStep: temp2 temp3 1)
			)
		)
		(cond 
			((not (& signal $0020)))
			(baseSetter (baseSetter doit: self))
			(else (BaseSetter self))
		)
	)
)



When the scaler changes hero's size, setStep() re-inits the mover creating a new PolyPath, setHeading(), etc.


script 64998 - Actor::setStep()

(= temp0 (>> origStep $0008))
(= temp1 (& origStep $00ff))
(if (and (>= argc 1) (!= param1 -1)) (= temp0 param1))
(if (and (>= argc 2) (!= param2 -1)) (= temp1 param2))
(if (or (< argc 3) (not param3))
	(= origStep (+ (<< temp0 $0008) temp1))
)
(= xStep temp0)
(= yStep temp1)
(if
	(and
		mover
		(or
			(mover isMemberOf: MoveTo)
			(mover isMemberOf: PolyPath)
		)
	)
	(mover init:)
)



"send hero scaleSignal 0"
Problem goes away.
"send hero scaleSignal 1"
Problem returns.


I built ScummVM with "./configure --enable-text-console" to get live debugger feedback in the status window. (Tip: To return to the game, gotta type "go" instead of escape.)

"bp_write hero::scaleY log"

Scaling definitely coincides with stuttering.

comment:4 by Vhati, 9 months ago

I haven't found exactly where the standing pose is coming from yet.

comment:5 by sluicebox, 3 months ago

This CD-only behavior is due to Sierra upgrading the Cycle classes to significantly different after they'd programmed thegame against the working ones they shipped in floppy. The stuttering, which bothers me, also occurs in the original.

The grooper/grycler crashes at the inn door and monolith are other symptoms, and so is the dial puzzle at the monolith which can't spin a full circle anymore because the Cycle classes no longer allow wrapping around from a high to low cel value.

https://github.com/scummvm/scummvm/commit/c1610a9fd1d07c3652509e673be6e111f55df623

A while ago I investigated the differences to see if I could just patch the new motion classes back to the old behavior and fix all this, but they're all radically different. It's not just the codepaths, the Game class fires things in different orders through different structures, events fire in greater magnitudes, and this is software malpractice that you don't need decades of hindsight to diagnose. GK1, a SCI32 contemporary which is a stable game without motion bugs, used the same classes as QFG4 floppy in all of its versions with no problems. Proof by example!

I say there's nothing to be done about this. I'll leave this open for a while before closing in case someone else has thoughts. It is indeed a bug! That it's a visible regression on every screen tells you how well the QFG4CD bug-stomping went.

comment:6 by sluicebox, 2 months ago

Owner: set to sluicebox
Resolution: wontfix
Status: newclosed
Note: See TracTickets for help on using tickets.