Logo Pending


Police Quest’s flashing siren lights

The flashing siren lights in the title screens for Police Quest 1 and 3 are sort of interesting, because they are not quite a simple matter of calling (Palette palANIMATE) once or twice. In fact it’s called eight times each frame! Here’s the final result:

And here’s the Script at the heart of it:

(instance cycleColors of Script
  (method (changeState newState)
    ; Fun fact: the switch isn't actually needed.
    ; Not in this use-case.
    (switch (= state newState)
      (0
        (Palette palANIMATE 208 213  1) ;blue in the middle
        (Palette palANIMATE 213 218  1)
        (Palette palANIMATE 218 223  1)
        (Palette palANIMATE 223 228  1) ;blue on the side
        ; Note that we're switching from 1 to -1 now.
        (Palette palANIMATE 229 234 -1) ;red in the middle
        (Palette palANIMATE 234 239 -1)
        (Palette palANIMATE 239 244 -1)
        (Palette palANIMATE 244 249 -1) ;red on the side
 
        ; Almost immediately do it all over again
        (= cycles 10000)
        (= state -1)
      )
    )
  )
)

The palette here has a very particular setup. The lowest colors, #208 to #249, are set up like this:

Each of the eight siren colors in the image has its own four-step palette, individually rotated! It looks kinda like this:

If that one black entry wasn’t in the way between blue and red, it’d line up better, but what can you do?

What’s particularly funny about this is of course that no SCI interpreter with fewer than 256 colors implements this feature.

The cycleColors script is still there and is still invoked. Just like with the chronostream animation in Space Quest 4.

[ , , , ] Leave a Comment

Sorry, Bonds – Police Quest 2 Copy Protection

Last for now in the set on copy protection is Police Quest 2. I might go into some others, I dunno, and I have something planned where I optimize the hell out of the PQ2 copy protection script by means of KQ4. But let’s get down to it.

(local
  [yourAnswer 40]
)
 
(procedure (ToUpper &tmp i ch)
  (= i 0)
  (while (= ch (StrAt @yourAnswer i))
    ; If ch is between 'a' and 'z'...
    (if (and (>= ch 97) (<= ch 122))
      ; ...change it to uppercase.
      (StrAt @yourAnswer i (- ch 32))
    )
    (++ i)
  )
)
 
(instance rm701 of Rm
  (method (doit &tmp myPick)
    (= myPick (& (GetTime gtTIME_OF_DAY) 7))
    (= yourAnswer 0)
 
    (Print "TO: Detective Bonds\n
            FROM: Captain Hall\n
            SUBJECT: ID of evidence photo\n
            \n
            Please provide the LAST name of the person pictured in
            the attached evidence photo for homicide case 186751.\n
            \n
            Please respond in box below, ASAP!\n"
            #icon 701 0 myPick
            #edit @yourAnswer 20
    )
 
    (= gQuit true)
    (ToUpper)
 
    ; Like in C, StrCmp returns zero if the strings are the same.
    ; Zero is false, so we use a not to make equal be true.
    (switch myPick
      (0    (if (not (StrCmp @yourAnswer "GRANANDEZ")) (= gQuit false)))
      (1    (if (not (StrCmp @yourAnswer "SIMMS"))     (= gQuit false)))
      (2    (if (not (StrCmp @yourAnswer "TASELLI"))   (= gQuit false)))
      (3    (if (not (StrCmp @yourAnswer "COLBY"))     (= gQuit false)))
      (4    (if (not (StrCmp @yourAnswer "BAINS"))     (= gQuit false)))
      (5    (if (not (StrCmp @yourAnswer "SNIDER"))    (= gQuit false)))
      (6    (if (not (StrCmp @yourAnswer "JONES"))     (= gQuit false)))
      (else (if (not (StrCmp @yourAnswer "DICKEY"))    (= gQuit false)))
    )
    (if gQuit
      (Print "Sorry Bonds, you'll need to do better than that!")
      ; With gQuit set, we'll exit at the end of this doit cycle.
    else
      (gGame restart:)
      ; The main game object can tell if we're restarting, so it'll
      ; put us in the first playable scene instead of the title screen.
    )
  )
)

