Final Fantasy like speech system.

This goes in the speaking NPC:

[CODE]
if(ff3spoke){
//Because graal is stupid, every letter need to be separated by a comma or a space.
// * = space
// / = comma
// the letter u precedes the uppercase characters (ex.: uM)

client.quantityofspeechbubbles=5;
setstring client.s1,uI,,a,m,,a,,c,a,t,.,.,. uB l a h / b l a h * b l a h * b l a h * b l a h * b l a h uB l a h / b l a h * b l a h * b l a h * b l a h * b l a h uB l a h / b l a h * b l a h * b l a h * b l a h * b l a h uB l a h / b l a h * b l a h * b l a h * b l a h * b l a h;
setstring client.s2,uN,o,
,r,e,a,l,l,y,/,,uI,’,m,,a,,c,a,t,!;
setstring client.s3,uM,e,o,w,!;
setstring client.s4,uM,e,o,w,
,uM,e,o,w,*,uM,e,o,w,!;
setstring client.s5,uO k * uI ’ m * d o n e .;

for(weapon=0;weapon<weaponscount;weapon++){
callweapon weapon,showspeechbubble;
}
}[/CODE]

This is the npcw (note that it uses the var client.speaking):

[CODE]
// NPC made by 2ndwolf
if (created) {
toweapons FF3 Speech;
}

if(keypressed&&keydown2(keycode(a),true)){
if(client.speaking==0){
this.npcsindex = -1;
this.callthenpclooped = 0;
callthenpc();
}
}

function callthenpc(){
if(testnpc(playerx+.95+vecx(playerdir)*this.callthenpclooped,playery+2+vecy(playerdir)*this.callthenpclooped)!=-1){
callnpc testnpc(playerx+.95+vecx(playerdir)*this.callthenpclooped,playery+2+vecy(playerdir)*this.callthenpclooped),ff3spoke;
}
else{
this.callthenpclooped += .5;
if(this.callthenpclooped<5){callthenpc();}
}
}

if(showspeechbubble){
//Declare constants
setstring this.letters,uA,uB,uC,uD,uE,uF,uG,uH,uI,uJ,uK,uL,uM,uN,uO,uP,uQ,uR,uS,uT,uU,uV,uW,uX,uY,uZ,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;
this.exclam=1;
this.questionmrk=2;
this.dot=3;
this.eacute=4;
this.agrave=5;
this.egrave=6;
this.ugrave=7;
this.comma=8;
this.apos=9;
this.space=10;

this.uppers=1;
this.mins=2;
this.punct=3;

this.maxwidth=576;

this.showimgstartindex = 3000;

this.speechoffset = {16,16}

this.speechbubblewidth = 606;
this.speechbubbleheight = 157;
if(screeny(playerx,playery)>screenheight/2){this.speechbubbleyoffset=16;}else{this.speechbubbleyoffset=screenheight-this.speechbubbleheight-10;}
this.speechbubbleoffset = {(screenwidth-this.speechbubblewidth)/2,this.speechbubbleyoffset}

client.speaking = 1;

//Declare variables
this.speechbubble = this.showimgstartindex+this.imagenumber-1;
this.speechbubnumber=1;
this.tokenindex=0;
this.charyoffset=-1;
this.charxoffset=-1;

//Start the speech already!
initspeech();
}

function initspeech(){
freezeplayer 0.05;
tokenize #s(client.s#v(this.speechbubnumber));

showimg this.speechbubble,speechbubble.png,this.speechbubbleoffset[0],this.speechbubbleoffset[1];
changeimgvis this.speechbubble,4;

timeout = 0.05;
}

if(timeout){
freezeplayer 0.05;
//reset the offsets
this.charyoffset=-1;
this.charxoffset=-1;
//is it punctuation?
checkpunct();
//is it a letter?
if(this.charyoffset==-1){this.letterindex=0; checkletter();}

//show the character
showletter();
this.lastcharxoffset = this.charxoffset;

//loop for the next letter
if(this.tokenindex<tokenscount){
this.tokenindex+=1;
timeout = 0.05;
}
//loop for the next speechbox
else if(this.speechbubnumber<client.quantityofspeechbubbles){
freezeplayer 2;
sleep 2;
this.tokenindex=0;
this.linenumber=0;
this.speechbubnumber+=1;
hidetext();
this.lastimagenumber = this.imagenumber;
this.lastwidth=0;
initspeech();
}
//end the speech
else{
freezeplayer 2;
sleep 2;
hideeverything();
this.lastimagenumber= this.imagenumber;
this.lastwidth = 0;
client.speaking = 0;
}
}

