/* This plugin runs a karaoke with lyrics and music (if available) */
/* $Id: plugin_am_karaoke.sma, v0.3 2002/23/04 15:07:12 Snip & YoGi $ */
 
/*
	================================
	ADMIN_KARAOKE v0.3 - MINI HOW-TO
	================================
	by : Snip (snipfou@hotmail.com) : idea/lyrics management
			 YoGi (yogi@darkmag.net)    : AM coding
 
	Special thanks to dJeyL (http://djeyl.net) for his huge help			 
 
 
	o AM commands : 
  ---------------
 
	admin_karaoke <songID>				: launch a karaoke
	admin_vote_karaoke <songID>		: vote for a karaoke
	admin_list_karaoke						: list available songIDs/songs
 
 
	o files required :
	  ----------------
 
	%MODNAME%/karaoke/karaoke_list.txt
 
	%MODNAME%/karaoke/songID1.txt
	%MODNAME%/sound/karaoke/songID1.wav (optionnal)
 
	%MODNAME%/karaoke/songID2.txt
	%MODNAME%/sound/karaoke/songID2.wav (optionnal)
 
	...
 
	note : every client must own a copy of the wav files. 
	       if a client doesn't, he won't hear the music
 
 
	o files templates :
	  -----------------
 
	* karaoke_list.txt :
		1/	number of songs
		2/	blank line
		3/	songID1.txt
		4/	songID2.txt
		...
 
	* songID*.txt :	
		1/	full song name ("artist - title" for example)
		2/	total number of lines of the current file
		3/	blank line
		4/	line1-duration line1-color line1-sentence
		5/	line2-duration line2-color line2-sentence
		6/	line3-duration															<-- blank sentence : for a solo or anything else without lyrics.
		7/	line4-duration line4-color line4-sentence
		...
 
		note : X/ stands for line numbers, and must not appear in the files
 
 
	o misc informations :
	  -------------------
	_ IMPORTANT : the AM CVAR 'file_access_read' must be at 1 in 'server.cfg' (p/j : n'est ce pas Klug ? :)
	_ durations are in seconds
	_ available colors are : red, blue, green, white, yellow, purple
	_ a single sentence cannot be 80 chars higher.
	_ Admin_Karaoke may generate irreversible damages to your brain. Handle with care and at your own risks :)
 
*/	
 
#include <core>
#include <console>
#include <string>
#include <admin>
#include <adminlib>
 
#define ACCESS_VOTE_KARAOKE 1
#define ACCESS_LIST_KARAOKE 1
#define ACCESS_KARAOKE 131
 
new STRING_VERSION[MAX_DATA_LENGTH] = "0.3";
new sFile[MAX_DATA_LENGTH] = "karaoke/karaoke_list.txt" ;		// fichier de liste des chansons
 
 
/* variables globales - ne pas modifier */
 
new sCurSong[MAX_DATA_LENGTH] ;				// titre courant
new iTotal ;													// nombre de lignes du titre courant
 
new iCRed ; 													// couleurs pour le texte
new iCGreen ;
new iCBlue ;
 
 
/* 
	get_color - fct interne
	détermine les couleurs R,G,B decimales a partir d'un nom de couleur
	note : ICRed, ICGreen et ICBlue sont des vars globales
*/	
 
get_color(sColor[MAX_DATA_LENGTH]) {
	if (streq(sColor,"red") == 1) {
		iCRed = 250 ;
		iCGreen = 10 ;
		iCBlue = 10 ;
	}
	else 
		if (streq(sColor, "blue")==1) {
			iCRed = 10 ;
			iCGreen = 10 ;
			iCBlue = 250 ;
		}
		else 
			if (streq(sColor, "green")==1) {
				iCRed = 10 ;
				iCGreen = 250 ;
				iCBlue = 10 ;
			}
			else 
				if (streq(sColor, "white")==1) {
					iCRed = 250 ;
					iCGreen = 250 ;
					iCBlue = 250 ;
				}
				else 
					if (streq(sColor, "yellow")==1) {
						iCRed = 250 ;
						iCGreen = 250 ;
						iCBlue = 10 ;
					}
	 				else 
						if (streq(sColor, "purple")==1) {
							iCRed = 250 ;
							iCGreen = 10 ;
							iCBlue = 250 ;
						}
						else { 	// green par defaut, si couleur non trouvee
							iCRed = 10 ;
							iCGreen = 250 ;
							iCBlue = 10 ;
						}
 
}
 
 
/*
	karaoke_show_lyrics - fct interne
	affiche une ligne des paroles : le numero de la ligne est passe ds le timer
*/	
 