Gee, I can think of a way to improve this already. Let’s turn yourAnswer from a local to a temp, and inline ToUpper:

(method (doit &tmp myPick i ch [yourAnswer 40])
  ; ...
  (= gQuit true)
 
  (= i 0)
  (while (= ch (StrAt @yourAnswer i))
    (if (and (>= ch 97) (<= ch 122))
      (StrAt @yourAnswer i (- ch 32))
    )
    (++ i)
  )
  ; ...
)

And that’s just one improvement. It really helps that, unlike the subtitle typing in Larry 5, we only uppercase one thing once. Tune in next time to see what could be done.

[ , , , ] 2 Comments on Sorry, Bonds – Police Quest 2 Copy Protection

On SCI Windows – Part 5 – Police Quest 4 but not

Police Quest IV – Open Season is an SCI2 game. As such, it had a radically different way of doing several things. It’s not too hard though to backport one of its elements, namely its translucent windows.

I’ve tweeted about this at length, and actually had to reimplement it all over again. But I did it.

(class TranslucentWindow of SysWindow
  (method (open &tmp oldPort screens scaleX scaleY)
    ; Your standard setup, KQ6 style...
    (= lsLeft (- left 1))
    (= lsRight (+ right 1))
    (= lsTop (- top 1))
    (= lsBottom (+ bottom 1))
 
    (= type 128)
    (= priority 15)
    (super open:)
 
    (= oldPort (GetPort))
    (SetPort 0)
    (= screens VISUAL)
    (if (!= priority -1) (= screens (| screens PRIORITY)))
 
    ; 128 is 100% of the source image size, which is 8x8.
    ; (128 / source) * target --> 16 * target.
    (= scaleX (* (- lsRight lsLeft) 16))
    (= scaleY (* (- lsBottom lsTop) 16))
    (DrawCel 923 1 0 lsLeft lsTop 15 scaleX scaleY)
 
    ; Draw the frame
    (Graph grDRAW_LINE lsTop lsLeft lsTop (- lsRight 1) 0 -1 -1)
    (Graph grDRAW_LINE (- lsBottom 1) lsLeft (- lsBottom 1) (- lsRight 1) 0 -1 -1)
    (Graph grDRAW_LINE lsTop lsLeft (- lsBottom 1) lsLeft 0 -1 -1)
    (Graph grDRAW_LINE lsTop (- lsRight 1) (- lsBottom 1) (- lsRight 1) 0 -1 -1)
 
    ; Show what we have wrought.
    (Graph grUPDATE_BOX (- lsTop 4) (- lsLeft 4) (+ lsBottom 4) (+ lsRight 4) 1)     
    (SetPort oldPort)
  )
)

You’ll also need to do something about DText, up in Interface.sc, or you’ll get ugly opaque text in a translucent window. I use my own extended interpreter so I get the drop shadow for free, but here’s the deal:

(class DText of DItem
  ; Rest of the class elided.
  (method (draw)
    ; We don't get to use hotspot rects anymore, sorry.
    (Display text dsFONT font dsCOORD nsTop nsLeft dsWIDTH (- nsRight nsLeft) dsCOLOR 7 dsBACKGROUND -1 dsALIGN mode)
  )
)

And yeah, the color’s pretty much fixed too — the DrawControl kernel call uses the current port’s colors, which would be the window’s. No such luck unless you significantly mess with things to not only add a color property to DText but also set it somehow while not actually invoking DText yourself so yeeeeaaah this might not be the window style for you.

[ , , ] Leave a Comment

Adventure game background art

Ah, Sierra. You gotta love the beautiful background art in their VGA games. From the cartoony…

…to the outright pretty…

…you have to admit someone was credit to team.

But then there’s games where they seemingly dropped the ball (in my opinion) for whatever style-related reason…

…or simply didn’t do much “background art” at all…

And that makes me feel…

Well, okay, I guess, about using edited Gmod screenshots from Letrune in “The Dating Pool”, turning this…

…into this:

[ , , , , , , ] Leave a Comment