Adding a real-time game clock to the status line

From SCI Wiki
Jump to: navigation, search

Ever wanted a clock displayed in your status bar like in King's Quest III? Well it's relatively simple. First we'll need to add an additional global variable to the Main script here:

Code:
	gTimeSeconds ; the seconds
	gTimeMinutes ; the minutes
	gTimeHours ; the hours


Add a variable named "gTimeTicks" before these variables like so:

Code:
	gTimeTicks
	gTimeSeconds ; the seconds
	gTimeMinutes ; the minutes
	gTimeHours ; the hours


The reason we need this extra variable is so we can have room to update the seconds counter on the clock, which is normally done within the if statement condition below:

Code:
	(if (!= gCurrentTime (= gCurrentTime (GetTime gtTIME_OF_DAY)))
		(if (>= (++ gTimeSeconds) 60)
			(= gTimeSeconds 0)
			(++ gTimeMinutes)
			(if (>= gTimeMinutes 60)
				(= gTimeMinutes 0)
				(++ gTimeHours)
			)
		)
	)


Change this block of code by adding an additional nested if statement utilizing the new gTimeTicks variable and adding "(SL:doit())" to each of the statements as expressed below. Also make sure to change the line "(if(>= ++gTimeSeconds 60)" to read "(if(>= gTimeSeconds 60)" instead or else it will increment the seconds counter by two instead of one. Now that the gTimeTicks variable is incremented in the if statement condition, the gTimeSeconds variable does not need to be incremented (within the condition).

Code:
	(if (!= gCurrentTime (= gCurrentTime (GetTime gtTIME_OF_DAY)))
	    (if (>= (++ gTimeTicks) 1)
	    	(= gTimeTicks 0)
	    	(++ gTimeSeconds)
	    	(SL doit:)
	    	(if (>= gTimeSeconds 60)
		    	(= gTimeSeconds 0)
	    		(++ gTimeMinutes)
	    		(SL doit:)
	    		(if (>= gTimeMinutes 60)
		    		(= gTimeMinutes 0)
	    			(++ gTimeHours)
	    			(SL doit:)
				)
			)
		)
	)


Now this new block of code will update the status line each time the seconds, minutes, and hours counter is updated. One more thing that is required is to go to the Initrooms script and scroll down to the doit method to the line that reads:

Code:
	(= gTimeSeconds 0)
	(= gTimeMinutes 0)
	(= gTimeHours 0)
	(= gEgoView 0)


Add "= gTimeTicks 0" like so:

Code:
	(= gTimeTicks 0)
	(= gTimeSeconds 0)
	(= gTimeMinutes 0)
	(= gTimeHours 0)
	(= gEgoView 0)


This will reset the clock each time the Initrooms script is called (each time the game is restarted from the beginning).

Almost done. There's still one more thing left to do. All this is for nothing if we can't see the actual clock on the status line. So we have to go back to the Main script and alter the statusCode instance to read:

Code:
(instance statusCode of Code
	(properties)
	(method (doit param1)
		(Format param1 {_Score: %d of %-3d_______Template Game______%02d:%02d:%02d_} gScore gMaxScore gTimeHours gTimeMinutes gTimeSeconds)
	)
)



You can move the lines around but I recommend keeping the clock to the right unless you're using a unicode font, otherwise every time the clock updates anything to the right of the clock will shift slightly to the left or right due to the font character widths being different each time.

NOTE: There is a slight bug worth noting, which doesn't impair the operation but is visually kind of jarring. When the seconds counter reaches 59 it does not go directly back to 0. It first updates to 60 and then suddenly within a split-second reverts to zero and the minute counter updates. The same thing happens with the minute counter reaches 60. I'm not sure of the workaround. If anyone else can figure out a way to fix this little glitch please update my code!