Community

SCI Programming => SCI Syntax Help => Topic started by: Kawa on July 09, 2015, 11:08:10 AM

Title: SCI1.1: what in the flying hell is up with walking?
Post by: Kawa on July 09, 2015, 11:08:10 AM
This is complete horseshit.

I can interact with the car up to and including triggering EnterCarScript, to finally crash on trying to go a not-yet-existing room 120, but walking is completely broken -- I can't move beyond automatic approach, and clicking certain spots causes a crash. Perhaps as a hint, cycling through my verbs with the right mouse button gives a pointer as the last option before walk. That, of course, always crashes.

Code: [Select]
(version 2)
(include "sci.sh")
(include "Verbs.sh")
(include "game.sh")
(include "110.shm")
(include "110.shp")
(exports
0 rm110
)
(use "Main")
(use "DisposeLoad")
(use "Sound")
(use "Cycle")
(use "Game")
(use "Feature")
(use "View")
(use "Obj")
(use "Print")
(use "Polygon")

(script 110)

(local
lSaidNotToLeaveGreen = 0
lSaidNotToLeaveTeal = 0
)

(instance public rm110 of Rm
(properties
picture scriptNumber
style (| dpANIMATION_BLACKOUT dpOPEN_FADEPALETTE)
horizon 50
vanishingX 130
vanishingY 50
east 111
noun N_ROOM
)

(method (init)
AddPolygonsToRoom(@P_Default110)
(super:init())
SetUpEgo()
(switch (gPreviousRoomNumber)
(case east
(send gEgo:
posn(300 128)
loop(8)
cel(1)
)
)
(default
(send gEgo:
posn(150 120)
loop(8)
cel(2)
)
)
)

(aPuddle:init())
(aCar:init())

(send gEgo:init())
//(send gGame:handsOn(TRUE))
(if (not (== (send gSq5Music1: number) scriptNumber))
(send gSq5Music1: number(scriptNumber) loop(-1) play())
)
(if (not Btest(fDayOneStart))
Bset(fDayOneStart)
(send gEgo:get(0 1))
//(send gSq5IconBar:disable())
(self:setScript(IntroScript))
//(self:setScript(RoomScript))
)(else
(self:setScript(RoomScript))
)
)
)

(instance IntroScript of Script
(properties)

(method (changeState newState)
DebugPrint("IntroScript::changeState(%d)" newState)
(switch (= state newState)
(case 0
//Set Ego to play an animation of Ilira getting out of the car.
(send gEgo:view(13) loop(0) setCycle(End self))
//The setCycle(End self) bit does two things:
// ? makes the loop play once (because of the End cycler)
// ? makes End call a cue on IntroScript (self) when it's done
//End result: we switch to the next case when the animation's over.
)
(case 1
//Reset Ego, facing the car (west), and wait a bit
SetUpEgo()
//(send gEgo:view(0) loop(8) cel(1))
= seconds 2
)
(case 2
//Narrate, give the player control, and switch tracks to another script.
(send gTestMessager:say(0 0 0 1 0 scriptNumber))
//(send gGame:handsOn())
(send client:setScript(RoomScript))
//(rm110:setScript(RoomScript))
)
)
)
)

(instance RoomScript of Script
(properties)

(method (changeState newState)
DebugPrint("RoomScript::changeState(%d)" newState)
(switch (= state newState)
(case 0
DebugPrint("eech")
)
)
)

(method (doit)
(super:doit())
(if ((& (send gEgo:onControl()) ctlTEAL) and (== lSaidNotToLeaveTeal 0))
DebugPrint("Teal!")
(send gTestMessager:say(0 0 (if (Btest(fDayOneCarFixed)) C_FIXEDINTAKE)(else 0) 2 0 scriptNumber))
= lSaidNotToLeaveTeal 1
return
)
(if ((& (send gEgo:onControl()) ctlGREEN) and (== lSaidNotToLeaveGreen 0))
DebugPrint("Green!")
(send gTestMessager:say(0 0 (if (Btest(fDayOneCarFixed)) C_FIXEDINTAKE)(else 0) 3 0 scriptNumber))
= lSaidNotToLeaveGreen 1
return
)
)

(method (handleEvent pEvent)
DebugPrint("handleEvent $%x" (send pEvent:type))
(super:handleEvent(pEvent))
)
)