public karaoke_show_lyrics(Timer,Repeat,HLUser,HLParam) {	// HLParam = ligne courante du fichier de paroles
	new sLine[MAX_DATA_LENGTH] ;
	new sTempo[MAX_DATA_LENGTH] ;
	new sPhrase[MAX_DATA_LENGTH] ;
	new sColor[MAX_DATA_LENGTH] ;
	new sCurLine[MAX_DATA_LENGTH] ;
	new sTmp[MAX_DATA_LENGTH] ;
 
	new iTempo ;
	new iCurLine ;
 
	/* initialisation des chaines de cars */
 
	strinit(sLine) ;
	strinit(sTempo) ;
	strinit(sColor) ;
	strinit(sPhrase) ;
	strinit(sCurLine) ;
	strinit(sTmp) ;
 
	/* conversion du paramètre */
 
	convert_string(HLParam,sCurLine,MAX_NAME_LENGTH) ;
 
	/* lecture de la ligne courante */
 
	iCurLine = strtonum(sCurLine) ; 
	readfile(sCurSong,sLine,iCurLine,MAX_DATA_LENGTH) ;
 
	/* separation de la tempo et de la couleur+phrase */
 
	strbreak(sLine, sTempo, sTmp, MAX_DATA_LENGTH) ;
	iTempo = strtonum(sTempo) ;
 
	if (strlen(sTmp)) {
		/* separation de la couleur+phrase */	
 
		strbreak(sTmp, sColor, sPhrase, MAX_DATA_LENGTH) ;
		get_color(sColor) ;		// affecte les resultats ds ICRed, ICGreen & ICBlue
 
		/* affichage si il y a une phrase */
 
		if (strlen(sPhrase)) 
			typesay(sPhrase,iTempo,iCRed,iCGreen,iCBlue) ;
	}
 
	/* on réinitialise le timer s'il reste des lignes a afficher */
 
	if (iCurLine+1 <= iTotal) {
		numtostr(iCurLine+1,sCurLine); 	// nouvelle valeur de sCurLine
		set_timer("karaoke_show_lyrics",iTempo,1,sCurLine) ;
	}
 
	return PLUGIN_CONTINUE ;
}
 
 
/*
	karaoke_play_sound - fct interne
	joue le fichier wav sur chaque client (s'il existe)	
*/	
 
public karaoke_play_sound(Timer,Repeat,HLUser,HLParam) {	// HLParam = fichier wav a jouer
	new sParam[MAX_DATA_LENGTH] ;
	new sName[MAX_NAME_LENGTH];
	new iUserID;
	new iWONID;	
	new i ;
 
	new iPlayerCount = maxplayercount();
 
	/* initialisation des chaines de cars */
 
	strinit(sParam) ;
	strinit(sName) ;
 
	/* conversion du paramètre */
 
	convert_string(HLParam,sParam,MAX_NAME_LENGTH);
 
	/* lancement du fichier wav sur chaque client - basé sur Killing Streak Announcer (c) Bud-froggy Productions */
 
	for (i=1 ; i<=iPlayerCount ; i++) 
		if (playerinfo(i, sName, MAX_NAME_LENGTH, iUserID, iWONID)) 
			if (iWONID)  // si ce n'est pas un bot 
				playsound(sName, sParam);
 
	return PLUGIN_CONTINUE ;
}
 
 
/*
	admin_list_karaoke
	liste les ID et les titres complets des chansons disponibles	
*/	
 
