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