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