public karaoke_list_songs(HLCommand,HLData,HLUserName,UserIndex) {
	new sLine[MAX_DATA_LENGTH] ;
	new sLine2[MAX_DATA_LENGTH] ;
	new sTmp[MAX_DATA_LENGTH] ;
	new iNum ;
	new i ;
 
	if (fileexists(sFile)) {
		/* initialisation des chaines de cars */
 
		strinit(sLine) ;
		strinit(sLine2) ;
 
		/* recuperation du nb de chansons dispos */
 
		readfile(sFile,sLine,1,MAX_DATA_LENGTH) ;
		iNum = strtonum(sLine) ;
 
		/* affichage des chansons dispos */
 
		selfmessage("Available songs :") ;
 
		for (i=0 ; i<iNum ; i++) {
			/* on recupere le nom du fichier */
 
			readfile(sFile,sTmp,i+3,MAX_DATA_LENGTH) ;
 
			/* on retire le ".txt" du nom de fichier */
 
			strncpy(sLine,sTmp,strchr(sTmp,'.'), MAX_DATA_LENGTH) ;
 
			/* on recupere le nom de la chanson */
 
			snprintf(sTmp,MAX_DATA_LENGTH,"karaoke/%s.txt",sLine) ;
			readfile(sTmp,sLine2,1,MAX_DATA_LENGTH) ;
 
			/* on genere la ligne et on l'affiche */
 
			snprintf(sTmp,MAX_DATA_LENGTH,"'%s' : %s",sLine,sLine2) ;
			selfmessage(sTmp) ;
		}
	}
	else {
		selfmessage("Oops, the file 'karaoke_list.txt' is missing on the server !") ;
	}
 
	return PLUGIN_HANDLED ;
}
 
 
/*
	admin_vote_karaoke <songID>
	propose un vote pour lancer un karaoke sur le titre determine par <songID>
*/	
 
public karaoke_vote(HLCommand,HLData,HLUserName,UserIndex) {
	new sData[MAX_DATA_LENGTH] ;
	new sTmp[MAX_DATA_LENGTH] ;
	new sTitle[MAX_DATA_LENGTH] ;
 
	/* si vote pas autorisé, DTC !! */
 
	if (vote_allowed() != 1) {
		selfmessage( "Vote not allowed at this time.");
		return PLUGIN_HANDLED;
	}
 
	/* sinon, initialisation des chaines de cars */
 
	strinit(sData);
	strinit(sTmp);
	strinit(sTitle);
 
	/* conversion du paramètre <songID> */
 
	convert_string(HLData,sData,MAX_DATA_LENGTH);
 
	/* au cas ou le boulet d'user aurait mis les quotes :) */
 
	strstripquotes(sData) ;		
 
	/* si le parametre est present */
 
	if (strlen(sData)) {
		/* generation du chemin vers le fichier de paroles */
 
		snprintf(sTmp,MAX_DATA_LENGTH,"karaoke/%s.txt",sData) ;
 
		/* si ce fichier existe.. */
 
		if (fileexists(sTmp)) {
			/* alors on lit la 1ere ligne : le titre complet de la chanson */
 
			readfile(sTmp,sTitle,1,MAX_DATA_LENGTH) ;
 
			/* on genere la question pour le vote */
 
			snprintf(sTmp,MAX_DATA_LENGTH,"Play '%s' ?",sTitle) ;
 
			/* et hop on balance le vote */
 
			vote(sTmp,"Yes","No","karaoke_handle_vote",sData);
		}
		else {
			snprintf(sTmp,MAX_DATA_LENGTH,"Oops, the ID '%s' is not a valid song ID !",sData) ;
			selfmessage(sTmp) ;
		}
	}
	else {
		selfmessage("Usage : admin_vote_karaoke <songID>") ;
	}
 
	return PLUGIN_HANDLED ;
}
 
 
/*
	karaoke_handle_vote - fct interne
	fonction qui traite le resultat du vote et agit en consequence
*/	
 