(instance EnterCarScript of Script
(properties)
(method (changeState newState)
(switch (= state newState)
(case 0
= seconds 1
)
(case 1
(send gTestMessager:say(N_CAR V_DO C_FIXEDINTAKE 1 0 scriptNumber))
(send gSq5Music2: number(8) loop(-1) play())
= seconds 4
)
(case 2
(send gTestMessager:say(N_CAR V_DO C_FIXEDINTAKE 2 0 scriptNumber))
= seconds 1
(send gSq5Music2: fade())
(send gGame:newRoom(120))
)
)
)
)
 
(instance aPuddle of Feature
(properties
//x 248
//y 65
nsLeft 80
nsTop 125
nsRight 125
nsBottom 133
sightAngle 40
approachX 128
approachY 126
_approachVerbs V_LOOK
noun N_PUDDLE
)

(method (doVerb theVerb)
(switch (theVerb)
(case V_LOOK
(send gTestMessager:say(N_PUDDLE V_LOOK (if (Btest(fDayOnePuddleChecked)) C_CHECKEDPUDDLE)(else 0) 1 0 scriptNumber))
Bset(fDayOnePuddleChecked)
)
(default
(super:doVerb(rest theVerb))
)
)
)
)

(instance aCar of Prop
(properties
view 111
loop 0
cel 0
x 114
y 128
approachX 128
approachY 126
_approachVerbs V_DO
noun N_CAR
signal (| fixPriOn ignAct)
priority 0
)

(method (init)
DebugPrint("aCar::init()")
(super:init())
)

(method (doVerb theVerb param2 param3)
DebugPrint("aCar::doVerb(%d %d %d" theVerb param2 param3)
(switch (theVerb)
(case V_DO
(if (not Btest(fDayOnePuddleChecked))
(send gTestMessager:say(N_CAR V_DO 0 1 0 scriptNumber))
)(else (if (not Btest(fDayOneCarFixed))
(send gTestMessager:say(N_CAR V_DO C_CHECKEDPUDDLE 1 0 scriptNumber))
//Show inset
DebugPrint("Pretending you fixed it now.")
Bset(fDayOneCarFixed)
)(else
(send gGame:handsOff())
(rm110:setScript(EnterCarScript))
))
)
(case V_TALK
(send gTestMessager:say(N_CAR V_TALK (if (Btest(fDayOneCarFixed)) C_FIXEDINTAKE)(else 0) 1 0 scriptNumber))
)
(default
(super:doVerb(rest theVerb))
)
)
)
)
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: troflip on July 09, 2015, 11:22:55 AM
Curious. I don't think anyone's going to notice anything by looking at the code, this probably has to be debugged to figure out (at least the crashes).

Why is there a pointer in your verb cursors? That is probably relevant, but does it only appear in that room?

Have you tried the ScummVM debugger? At the very least, it's easy to get a stack trace of the crash.
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: Kawa on July 09, 2015, 11:46:11 AM
I have no idea where the pointer came from, and I'll try ScummVM shortly. Thanks for that suggestion.

Edit: "signature mismatch in method ::export 13 (room 110, script 0, localCall 0x46f)", which is apparently caused by AddPolygonsToRoom(@P_Default110). Commenting that still won't let me walk. Also, 110 is the only room in the game besides the title screen and age check.
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: troflip on July 09, 2015, 12:26:01 PM
Hmm.... signature mismatch should refer to kernel calls. The only kernel call in that method is Memory, but that should be part of the error message. Assuming the kernel call *is* the problem, that must mean one of the parameters is wrong...

Hold on a sec... Why is the room crashing when it starts in ScummVM... you implied it was fine running in Sierra's interpreter.

