please look at next comment about explanation.
// script code
list Trigger = [];
list Gesture = [];
list Item = ["Chat","Wait","Sound","AnimStart","AnimStop"];
list Link = [];
list Type = [];
list Name = [];
integer Listen1 = 0;
integer Listen2 = 0;
integer Channel1 = 0;
integer Channel2 = 0;
integer Finish = FALSE;
integer Preload = TRUE;
integer Begin = 0;
integer End =0;
integer Count = 0;
integer NoteLine = 0;
string NoteName = "";
integer NoteIndex = 0;
string BackButton = "! << BACK ! ,";
string NextButton = "! NEXT >> ! ,";
Say(integer enable,string data)
{
if(enable)
llOwnerSay(data);
}
list GetList(integer begin, integer end)
{
list List = [];
integer Length = llGetListLength(Gesture);
if(end > Length)
end = Length;
integer i = 0;
for(i = begin; i < end; i++)
List = llListInsertList(List, [llList2String(Gesture, i)], i);
return List ;
}
PlayList(integer start, integer stop)
{
integer i = start;
for(i = start; i < stop; i++)
{
integer Index = (integer)llList2String(Type, i);
if(Index == 0)
llSay(0,llList2String(Name, i));
else if(Index == 1)
llSleep((float)llList2String(Name, i));
else if(Index == 2)
llPlaySound(llList2String(Name, i),1);
else if(Index == 3)
llStartAnimation(llList2String(Name, i));
else if(Index == 4)
llStopAnimation(llList2String(Name, i));
}
}
Play(integer index)
{
Say(!Finish,"load notecard...ok"

integer Start = 0;
integer Stop = 0;
integer i = 0;
if(index == -1)
Stop = llGetListLength(Type);
else
{
list List = llCSV2List(llList2String(Link,index));
Start = (integer)llList2String(List,0);
Stop = (integer)llList2String(List,1);
i = Start;
}
if(Preload)
{
Say(!Finish,"cashing sound..."

for(i = Start; i < Stop; i++)
{
integer Index = (integer)llList2String(Type, i);
if(index == 2)
llPreloadSound(llList2String(Name, i));
}
Say(!Finish,"cashing sound...ok"

}
Say(!Finish,"test playing..."

PlayList(Start, Stop);
Say(!Finish,"test playing...ok"

}
Reset(integer enable)
{
if(enable)
{
Trigger = [];
Gesture = [];
Type = [];
Name = [];
Count = 0;
NoteLine = 0;
NoteName = "";
NoteIndex = 0;
}
Channel1 = (integer)llFrand(123456789);
if(Channel1 < 10000)
Channel1 = Channel1 + 10000;
Channel2 = Channel1 + 1;
llListenRemove(Listen1);
llListenRemove(Listen2);
Listen2 = llListen(0, "", llGetOwner(), ""

llResetTime();
llSetTimerEvent(0.0);
llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION);
integer Length = llGetInventoryNumber(INVENTORY_NOTECARD);
integer i = 0;
if(enable)
{
for(i = 0; i < Length; i++)
{
list List = llCSV2List(llGetInventoryName(INVENTORY_NOTECARD, i));
if(llGetListLength(List) == 2)
{
Trigger = llListInsertList(Trigger, [llList2String(List,1)], i);
Gesture = llListInsertList(Gesture, [llList2String(List,0)], i);
}
else
{
Trigger = llListInsertList(Trigger, [""], i);
Gesture = llListInsertList(Gesture, [llGetInventoryName(INVENTORY_NOTECARD, i)], i);
}
}
Say(!Finish,"reset script...ok"

}
}
NoteCard(list List, string data)
{
integer Index = llListFindList(List,[data]);
if(Index != -1)
{
if(!Finish)
{
Count = 0;
NoteLine = 0;
NoteName = llList2String(Gesture, Index);
if(llList2String(Trigger, Index) != ""

NoteName = NoteName + "," + llList2String(Trigger, Index);
Type = [];
Name = [];
Say(!Finish,"load notecard..."

llGetNotecardLine(NoteName, NoteLine);
}
else
Play(Index);
}
}
Menu(key id)
{
integer Back = 0;
integer Next = llGetListLength(Gesture);
if(Next == 0)
{
llListenRemove(Listen1);
llDialog(llGetOwner(), "there is no notecard", [], Channel1);
return;
}
if(Next > 9)
Next = 9;
list List = GetList(Back,Next);
if(Next == 9 || Next < 9)
Next = 0;
if(llGetListLength(Gesture) > 9)
Next = 9;
string BACK = BackButton + (string)Back;
string NEXT = NextButton + (string)Next;
llListenRemove(Listen1);
Listen1 = llListen(Channel2, "", llGetOwner(), ""

llDialog(llGetOwner(), "select nortcard", [BACK, llList2String(["MENU","-"], Finish), NEXT] + List, Channel2);
}
Dialog(key id)
{
llListenRemove(Listen1);
Listen1 = llListen(Channel1, "", llGetOwner(), ""

string Data = "[x]Preload";
if(!Preload)
Data = "[-]Preload";
llDialog(llGetOwner(), "main menu", ["Reset", "Note", "Finalize", Data], Channel1);
}
default
{
on_rez(integer i)
{
Reset(FALSE);
}
touch_start(integer i)
{
if(!Finish)
Dialog(llDetectedKey(i));
else
Menu(llDetectedKey(i));
}
state_entry()
{
Reset(TRUE);
}
dataserver(key id, string data)
{
if(data != EOF)
{
list List = llCSV2List(data);
if(llGetListLength(List) == 2)
{
integer Check = llListFindList(Item,[llList2String(List,0)]);
if(Check != -1)
{
Type = llListInsertList(Type, [(string)Check], Count);
Name = llListInsertList(Name, [llList2String(List,1)], Count);
Count ++;
End ++;
}
}
NoteLine ++;
llGetNotecardLine(NoteName, NoteLine);
}
else
{
if(!Finish)
Play(-1);
else
{
Link = llListInsertList(Link, [(string)Begin + "," + (string)End], NoteIndex);
Begin = End;
NoteLine = 0;
NoteIndex ++;
if(NoteIndex < llGetListLength(Gesture))
{
NoteName = llList2String(Gesture, NoteIndex);
if(llList2String(Trigger, NoteIndex) != ""

NoteName = NoteName + "," + llList2String(Trigger, NoteIndex);
llGetNotecardLine(NoteName, NoteLine);
Say(1,"[" + (string)NoteIndex + "]" + NoteName + "..."

}
else
Say(1,"finalize script...ok"

}
}
}
listen(integer ch, string name, key id, string message)
{
if(ch == 0)
NoteCard(Trigger, message);
else if(ch == Channel1)
{
if(Finish)
return;
if(message == "Reset"

Reset(TRUE);
else if(message == "Note"

{
Menu(id);
return;
}
else if(message == "[x]Preload"

Preload = FALSE;
else if(message == "[-]Preload"

Preload = TRUE;
else if(message == "Finalize"

{
Finish = TRUE;
Say(1,"finalize script..."

integer Length = llGetListLength(Gesture);
if(Length == 0)
Say(1,"there is not notecard..."

else
{
Begin = 0;
End =0;
Count = 0;
NoteLine = 0;
NoteIndex = 0;
NoteName = llList2String(Gesture, NoteIndex);
if(llList2String(Trigger, NoteIndex) != ""

NoteName = NoteName + "," + llList2String(Trigger, NoteIndex);
llGetNotecardLine(NoteName, NoteLine);
Say(1,"[" + (string)NoteIndex + "]" + NoteName + "..."

}
}
llListenRemove(Listen1);
}
else if(ch == Channel2)
{
integer CheckBack = llSubStringIndex(message, BackButton);
integer CheckNext = llSubStringIndex(message, NextButton);
if(CheckBack != -1 || CheckNext != -1)
{
integer Back = 0;
integer Next = 0;
if(CheckBack != -1)
{
string Data = llDeleteSubString(message, CheckBack, llStringLength(BackButton) - 1);
if(Data == "0"

Data = "9";
Back = (integer)Data - 9;
Next = (integer)Data;
}
else
{
integer Data = (integer)llDeleteSubString(message, CheckNext, llStringLength(NextButton) - 1);
Back = Data;
Next = Data + 9;
}
if(Back < 0)
Back = 0;
list List = GetList(Back,Next);
integer Length = llGetListLength(Gesture);
if(Length < Next || Length == Next)
Next = Back;
string BACK = BackButton + (string)Back;
string NEXT = NextButton + (string)Next;
llDialog(llGetOwner(), "select nortcard", [BACK, llList2String(["MENU","-"], Finish), NEXT] + List, Channel2);
return;
}
else
{
if(message == "MENU"

{
if(Finish)
return;
Dialog(id);
return;
}
else if(message == "-"

llListenRemove(Listen1);
else
NoteCard(Gesture, message);
}
llListenRemove(Listen1);
return;
}
}
}