Why it says only the last line? I need it to go as an usual .Say, one after another.
cChar.SayBackground("text1");
cChar.SayBackground("text2");
cChar.SayBackground("text3");
It's explained right there in the manual.
QuoteIf background speech is already on-screen for the character, it will be removed and replaced with the new MESSAGE.
What you need to do is check in repeatedly_execute if the previous message is still there and call the next message if it isn't.
There's a module for that though:
http://www.adventuregamestudio.co.uk/yabb/index.php?topic=23806.0
SayBackground is a non-blocking command, which means that while the first line is being spoken, the script keeps on going forward in the meantime. When it then stumbles across another line to be spoken, it 'overrides' the previous one. And so it will skip ahead through all the SayBackground lines until only the last one is left. So yeah, that's where that module comes in. :)
After installing module code should look like that?
cChar.SayQueued("text1");
cChar.SayQueued("text2");
cChar.SayQueued("text3");
But now it only says the first line and hangs there.
Where are you queuing the speech from? You never actually specified what function you're putting that code in.
From there it might also be relevant to try some basic debugging. The functions like QueuedSpeech.IsQueueEmpty, QueuedSpeech.GetCurrentIndex, or QueuedSpeech.GetItemCountInQueue might be useful to actually ensure that the items are being added to the queue and that it's running through the queue.
I wrote those AfterFadeIn.
EDIT: Well I found a work around.
Rep_Exec
(
Wait(20);
time++;
if (time==1) cChar.SayQueued("text1");
if (time==9) QueuedSpeech.ClearQueue();
if (time==10)cChar.SayQueued("text2");
if (time==19) QueuedSpeech.ClearQueue();
...........
)
How does blocking the game for half a second every second "work"?
That's not acceptable by any standard.
Not to mention the fact that if you're only adding a single item to the queue and then force-clearing it afterwards then you're not utilizing a queue at all and for that "method" you don't even need the module. Let me take a look and see if I can reproduce your problem though.. :-\
here is whole room1.asc
// room script file
function room_RepExec()
{
object[0].Move(movx, 480, 1, eNoBlock, eAnywhere);
Wait(5);
movx--;
if (movx==-2) cEren2.SayQueued("...One week has changed so much...");
if (movx==-19) QueuedSpeech.ClearQueue();
if (movx==-20)cEren2.SayQueued("");
if (movx==-39) QueuedSpeech.ClearQueue();
if (movx==-40)cEren2.SayQueued("It looks so peaceful and quiet from here.");
if (movx==-59) QueuedSpeech.ClearQueue();
if (movx==-60)cEren2.SayQueued("But down there is a real hell.");
if (movx==-79) QueuedSpeech.ClearQueue();
if (movx==-80)cEren2.SayQueued("");
if (movx==-99) QueuedSpeech.ClearQueue();
if (movx==-100)cEren2.SayQueued("...If only I wouldn't...");
if (movx==-119) QueuedSpeech.ClearQueue();
if (movx==-120)cEren2.SayQueued("No, it's too late...");
if (movx==-139) QueuedSpeech.ClearQueue();
if (movx==-140) cEren2.SayQueued("...To change one week, that became 20 years...");
if (movx==-159) QueuedSpeech.ClearQueue();
if (movx==-160)cEren2.SayQueued("");
if (movx==-179) QueuedSpeech.ClearQueue();
if (movx==-180)cEren2.SayQueued("It all started 20 years ago...");
if (movx==-209) QueuedSpeech.ClearQueue();
if (movx==-210){
FadeOut(1);
odate.Visible=true;
Wait(20);
FadeIn(1);
Wait(80);
FadeOut(1);
cEren.ChangeRoom(2, 160, 430);
}}
function room_AfterFadeIn()
{
}
function room_Load()
{
mouse.Visible=false;
cEren.Transparency=100;
odate.Visible=false;
}
Maybe I'm missing something.
Disregarding the current method you're using, if you're calling background speech commands based on some sort of timer, why use the module at all?
The original problem is gone and using Character.SayBackground should work fine.
It's the script how I use now ("fixed"). All speech used to be in AfterFadeIn section, but it's good as it is for now.
I don't mean this to be offensive, but you don't really seem to understand how scripting works. Just because you can put some code in and it seems to do what you want, doesn't mean you should rely on it working that way. Although your code might be working for this case, it's got a lot of overhead and is very error-prone, and potentially difficult to debug in the event an error did come up.
object[0].Move(movx, 480, 1, eNoBlock, eAnywhere);
Wait(5);
Seeing as this is the room script, there's no need to use the object array unless you're looping through the objects. It would make your code clearer if you used the object's script name instead of referencing it this way, even though they are both the same object. Also, you're calling Object.Move as a non-blocking call, but the immediately just forcing it to block by calling Wait. That doesn't really make any sense. Why not just make it a blocking movement?
oObject.Move(movx, 480, 1, eBlock, eAnywhere);
movx--;
if (movx == -2) { /* ... */ }
// ...
if (movx == -210) { /* ... */ }
So, I'm just assuming here that movx is initialized to 0 considering that it's obviously not a room-level object and must therefore be global. Of course that brings into question whether or not you even need movx to be global. Is it used by any other rooms? It seems like it serves a very specialized purpose for this room, so I don't know why it would be needed for other rooms. If it only has any meaning in this room, don't declare it as a global variable, declare it as a variable within the room script, at the top of the script, outside of any functions.
From there, you're decrementing the variable to -210. Although it doesn't really make any difference whatsoever, it is more conventional to increment temporary variables in situations like these. However, you are also using that variable to position an object, so that's fine here.
But wait, are you really moving an object to have it's X position at -210? Unless this is a rather wide object and it's moving off-screen, then I don't understand what you're trying to accomplish here. So while there is a conceivable case under which this would actually be a viable way of accomplishing what you want, it seems more likely that this isn't the case. You should be careful about doing this, because under most normal circumstances this is not what you should be doing.
Also, this is the point at which you're adding an item to a queue and then clearing it out before a single other item is added. Doesn't that occur to you as defeating the purpose of a queue??
Oh, and I should also point out that you're checking the value of movx 21 times every time that your room's rep exec function actually runs (which since you're blocking it 5/40 times per second, amounts to 168 times per second). That should be the worst-case scenario. That's the reason you use else if. Best-case scenario here it should only have to check the value of movx once, but you are running the worst-case scenario every game loop. That's ridiculous.
movx--;
if (movx == -2) { /* ... */ }
// ...
else if (movx == -209) { /* ... */ }
else if (movx == -210) { /* ... */ }
if (movx == -210) {
FadeOut(1);
odate.Visible = true;
Wait(20);
FadeIn(1);
Wait(80);
FadeOut(1);
cEren.ChangeRoom(2, 160, 430);
}
}
So once movx is finally set to -210 (26.25 seconds after the room's rep exec function starts), you fade out as slowly as possible, turn an object on, wait an additional half a second, fade back in as slowly as possible, wait two seconds, and then fade out as slowly as possible, before sending the character to the next room.
There's not really anything necessarily wrong with the way this is scripted, but as a player I would actually find it infuriating to have to sit through this. I would recommend making it a skippable cutscene (at the very least the fade in/out bit).
Beyond that I could also comment on your indentation which is inconsistent and makes your code harder to read, and harder to debug. The purpose of indentation is so you know what commands are nested within what functions, what conditions, what loops, and so forth. If your indentation is inconsistent, then you can't, at-a-glance, tell as readily any of this information. Inconsistency in indentation is the same as not using any indentation at all. It defeats the purpose entirely.
Furthermore, I tried to edit my post earlier, but apparently it didn't save my edit. The proper way of using the module would be to do something like:
function room_AfterFadeIn()
{
player.SayQueued("text1");
player.SayQueued("text2");
player.SayQueued("text3");
}
That would say each of the commands in the specified order, one after the other. And it works fine. You said that it was hanging on the first line, but that means you were doing something else wrong. The module works as intended. Though it doesn't seem necessary due to your actual implementation.
I'm the best scripter ever ;D
Yes, I'm using an object, witch is wider that background and moves all the time.
I putted SayQueued to RepExec, because it didn't worked in room_Load with a code that i wrote in 4th message (only first line was shown). I thought only this way to get this working, by putting it to RepExep and using coordinates array as a timer. I putted "Wait" there, because object was moving too fast. Now I only need a button to skip a cutscene.
I guess I explained everything.
You haven't explained anything, you've tried to rationalize it. You're now also saying that you tried putting the function calls in room_Load as opposed to room_AfterFadeIn. Honestly I don't know how that would work considering that room_Load happens before the room is faded in..
But, hey, whatever works for you man.