On 27 Nov 2006, at 20:22, Alban Bedel wrote:



A crucial element of conversations seems to be the saveRestoreVerbs
op-code, which is exposed as three functions in SCUMMC:

saveVerbs(saveID, start, end)
    Sets saveid for each verb from start -> end, where saveid == 0
restoreVerbs(saveID, start, end)
    Sets saveid to 0 for each verb from start -> end, where saveid ==
saveID. Any verbs where saveid is already 0 are killed.
deleteVerbs(saveID, start, end)
    Kills verbs from start -> end where saveid == saveID.

(Note that in all cases, start and end are indexes in the verb list)

Hmm, are you sure of the argument order ? From the ScummVM code
(script_v6.cpp:o6_saveRestoreVerbs) it seems the saveID come last
and not first.

Yes. The args get popped in the order:
   c b a
I would assume scummc pushes the args in the order:
   a b c

a being the start, b being the end, and c being the id, which would make sense. Plus of course it works :)


This function is called a few times before and after conversations. I
haven't seen it being called during conversations, so i can only
assume that all the conversation items must be plonked on all at once.

How does this work in a conversation? well its rather simple.

To start off with, you'll want to remove all the verbs on the screen,
which can be done in the road demo by calling :
    saveVerbs(1, SntcLine, Pull);
(I assumed SntcLine was the first verb, and Pull was the last. This
should of course be changed if this is not the case).

Again one need to somewhat group verbs together. Currently one can just enforce the addresses (like with the inventory verbs in road), but it would probably be better to have some construct to tell the linker that a given
group of symbol need consecutive addresses. Any suggestion for a nice
syntax to represent that is welcome.

I was thinking of plonking the verb's in an array, but then again I have no idea if that would work. And even if it did work, I don't know how the compiler treats array values, so unnecessary overhead could be incurred.

I tried implementing a working example of my conversation script idea. I was able to hide all of the normal verbs (as mentioned previously), but I had a little problem when restoring them after exiting the conversation. Seems I forgot the range needed to include the added conversation verbs for them to be killed. Though this problem could be solved by making another call to restoreVerbs with the additional range:

restoreVerbs(1, Conv1, Conv3);

Though a cleaner solution would perhaps be to order the verbs accordingly so one can wipe out all the conversation verbs in one go, along with restoring the normal verbs. Or you could just call deleteVerbs() instead.

For my test though, I just killed them manually - very ugly! i.e.:
setCurrentVerb(Conv1);
killVerb();
// Repeat for each conversation verb

I agree though that it would be nice to have some way of ensuring the order of the verb's. How about adding an "ordered" keyword, which would order all variables in the statement? e.g.:

ordered verb verb1, verb2, verb3, verb4;

Though in my experience, if you just specify verb's in order in the source file, they should be ordered auto-magically, so that would likely be redundant.

Anyhow to summarise, for my conversation test I first added these verbs (common.sch):

// Conversation items
verb con1, con2, con3;

Then i modified the LookAt case for the river object:

        case LookAt:
            cutscene() {
                egoSay("Wa _ Water ??\wI hate that stuff.");
                waitForMessage();
                ResRoom::hideVerbs();
                egoSay("Now i'm going to test some conversation verbs");

                if (!looked)
                {
                setCurrentVerb(con1);
                initVerb();
                setVerbName("Selection 1");
                setVerbXY(10,146);
                setVerbColor(6);
                setVerbHiColor(8);
                setVerbDimColor(2);
                setVerbOn();
                redrawVerb();

                setCurrentVerb(con2);
                initVerb();
                setVerbName("Selection 2");
                setVerbXY(10,160);
                setVerbColor(6);
                setVerbHiColor(8);
                setVerbDimColor(2);
                setVerbOn();
                redrawVerb();

                setCurrentVerb(con3);
                initVerb();
                setVerbName("Selection 3");
                setVerbXY(10,176);
                setVerbColor(6);
                setVerbHiColor(8);
                setVerbDimColor(2);
                setVerbOn();
                redrawVerb();
                }

                waitForMessage();

                //setVerbKey('p');
                //ResRoom::showHiddenVerbs();
            }

Then i added these cases to the defaultAction script:

        case con1:
            egoSay("Bla Bla Bla 1");
        break;
        case con2:
            egoSay("Bla Bla Bla 2");
        break;
        case con3:
            egoSay("Bla Bla Bla 3. Exit.");
            exitConversation();
        break;

Then I had to add a little shortcircuit in the inputHandler script, just after the "a verb was clicked" block:

// Conversation item clicked, which means we can get right to the action.
        if (isAnyOf(cmd, [ con1, con2, con3 ] )) {
                        defaultAction(cmd, 0, 0);
                        return;
        }

Oh, and I also added these helper script's in ResRoom:

    script showHiddenVerbs()
    {
       restoreVerbs(1, SntcLine, Pull);
    }

    script hideVerbs()
    {
       saveVerbs(1, SntcLine, Pull); // SntcLine -> Pull
    }

    script exitConversation() {
                // Hack Hack
                setCurrentVerb(con1);
                killVerb();
                setCurrentVerb(con2);
                killVerb();
                setCurrentVerb(con3);
                killVerb();
                restoreVerbs(1, SntcLine, Pull);
                
    }

To get this to work, just look at the river. The screen should enter into a conversation mode. If you want to exit, just choose the third option. I still haven't decided upon how to handle scrolling conversation items, or items which disappear after you have clicked on them. I could either shift the positions of the verbs, or hide the last verb and shift the text up. Or perhaps i could make use of additional scumm functionality i haven't discovered yet. Decisions, Decisions....

Also, the verb click handling is a bit messy. A better idea would be to change the VAR_VERB_SCRIPT variable to point to a custom conversation handler script. Then there's the issue of the font. At the moment the regular verb text is used, so the conversation options take up more space than they should.

Finally, I should also point out that one doesn't necessarily have to kill the conversation verb's. You could assign them another id and make them vanish, then restore them later as usual, i.e.:

// Create the conversation verb's
// ...
// Save the conversation verb's for later
saveVerbs(2, Conv1, Conv3);

// ...

// Enter conversation
saveVerbs(1, SntcLine, Pull);
restoreVerbs(2, Conv1, Conv3);

// Exit conversation
saveVerbs(2, Conv1, Conv3);
restoreVerbs(1, SntcLine, Pull);

There's so many ways to do things, its almost mind boggling!
Anyhow, i hope this helps anyone who wants to add conversations to their scumm game.

-SJU





_______________________________________________
ScummC-general mailing list
[email protected]
https://mail.gna.org/listinfo/scummc-general

Reply via email to