function checkpunct(){
if(strequals(#t(this.tokenindex),!))this.charxoffset=this.exclam;
if(strequals(#t(this.tokenindex),?))this.charxoffset=this.questionmrk;
if(strequals(#t(this.tokenindex),.))this.charxoffset=this.dot;
if(strequals(#t(this.tokenindex),é))this.charxoffset=this.eacute;
if(strequals(#t(this.tokenindex),à))this.charxoffset=this.agrave;
if(strequals(#t(this.tokenindex),è))this.charxoffset=this.egrave;
if(strequals(#t(this.tokenindex),ù))this.charxoffset=this.ugrave;
if(strequals(#t(this.tokenindex),’))this.charxoffset=this.apos;
if(strequals(#t(this.tokenindex),*))this.charxoffset=this.space;
if(strequals(#t(this.tokenindex),/))this.charxoffset=this.comma;

if(this.charxoffset!=-1)this.charyoffset=this.punct;
}

function checkletter(){
if(strequals(#t(this.tokenindex),#I(this.letters,this.letterindex))){
if(this.letterindex<26){this.charyoffset=this.uppers; this.charxoffset=this.letterindex+1;}
else{this.charyoffset=this.mins; this.charxoffset=this.letterindex+1-26;}
}
else if(this.letterindex<52){
this.letterindex+=1;
checkletter();
}
}

function showletter(){
//Makes sure the text does not go wider than the bubble.
if(this.lastcharxoffset==this.space){
this.templetteroffset += 1;
if(strequals(#t(this.tokenindex+this.templetteroffset),*)||this.tokenindex+this.templetteroffset==tokenscount)this.wordboundaryfound=1;
if(((this.tokenindex+this.templetteroffset)16-(this.maxwidththis.linenumber))>this.maxwidth){this.wordboundaryfound=1; this.skipline=1; this.lastwidth=(this.tokenindex)*16;}
if(this.wordboundaryfound!=1){showletter();}
}

//Showletter
if(this.wordboundaryfound==1||this.lastcharxoffset!=this.space){
if(this.skipline==1){this.linenumber+=1; this.skipline=0;}
this.templetteroffset=0;
this.wordboundaryfound=0;
showimg this.showimgstartindex+this.imagenumber,courrier_charactersheet.png,this.speechoffset[0]+this.speechbubbleoffset[0]+(this.imagenumber-this.lastimagenumber)16-(this.lastwidth),this.speechoffset[1]+this.speechbubbleoffset[1]+this.linenumber21;
changeimgpart this.showimgstartindex+this.imagenumber,this.charxoffset16,this.charyoffset21,16,21;
changeimgvis this.showimgstartindex+this.imagenumber,5;
this.imagenumber += 1;
}
}

function hidetext(){
hideimgs this.showimgstartindex+this.lastimagenumber,this.showimgstartindex+this.imagenumber;
}

function hideeverything(){
hideimg this.speechbubble;
hideimgs this.showimgstartindex+this.lastimagenumber,this.showimgstartindex+this.imagenumber;
}[/CODE]

Behaviour:
Once the player presses a next to a speaking NPC, it shows a textbox and letters appear one by one to show text.

Known bugs:
None

To do:
Make the text slower and add speed while the player presses a.
Once the textbox finishes showing its text, show an arrow on bottom right and wait for player to press a.
A way to cancel the textbox.
A better looking textbox.
Maybe a version not using a monospaced font.

Hosler, if you want to keep it for yourself, delete this post :slight_smile:

This is how it looks:

uh that’s cool and all but why is the code so large?

http://forums.graal.in/forums/showthread.php?6300-Bitmap-font

Because I didn’t know of #e and ascii.
So I worked around it using tokenize and special characters and shit.

The only features that should really take up more space than your script is the full-line checker(7 lines), and that there can be more than one speech box(10 lines).

So in all my script shouldn’t be much longer than 40 lines, including the boilerplate stuff.

I feel kinda stupid, back to the drawing boards!

Not calling you stupid; just showing you an easier way.

@2ndwolf, i forgot to tell you about spooon’s stuff. was going to do that, but good job. im gonna use this. i’ll pm you another request.