Oh... it crashes for me too in ScummVM. arghh... I guess I never tried the polygon stuff in ScummVM (and indeed, it is the Memory call, you didn't post the entire error message).

Full error text:
Code: [Select]
parameter 0: 0000:0006 (integer), should be null, integer
parameter 1: 0014:0042 (reference), may be any (optional) (more may follow)
parameter 2: 0029:0066 (reference, invalid)
[VM] kMemory[72]: signature mismatch via method ::export 13 (room 110, script 0,
 localCall 0x408)!

Ok, this actually seems to be this code:
Code: [Select]
// Tell the caller the position of the next poly, if they care:
(if (> paramTotal 1)
Memory(memPOKE nextPoly (+ polyBuffer (+ 4 (* 4 pointCount))))
)

We're placing a pointer (which points *past* the local var buffer for room 110) into the address specified by nextPoly. Somehow, ScummVM knows this value is a pointer and not just a number (I have no idea how), and complains. Even though we will never actually read from this location. Hmmm....
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: Kawa on July 09, 2015, 12:37:06 PM
Did I imply that? I thought I rather explicitly said things weren't fine. And at any rate, the problems persist even without calling AddPolygonsToRoom().
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: troflip on July 09, 2015, 12:39:03 PM
Did I imply that? I thought I rather explicitly said things weren't fine. And at any rate, the problems persist even without calling AddPolygonsToRoom().

Well you described crashes and weird behavior that happened in that room, but that you could walk a bit and cycle through cursors. So presumably that means the room loaded, right? And it doesn't even load on ScummVM.

Comment out the AddPolygonsToRoom so it gets past that point in ScummVM, then debug the other crashes.
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: Kawa on July 09, 2015, 12:43:27 PM
"I can't move beyond automatic approach", as in the Walk cursor doesn't do anything, but interacting with the car and puddle does move Ego. Which isn't by very much considering both of these are close by eachother.

Updort: clicking Walk on Ego's bounding rect allows me to slowly shuffle to places. Interesting.
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: troflip on July 09, 2015, 01:03:35 PM
Well when you figure it out, let's see what we can do to prevent this from happening to others.
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: Cloudee1 on July 09, 2015, 02:09:47 PM
What are the Btest flag values that you have set... I don't know if it is related or not, but I just fought for an hour trying to figure out why I couldn't change rooms if I picked up a rock inventory item.

Turns out I was setting B flag of 224 at the time when I upped the players score... by default, 224 flag is too high. Are any of your bflags set higher than 223?

Just a shot in the dark here.
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: Kawa on July 09, 2015, 02:12:57 PM
What are the Btest flag values that you have set... I don't know if it is related or not, but I just fought for an hour trying to figure out why I couldn't change rooms if I picked up a rock inventory item.

Turns out I was setting B flag of 224 at the time when I upped the players score... by default, 224 flag is too high. Are any of your bflags set higher than 223?

Just a shot in the dark here.
Nice shot, but no. The flags in this room are #10 to 12.

At any rate, it might just be ill-informed hackjobs come back to bite me, so I started over with a full export. I'm focusing on the room right now, and so far so good.
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: lskovlun on July 09, 2015, 03:00:45 PM
We're placing a pointer (which points *past* the local var buffer for room 110) into the address specified by nextPoly. Somehow, ScummVM knows this value is a pointer and not just a number (I have no idea how  :)), and complains. Even though we will never actually read from this location. Hmmm....
I laughed at this... right, so it seems that the allow-any third parameter for Memory() doesn't actually let you through if there's an invalid pointer. Part of me wants to argue that this is correct behavior (fail fast) - on the other hand the lenient behavior would be consistent with how C++ iterators (for instance) work.
This kernel signature seems to work but I have not tested it broadly:
Code: [Select]
        { MAP_CALL(Memory),            SIG_EVERYWHERE,           "i(.)([!ir])", NULL,            kMemory_workarounds }, // subop
there are actually a few different ways to solve this. An easy one on the script side would be to always put a zero at the end of the polygon array, that way the pointer will be valid.
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: troflip on July 09, 2015, 03:07:09 PM
I mean, I can see the benefit of Scumm behaving this way. It alerts to a game doing something potentially incorrect. I don't think this merits any changes in Scumm.

Yeah, adding a zero is a clever alternative (although that requires people to update their game). I can also just re-work the code in those two functions to not need to do this. I'm using memPOKE just so I can return an additional value from that function in a parameter. But I can just as easily make the needed calculation in the calling function.
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: lskovlun on July 09, 2015, 03:14:06 PM
I mean, I can see the benefit of Scumm behaving this way. It alerts to a game doing something potentially incorrect. I don't think this merits any changes in Scumm.

Yeah, adding a zero is a clever alternative (although that requires people to update their game). I can also just re-work the code in those two functions to not need to do this. I'm using memPOKE just so I can return an additional value from that function in a parameter. But I can just as easily make the needed calculation in the calling function.
Too bad. I liked the approach of returning the next pointer via Memory().
Title: Re: SCI1.1: what in the flying hell is up with handsOn?
Post by: Kawa on July 09, 2015, 03:17:08 PM
Mmmm, technical investigations...

Anyway I've gotten to the point where all the interactions in the room are reimplemented and all that, and that leaves me with a hint as to where that pointer cursor came from. I or the template, but probably I, may be doing something wrong with the icon bar and handsOff/On.

The only place in rm110.sc right now where interactivity is manipulated is in rm110::init, near the end, just before playing the background music and setting the room script. The only other room that's been edited for now is the title screen, to remove a few states. I haven't even un-spaced the menu yet. In fact, besides the imagery, even the UI is untouched from template. What I'd like is to disallow user input while getting in and out of the car. So maybe I'll just...
Code: [Select]
(instance IntroScript of Script
(properties)
(method (changeState newState)
(switch (= state newState)
(case 0
(send gGame:handsOff())
(send gEgo:view(13) loop(0) setCycle(End self))
)
(case 1
(send gEgo:view(0) loop(8) cel(1) setCycle(Walk))
= seconds 4
)
(case 2
(send gTestMessager:say(0 0 0 1 0 scriptNumber))
(send gGame:handsOn())
(send client:setScript(RoomScript))
)
)
)
)
...Oh. When I do that, I get a dead walk cursor. Dead as in I can see it and move it around, but I can't actually walk, cycle verbs, or access the icon bar. My only in-engine way to get out is alt-D alt-X. But if I don't do that first bit, you can act while still getting out of the car. Hmm.
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: Cloudee1 on July 09, 2015, 03:45:44 PM
It's something else...

Using your code, I got the desired response (more or less). I had to change the intro ego view to 704 as I don't have a 13 at the moment and likewise the picture number to 0. Oh yeah, I also commented out the print statement. I put a setcycle fwd in the roomscript changestate just so I could visually see that it was reached.

Code: [Select]
(version 2)
(include "sci.sh")
(include "game.sh")
(include "110.shm")
(exports
    0 rm110
)
(use "Controls")
(use "Cycle")
(use "Feature")
(use "Game")
(use "Main")
(use "Obj")
(script 110)

(instance public rm110 of Rm
    (properties
        picture 0
        north 0
        east 0
        south 0
        west 0
        noun N_ROOM
    )

    (method (init)
        (super:init())
        (self:setScript(IntroScript))
        (switch (gPreviousRoomNumber)
            (default
                (send gEgo:
                    posn(150 100)
                    loop(1)
                )
            )
        )
        SetUpEgo()
        (send gEgo:init())
    )

)
(instance IntroScript of Script
(properties)
(method (changeState newState)
(switch (= state newState)
(case 0
(send gGame:handsOff())
(send gEgo:view(704) loop(0) setCycle(End self))
)
(case 1
(send gEgo:view(0) loop(8) cel(1) setCycle(Walk))
= seconds 4
)
(case 2
// (send gTestMessager:say(0 0 0 1 0 scriptNumber))
(send gGame:handsOn())
(send client:setScript(RoomScript))
)
)
)
)

(instance RoomScript of Script
    (properties)
    (method (changeState newState)
        = state newState
        (switch (state)
            (case 0
                (send gEgo:view(704) loop(0) setCycle(Fwd))
            )
        )
    )

)

The only thing that bugged me was that the introscript state 0 ego... never took on view 704. So I added a new case 0 with just a simple cycle call and numbered everything else accordingly. When ran, that gave a view error. Placing the setupego call to come before the previous room switch, took care of that... so in the end, this is what I had.

Code: [Select]
(version 2)
(include "sci.sh")
(include "game.sh")
(include "110.shm")
(exports
    0 rm110
)
(use "Controls")
(use "Cycle")
(use "Feature")
(use "Game")
(use "Main")
(use "Obj")
(script 110)

(instance public rm110 of Rm
    (properties
        picture 0
        north 0
        east 0
        south 0
        west 0
        noun N_ROOM
    )

    (method (init)
        (super:init())
        (self:setScript(IntroScript))
       
        SetUpEgo()
       
        (switch (gPreviousRoomNumber)
            (default
                (send gEgo:
                    posn(150 100)
                    loop(1)
                )
            )
        )
        (send gEgo:init())
    )

)
(instance IntroScript of Script
(properties)
(method (changeState newState)
(switch (= state newState)
(case 0 = cycles 5)
(case 1
(send gGame:handsOff())
(send gEgo:view(704) loop(0)setCycle(End self))
)
(case 2
(send gEgo:view(0) loop(8) cel(1) setCycle(Walk))
= seconds 4
)
(case 3
// (send gTestMessager:say(0 0 0 1 0 scriptNumber))
(send gGame:handsOn())
(send client:setScript(RoomScript))
)
)
)
)

(instance RoomScript of Script
    (properties)
    (method (changeState newState)
        = state newState
        (switch (state)
            (case 0
                (send gEgo:view(704) loop(0) setCycle(Fwd))
            )
        )
    )

)

and all was good.

Cursor disappears during handsOff and returns for handsOn, and is fully functional at that point.
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: Kawa on July 09, 2015, 04:08:20 PM
Turns out all that reorganizing wasn't it -- it was disabling the messager. That's what was messing up the handsOn!

The solution?
Code: [Select]
(instance IntroScript of Script
(properties)
(method (changeState newState)
(switch (= state newState)
(case 0
(send gGame:handsOff())
(send gEgo:view(13) loop(0) setCycle(End self))
)
(case 1
(send gEgo:view(0) loop(8) cel(1) setCycle(Walk))
= seconds 4
)
(case 2
(send gTestMessager:say(0 0 0 1 self scriptNumber))
//THAT! THAT'S IT! PASSING SELF TO THE MESSAGER!
)
(case 3
//AND NOW IT'S SAFE TO HANDSON!
(send gGame:handsOn())
(send client:setScript(RoomScript))
)
)
)
)
holycrap

Edit: copied rm110.sc into the backup I made that has all the neat UI edits and such and rebuilt. Can I have a "blammo"?
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: troflip on July 09, 2015, 04:35:22 PM
We'll need good documentation for the messeger::say method.

It looks like the say method returns immediately, meaning the subsequent code is executed right away. So if you want to wait until the message has disappeared or been dismissed, you need to make a new state and pass self in order to get cued to change to the next state.

The messager (actually the Talker) messes with enabling/disabling the icon bar when it's shown/hidden, so that probably conflicted with you changing handson while it was up.
Title: Re: SCI1.1: what in the flying hell is up with walking?
Post by: Kawa on July 09, 2015, 04:37:04 PM
It looks like the say method returns immediately, meaning the subsequent code is executed right away. So if you want to wait until the message has disappeared or been dismissed, you need to make a new state and pass self in order to get cued to change to the next state.

The messager (actually the Talker) messes with enabling/disabling the icon bar when it's shown/hidden, so that probably conflicted with you changing handson while it was up.
In the wise words of Krim Steinbelt: Exactly!