public karaoke_handle_vote(WinningOption,HLParam,VoteCount,UserCount) {
	new sData[MAX_NUMBER_LENGTH];
	new sNumber[MAX_NUMBER_LENGTH];
	new sText[MAX_TEXT_LENGTH];
	new iRatio ;
 
	/* initialisation des chaines de cars */
 
	strinit(sNumber) ;
	strinit(sText) ;
	strinit(sData) ;
 
	/* conversion du paramètre */
 
	convert_string(HLParam,sData,MAX_DATA_LENGTH);
 
	/* si l'option gagnante est 'Yes' */
 
	if (WinningOption == 1) {
		/* recuperation du ratio de vote par défaut (60) */
 
		iRatio = getvar("admin_vote_ratio");
 
		/* si le nb de votes pour 'Yes' est > au ratio */
 
		if (VoteCount >= iRatio*UserCount/100) {
			/* ratio suffisant : exécution d'admin_karaoke */	
 
			plugin_exec("admin_karaoke",sData); 		
		} 
		else {
			/* si ratio insuffisant : message d'erreur*/
 
			numtostr(iRatio*UserCount/100,sNumber);
			snprintf(sText, MAX_TEXT_LENGTH, "Karaoke vote succeeded, but not enough votes (needed %s)",sNumber);
			say(sText);
		}
	} 
	else {
		say("Karaoke vote failed.");
	}			
 
	return PLUGIN_HANDLED ;
}
 
 
/*
	admin_karaoke <songID>
	lance un karaoke sur le titre déterminé par <songID>
*/	
 
public karaoke(HLCommand,HLData,HLUserName,UserIndex) {
	new sCurSound[MAX_DATA_LENGTH] ;			// chemin vers le fichier wav courant (si existant)	
	new sLine[MAX_DATA_LENGTH] ;
	new sParam[MAX_DATA_LENGTH] ;
	new sTmp[MAX_DATA_LENGTH] ;		
 
	/* initialisation des chaines de cars */
 
	strinit(sParam) ;
	strinit(sCurSong) ;
	strinit(sCurSound) ;
 
	/* conversion du parametre <songID> */
 
	convert_string(HLData,sParam,MAX_DATA_LENGTH);
 
	/* au cas ou le boulet d'user aurait mis les quotes :) */
 
	strstripquotes(sParam) ;		
 
	/* traitement - si l'user a bien precise un <songID> */		
 
	if (strlen(sParam)) {
		/* generation du chemin complet des fichiers */
 
		strinit(sTmp) ;
		snprintf(sCurSong,MAX_DATA_LENGTH,"karaoke/%s.txt",sParam) ;	
 
		if (fileexists(sCurSong)) {
			/* initialisation des chaines de cars */
 
			strinit(sLine) ;
 
			/* affichage du titre en arc en ciel :) */
 
			readfile(sCurSong,sLine,1,MAX_DATA_LENGTH) ;		// titre de la chanson
			snprintf(sTmp,MAX_DATA_LENGTH,"Admin_Karaoke v%s^nNow playing : %s",STRING_VERSION,sLine) ;
 
			rainbow(sTmp, 5 ,255,0,0, 0,0,255);
 
			/* recuperation du nombre de lignes du titre */
 
			readfile(sCurSong,sLine,2,MAX_DATA_LENGTH) ;
			iTotal = strtonum(sLine) ;
 
			/* traitements pour les timers.. */
 
			snprintf(sCurSound,MAX_DATA_LENGTH,"karaoke/%s.wav",sParam) ;
			numtostr(4,sTmp) ;
 
			/* lancement du fichier wav et des paroles*/
 
			set_timer("karaoke_play_sound",4,1,sCurSound) ;
			set_timer("karaoke_show_lyrics",4,1,sTmp) ;			
		}
		else {
			snprintf(sTmp,MAX_DATA_LENGTH,"Oops, the ID '%s' is not a valid song ID !",sParam) ;
			selfmessage(sTmp) ;
		}
	}
	else {
		selfmessage("Usage : admin_karaoke <songID>") ;
	}
 
	return PLUGIN_CONTINUE ;
}
 
 
/*
	initialisation du plugin et enregistrement des cmds
*/
 
public plugin_init() {
	plugin_registerinfo("Admin_Karaoke", "Runs a karaoke with lyrics and music.", STRING_VERSION);
 
	plugin_registercmd("admin_karaoke", "karaoke", ACCESS_KARAOKE, "admin_karaoke <songID> : launch a karaoke."); 
	plugin_registercmd("admin_list_karaoke", "karaoke_list_songs", ACCESS_LIST_KARAOKE, "admin_list_karaoke : lists available songIDs/songs."); 
	plugin_registercmd("admin_vote_karaoke", "karaoke_vote", ACCESS_VOTE_KARAOKE, "admin_vote_karaoke <songID> : vote for a karaoke."); 
 
	return PLUGIN_CONTINUE ;
}