/*	LogD-Time-Manager 3.2
	WRITTEN BY: [WING] Sir Drink a lot
	visit www.adminmod.de
 
	BESCHREIBUNG: 	Berechnet die vergangene Zeit auf der Map.
			In einer "command".ini werden die Befehle und Zeitpunkte
			festgelegt, welche dann entsprechend der Mapzeit (in Sekunden)
			ausgeführt werden sollen.
 
			In der "command".ini immer mit dem höchsten Zeitwert beginnen!
			Seht euch das Beispiel timeremaining.ini an! Das Beispiel stellt
			ein 'Timeremaining' dar, wieviel Zeit noch auf der Map verbleiben.
 
			In dieser neuen Version werden jetzt alle Tasks in einer *.ini Datei abgelegt.
			Man kann jetzt auch mehrere Tasks anlegen, die zur gleichen Zeit ablaufen sollen.
 
			Desweiteren reagiert es auf die Chateingabe "timeleft" und setzt die Variable mp_timeleft.
			Das plugin_sdal_allowsounds ermöglicht dem Client, individuell zu entscheiden, ob
			er Customsounds hören möchte. Hier eben die Sprachausgabe des "timeleft".
 
 
	BEFEHLE:
	admin_tm_add 'Mapzeit in sec' 'Befehl'	:fügt einen Task zur (eingelesenen) Taskliste hinzu.
	admin_tm_del 'Task-ID'			:löscht einen Task aus der (eingelesenen) Taskliste.
	admin_tm_debug '0/1'			:DEBUG Meldungen aus/an.	
	admin_tm_exec 'Task-ID'			:Führt einen Task aus, obwohl er nicht an der Reihe ist.
	admin_tm_kill				:Stoppt alle Taskausführungen und setzt alles zurück (leert die Taskliste). Man muss mit admin_tm_load <filename> ein neue Liste einlesen oder mit admin_tm_add neue Tasks einfügen.
	admin_tm_list 'ab Task-ID'		:Zeigt einem alle anstehenden Tasks (ab eingegebener TaskID+10)und führt eine Zeitkontrolle durch.
	admin_tm_load 'filename'		:Stoppt die Ausführung aller Tasks und liest eine neue Taskliste ein.
	admin_tm_restart			:Ausführung der Tasks wird fortgesetzt.
	admin_tm_stop				:Stoppt die Ausführung aller Tasks.
	admin_tm_write 'filename.ini'		:schreibt die (bearbeitete) Taskliste in die angebene Datei.(!!überschreibt den Inhalt bei bestehender Datei!!)
	say timeleft				:Spricht die Zeit aus.
 
	EINSTELLUNGEN:
	- einen Ordner 'tm' unter addons/adminmod/config anlegen und darin die Taskliste speichern.
	- die Taskliste sieht so aus: 'Zeit in Sekunden' 'Befehl und Parameter, der dann ausgeführt werden soll'
	- file_access_read 1 und file_access_write 1 in der adminmod.cfg setzen
	- Metamod Plugin LogD.
 
	VAULT.INI:
	TM_FILE 'der Dateiname.Dateiendung der Taskliste, die sich im Ordner addons/adminmod/config/tm befindet.
	TM_DEBUG 0
 
 
	!!!!HINWEIS/Important Notice!!!!
 
	Ich übernehme keine Verantwortung dafür, was ihr in eure command.ini schreibt
	und was dann passiert, wenn dieser Befehl ausgeführt wird.
	Wenn Ihr z.B. irgendwelche rcon Befehle benutzt oder einfach nur 'quit'.
	Am Besten lasst ihr nur Adminmod Plugins ausführen.
 
	You can not hold me responsible for your mistakes.  For example, if you set 
	rcon_password or quit in your command.ini then it is YOUR problem.  The
   	defaults should be quite secure....
 
	---Changelog---
	24.06.04:	- Error-Log wird erstellt bei falscher Konfiguration des Servers.
			- Debug Funktion als Befehl aktiviert.
	18.04.04:	- komplette Code-Überarbeitung
			- admin_tm_stop und admin_tm_restart hinzugefügt
			- setzt die Variable mp_timeleft in sec
			- kill_timer wird wieder verwendet.
 
	14.03.04:	- Alle automatischen vault.ini Einträge entfernt, da die Nutzung der Daten nicht notwendig.
			- Die Variable "time" in "g_time" geändert, damit kein Konflikt mit admin.inc entsteht.
 
	20.03.03:	- Die Zeitüberprüfung beginnt erst, wenn ein Game_Commencing stattgefunden hat.
			- HandleSay, um das Timeleft im Chat abzufragen mit Sprachausgabe.
 
	26.02.03:	- auf das kill_timer wird ganz verzichtet!
 
	14.02.03:	- admin_tm_kill killt timer nicht mehr. Löscht aber sonst alles, dass nichts mehr ausgeführt wird.
			- In tm_warn ein plugin_exec admin_tm_kill eingebaut, wenn sich die neue Wartezeit nicht ermitteln lässt.
			- in 'timer ' steht nur noch der TimerIndex der von tm_warn aufgerufen wird.
			- admin_tm_list wird die maximale Anzeige jeweils auf 10 Einträge begrenzt.
 
	09.02.03:	- Änderung der Rechte. Zur Bearbeitung der Taskliste braucht man RCON Recht. Soll vor Missbrauch schützen.
 
	08.02.03:	- Komplette Überarbeitung des Time-Managers.
			- Wegfall der mapzeitungebundenen Tasks.
			- Man kann jetzt mehrere Tasks zu einer bestimmten Mapzeit ausführen lassen.
			- Es läuft nur noch ein Timer.
			- Erweiterte Bearbeitungs-Ausgaben des Managers, dadurch bessere Kontrolle.
			- Zusätzliche Ausgabe-Parameter an die vault.ini, die man mit anderen Plugins nutzen kann.
			  (Teamscore, Bester Spieler mit meisten Frags, Rundenanzahl und die die Mapzeit)
*/
 
#include <core>
#include <console>
#include <string>
#include <admin>
#include <adminlib>
 
#define ACCESS_CONSOLE 131072
 
new STRING_VERSION[MAX_DATA_LENGTH] = "24.06.04_v3.2";
new TextFileDir[MAX_TEXT_LENGTH]="addons/adminmod/config/tm/";
new File[MAX_TEXT_LENGTH];
 
new Key[]="am_sound";
 
/*Definiert, wieviele Zeilen der command.ini ausgewertet werden*/
#define MAX_LINE 100
 
/*Check-Variablen für tm_welt*/
new g_GameCommencing;
new g_checktime;
new g_timelimit;
 
/*g_debug-Mode*/
new g_debug=0;
 
/* ---- Task-Abarbeitung ---- */
/*Die verbleibende Mapzeit*/
new g_time;
 
/*g_tm_pointer dient als Zeiger, wo wir uns gerade in der Abarbeitung befinden*/
new g_tm_pointer;
 
/*g_tm_line enthält die maximale Anzahl der geladenen tasks*/
new g_tm_line;
 
/*Time enthält die Zeitangaben der eingelesenen Tasks*/
new Time[MAX_LINE][MAX_NUMBER_LENGTH];
 
/*Execute enthält die Befehle der eingelesenen Tasks*/
new Execute[MAX_LINE][MAX_DATA_LENGTH];
 
/*timer enthält den TimerIndex. Der Timer ruft sch immer wieder entsprechend nach errechneter Wartezeit zwischen 'time' und 'Time' selber auf.
new timer;*/
new g_TimerIndex;
 
/*Hält die Tasks an*/
new g_stop;
 
//////////////////
// SPEAK-OUTPUT //
//////////////////
static OnesLib[10][] = { 
	"", "one ", "two ", "three ", "four ", "five ", "six ", "seven ", "eight ", "nine " 
};
static TensLib[10][] = {
	"", "ten ", "twenty ", "thirty ", "fourty ", "fifty ", "sixty ", "seventy ", "eighty ", "ninety " 
};
static TeensLib[10][] = {
	"", "eleven ", "twelve ", "thirteen ", "fourteen ", "fifteen ", "sixteen ", "seventeen "
	, "eighteen ", "nineteen " 
};
static HundredsLib[10][] = { 
	"", "one hundred ", "two hundred ", "three hundred ", "four hundred ", "five hundred ", 
	"six hundred ", "seven hundred ", "eight hundred ", "nine hundred " 
};
static GroupNamesLib[5][] = {
	"", "thousand ", "million ", "billion ", "trillion " 
};
 
public plugin_init(){
	new FilePath[MAX_TEXT_LENGTH];
	new LogD[20];
	new iaccess_read;
	new iaccess_write;
	new x;
	iaccess_read=getvar("file_access_read");
	iaccess_write=getvar("file_access_write");
	get_vaultdata("TM_FILE",File,MAX_TEXT_LENGTH);
 
	if(!iaccess_read){
		log("[TIME-MANAGER] FATALER FEHLER! file_access_read ist nicht auf 1 in der adminmod.cfg gesetzt!");
		x=1;
	}else if (!iaccess_write){
		log("[TIME-MANAGER] EINSCHRAENKUNG! file_access_write ist nicht auf 1 in der adminmod.cfg gesetzt! Man kann ueber Konsole keine Tasks hinzufuegen!");
	}else if(strlen(File)==0){
		snprintf(FilePath,MAX_TEXT_LENGTH,"%scommand.ini",TextFileDir);
		if(fileexists(FilePath)){
			set_vaultdata("TM_FILE","command.ini");
			log("[TIME-MANAGER] WARNUNG! Datei der Task-Liste automatisch auf die Datei 'command.ini' im Ordner 'addons/adminmod/config/tm' gesetzt!");
		}else{
			log("[TIME-MANAGER] FATALER FEHLER! Konnte keine Datei finden, die eine Taskliste enthält. Bitte unter addons/adminmod/config einen Ordner 'tm' anlegen und darin eine 'command.ini' mit Tasks speichern!");
			x=1;
		}
	}
	get_vaultnumdata("TM_DEBUG",g_debug);
	if(g_debug){
		log("[TIME-MANAGER] WARNUNG! TIME-MANAGER laeuft im DEBUG Modus, was zu Lags auf dem Server fuehren kann! Bitte mit admin_tm_debug 0 deaktivieren!");
	}
 
	getstrvar("logd_version",LogD,20);
	if(strlen(LogD)==0){
		log("[TIME-MANAGER] WARNUNG! Metamod Plugin 'LogD' entweder nicht installiert oder veraltet! Wenn nicht installiert, TIME-MANAGER nicht voll funktionsfaehig!");
	}
 
	if(!x){
		plugin_registerinfo("LogD-Time-Manager","Executing commands within maptime",STRING_VERSION);
		plugin_registercmd("admin_tm_add","admin_tm_add",ACCESS_RCON,"admin_tm_add <Maptime> <Command>: Fuegt einen neuen Task hinzu");
		plugin_registercmd("admin_tm_del","admin_tm_del",ACCESS_RCON,"admin_tm_del <TaskID>: Loescht den Task mit der ID");
		plugin_registercmd("admin_tm_debug","admin_tm_debug",ACCESS_RCON,"admin_tm_debug <0/1>: Debug Modus aus/an.");
		plugin_registercmd("admin_tm_exec","admin_tm_exec",ACCESS_RCON,"admin_tm_exec <TaskID>: Fuehrt den Task direkt aus!");
		plugin_registercmd("admin_tm_kill","admin_tm_kill",ACCESS_RCON,"admin_tm_kill : Loescht alles Tasks");
		plugin_registercmd("admin_tm_list", "admin_tm_list", ACCESS_RCON,"admin_tm_list <ab TaskNr>: Zeigt eine Liste aller Tasks ab TaskID + 10");
		plugin_registercmd("admin_tm_load", "admin_tm_load", ACCESS_RCON,"admin_tm_load <filename>: laedt eine neue Taskliste und loescht die Alte");
		plugin_registercmd("admin_tm_restart","admin_tm_restart",ACCESS_RCON,"admin_tm_restart: fuehrt eine Neuberechnung der Tasks aus.");
		plugin_registercmd("admin_tm_stop","admin_tm_stop",ACCESS_RCON,"admin_tm_stop: stoppt alle Ausfuehrungen");
		plugin_registercmd("admin_tm_write","admin_tm_write",ACCESS_RCON,"admin_tm_write <filename>: speichert die Taskliste in das angegeben File");
		plugin_registercmd("say","HandleSay",ACCESS_ALL);
		plugin_registerhelp("say",ACCESS_ALL,"say timeleft: Will speak the time left.");
		plugin_registercmd("tm_welt", "tm_welt", ACCESS_CONSOLE);
		exec("logd_reg 62 admin_command tm_welt");
 
		g_checktime =systemtime();
		read_file();
		restart_tasks(1);
	}else{
		plugin_registerinfo("LogD-Time-Manager","Plugin disabled! Please take a look in logfiles!",STRING_VERSION);
	}        
        return PLUGIN_CONTINUE;
}
 
public admin_tm_add(HLCommand,HLData,HLUserName,UserIndex){
	new Data[MAX_DATA_LENGTH];
	new Text[MAX_TEXT_LENGTH];
	new sNewTime[MAX_NUMBER_LENGTH];
	new sCommand[MAX_DATA_LENGTH];
	new i;
	new j;
	new iOldTime;
	new iNewTime;
 
	convert_string(HLData,Data,MAX_DATA_LENGTH);
 
	if(g_tm_line<99){
		strbreak(Data,sNewTime,sCommand,MAX_DATA_LENGTH);
		iNewTime=strtonum(sNewTime);
		if(strlen(sNewTime)!=0 && strlen(sCommand)!=0){
			for(i=0;i<g_tm_line;i++){
				iOldTime=strtonum(Time[i]);
				if(iNewTime>=iOldTime){
					for(j=g_tm_line;j>=i;j--){
						strcpy(Time[j+1],Time[j],MAX_NUMBER_LENGTH);
						strcpy(Execute[j+1],Execute[j],MAX_DATA_LENGTH);
					}
					break;
				}
			}
			strcpy(Time[i],sNewTime,MAX_NUMBER_LENGTH);
			strcpy(Execute[i],sCommand,MAX_DATA_LENGTH);
			g_tm_line++;
			snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Task hinzugefuegt!");
	        	selfmessage(Text);
	        	/*Neuberechnung der Tasks*/
	        	if(!g_stop){
        			restart_tasks(1);
        		}else{
        			selfmessage("[TIME-MANAGER] Taskausfuehrungen sind noch gestoppt. Bitte 'admin_tm_restart' verwenden!");
        		}
		}else{
			snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Konnte Task nicht hinzufuegen! Angaben fehlen! 'Mapzeit' oder 'Command'");
		        selfmessage(Text);
		}
	}else{
		snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Kann keine Tasks mehr anfügen. Maximal %i zugelassen!",MAX_LINE-1);
		selfmessage(Text);
	}
        return PLUGIN_HANDLED;
}
 
public admin_tm_debug(HLCommand,HLData,HLUserName,UserIndex){
	new Data[MAX_DATA_LENGTH];
	new Text[MAX_TEXT_LENGTH];
	new iData;
	convert_string(HLData,Data,MAX_DATA_LENGTH);
	iData=strtonum(Data);
 
	if(iData>=1){
		iData=1;
	}else{
		iData=0;
	}	
	set_vaultnumdata("TM_DEBUG",iData);
	g_debug=iData;
	snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Debug-Modus auf %i gesetzt!",iData);
	selfmessage(Text);
	return PLUGIN_HANDLED;
}
 
public admin_tm_del(HLCommand,HLData,HLUserName,UserIndex){
	new Data[MAX_DATA_LENGTH];
	new Text[MAX_TEXT_LENGTH];
	new i;
	new j;
	new iData;
	convert_string(HLData,Data,MAX_DATA_LENGTH);
	iData=strtonum(Data);
	if(iData<=g_tm_line){
		for(i=0;i<=g_tm_line;i++){
			if(iData==i){
				for(j=i;j<g_tm_line;j++){
					strcpy(Time[j],Time[j+1],MAX_NUMBER_LENGTH);
					strcpy(Execute[j],Execute[j+1],MAX_DATA_LENGTH);
				}
				break;
			}
		}
		g_tm_line--;
		snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Task-ID %i (%i) wurde geloescht",i,iData);
		selfmessage(Text);
		/*Neuberechnung der Tasks*/
		if(!g_stop){
        		restart_tasks(1);
        	}else{
			selfmessage("[TIME-MANAGER] Taskausfuehrungen sind noch gestoppt. Bitte 'admin_tm_restart' verwenden!");
		}
	}else{
		snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Kann Task-ID nicht finden!");
		selfmessage(Text);
	}
	return PLUGIN_HANDLED;
}
 
public admin_tm_exec(HLCommand,HLData,HLUserName,UserIndex){
	new Text[MAX_TEXT_LENGTH];
	new Data[MAX_DATA_LENGTH];
	new iData;
	convert_string(HLData,Data,MAX_DATA_LENGTH);
	iData=strtonum(Data);
	if(strlen(Execute[iData])==0){
		snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Konnte Task-ID %i nicht ausfuehren!", iData);
        	selfmessage(Text);
        }else{
        	execute(Execute[iData]);
        }
        return PLUGIN_HANDLED;
}
 
public admin_tm_kill(HLCommand,HLData,HLUserName,UserIndex){
	new Text[MAX_TEXT_LENGTH];
	snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Alles zurueck gesetzt. Plugin gestoppt! Mit 'admin_tm_load <file>' neue Liste einlesen!");
        selfmessage(Text);
        g_stop=1;
        kill_tasks();
        return PLUGIN_HANDLED;
}
 
public admin_tm_list(HLCommand,HLData,HLUserName,UserIndex){
	new Data[MAX_DATA_LENGTH];
	new Text[MAX_TEXT_LENGTH];
	new User[MAX_NAME_LENGTH];
        new a;
        new i;
        new iData;
        convert_string(HLUserName,User,MAX_NAME_LENGTH);
        convert_string(HLData,Data,MAX_DATA_LENGTH);
      	iData=strtonum(Data);
      	if(iData>g_tm_line){
      		iData=0;
      	}
      	map_time();  	
      	selfmessage("");
      	snprintf(Text,MAX_TEXT_LENGTH,"--- TASKLISTE: %s ---",File);
	selfmessage(Text);
      	selfmessage("TASK-ID -- ZEIT -- BEFEHL");
      	for(i=iData;i<iData+10;i++){
      		strinit(Text);
      		snprintf(Text,MAX_TEXT_LENGTH,"%i. --- %s --- %s",i,Time[i],Execute[i]);
      		selfmessage(Text);
      		if(g_time > strtonum(Time[i+1]) && g_time < strtonum(Time[i])){
      			selfmessage("===>Hier stehen wir<===");
      		}
      		if(i==g_tm_line){
      			selfmessage("--ENDE--");
      			i+=1;
      			break;
      		}
      	}
      	selfmessage("------------------------------------");
      	snprintf(Text,MAX_TEXT_LENGTH,"---^t^tTask %i bis %i   ^t^t  ---",iData,i-1);
	selfmessage(Text);
	snprintf(Text,MAX_TEXT_LENGTH,"---^t^tvon insg. %i Tasks^t  ---",g_tm_line);
	selfmessage(Text);
      	selfmessage("------------------------------------");
      	snprintf(Text,MAX_TEXT_LENGTH,"Verbleibende Zeit: %i sec",g_time);
      	selfmessage(Text);
      	a=g_time-strtonum(Time[g_tm_pointer]);
      	snprintf(Text,MAX_TEXT_LENGTH,"Naechster Befehl in %d Sekunden:",a);
      	selfmessage(Text);
	snprintf(Text,MAX_TEXT_LENGTH,"%s --- %s ",Time[g_tm_pointer],Execute[g_tm_pointer]);
      	selfmessage(Text);
      	if(a<0 || getvar("mp_timelimit")*60+2 != g_timelimit){
      		if(!g_stop){
      			restart_tasks(1);
      		}else{
      			selfmessage("[TIME-MANAGER] Negative Zeit! Bitte 'admin_tm_restart' verwenden!");
      		}
        }
      	selfmessage("------------------------------------");
      	return PLUGIN_HANDLED;
}
 
public admin_tm_load(HLCommand,HLData,HLUserName,UserIndex){
	new Data[MAX_DATA_LENGTH];
	new Text[MAX_TEXT_LENGTH];
	convert_string(HLData,Data,MAX_DATA_LENGTH);
	if(strlen(Data)!=0){
		snprintf(Text,MAX_TEXT_LENGTH,"%s%s",TextFileDir,Data);
		if(fileexists(Text)){
			set_vaultdata("TM_FILE",Data);
			snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Einlesen der Datei: %s",Text);
        		selfmessage(Text);
        		kill_tasks();
        		read_file();
			/*Neuberechnung der Tasks*/
			if(!g_stop){
				restart_tasks(1);
			}else{
				selfmessage("[TIME-MANAGER] Taskausfuehrungen sind noch gestoppt. Bitte 'admin_tm_restart' verwenden!");
			}
		}else{
			snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Datei '%s' konnte nicht gefunden werden!",Text);
        		selfmessage(Text);
        	}
        }else{
        	snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Datei-Angabe fehlt!");
        	selfmessage(Text);
       	}
        return PLUGIN_HANDLED;
}
 
public admin_tm_restart(HLCommand,HLData,HLUserName,UserIndex){
	new Text[MAX_TEXT_LENGTH];
	g_stop=0;
	restart_tasks(1);
	snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Taskausfuehrung wurden neu gestartet!");
        selfmessage(Text);
        return PLUGIN_HANDLED;
}
 
public admin_tm_stop(HLCommand,HLData,HLUserName,UserIndex){
	new Text[MAX_TEXT_LENGTH];
	g_stop=1;
	restart_tasks(0);
	snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Taskausfuehrung wurde angehalten! Mit 'admin_tm_restart' kann sie neu gestartet werden!");
        selfmessage(Text);
        return PLUGIN_HANDLED;
}
 
public admin_tm_write(HLCommand,HLData,HLUserName,UserIndex){
	new Data[MAX_DATA_LENGTH];
	new Text[MAX_TEXT_LENGTH];
	new TimeCommand[MAX_DATA_LENGTH];
	new NewFile[MAX_DATA_LENGTH];
	new i;
	convert_string(HLData,Data,MAX_DATA_LENGTH);
	if(strlen(Data)!=0){
		snprintf(NewFile,MAX_DATA_LENGTH,"%s%s",TextFileDir,Data);
		resetfile(NewFile);
		for(i=0;i<=g_tm_line;i++){
			snprintf(TimeCommand,MAX_DATA_LENGTH,"%s %s",Time[i],Execute[i]);
			writefile(NewFile,TimeCommand,-1);
		}
		snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Daten in '%s' gespeichert.",NewFile);
        	selfmessage(Text);
        }else{
        	snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Datei-Angabe fehlt!");
        	selfmessage(Text);
       	}
        return PLUGIN_HANDLED;
}
 
/*Haupt-Zeit-Funktionen*/
public tm_welt(HLCommand,HLData,HLUserName,UserIndex){
        new Data [MAX_DATA_LENGTH];                                  
        convert_string( HLData, Data, MAX_DATA_LENGTH );
        if(Data[0]=='G' && g_GameCommencing == 0){
                g_GameCommencing = 1;
                g_checktime =systemtime();
                restart_tasks(1);
        }else if(Data[8]=='R'){
                g_checktime = systemtime();
                restart_tasks(1);
        }
        time_change("");
        return PLUGIN_CONTINUE;
}
 
/*Helper-Functions*/
time_change(User[]){
	new Text[MAX_TEXT_LENGTH];
	new Minutes[MAX_NUMBER_LENGTH];
	new Seconds[MAX_NUMBER_LENGTH];
	new minutes;
	new seconds;
	new iTime;
	if (getvar("mp_timelimit")*60+2 != g_timelimit && !g_stop){
		restart_tasks(1);
        }
        /*Verwendung von iTime, da g_time gestoppt werden kann*/
        iTime=getvar("mp_timelimit")*60+2-(systemtime()-g_checktime);
        snprintf(Text,MAX_TEXT_LENGTH,"%i",iTime);
        setstrvar("mp_timeleft",Text);
 
        if(strlen(User)!=0){
        	minutes = iTime/60;
        	seconds= iTime%60;
	        snprintf(Minutes,MAX_NUMBER_LENGTH,"%i",minutes);
	        if(seconds<10){
	        	snprintf(Seconds,MAX_NUMBER_LENGTH,"0%i",seconds);
	        }else{
	        	snprintf(Seconds,MAX_NUMBER_LENGTH,"%i",seconds);
	        }
	        snprintf(Text,MAX_TEXT_LENGTH,"Time Remaining: %s:%s minutes",Minutes,Seconds);
	        say(Text);
	        speak_timeleft(minutes,seconds,User);
	}
}
 
map_time(){
	g_time = g_timelimit-(systemtime()-g_checktime);
}
 
kill_tasks(){
	new i;
	for(i=0;i<=g_tm_line;i++){
		Time[i][0]	=0;
		Execute[i][0]	=0;
	}
	g_tm_line		=0;
	restart_tasks(0);
}
 
restart_tasks(iNext){
	new Text[MAX_TEXT_LENGTH];
	g_timelimit=getvar("mp_timelimit")*60+2;
	g_tm_pointer=0;
	if(g_TimerIndex!=0){
		if(g_debug){
			snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER-DEBUG] restart task -> kill timer ");
			selfmessage(Text);
		}
		kill_timer(g_TimerIndex);
		g_TimerIndex=0;
	}
	if(g_debug){
		snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER-DEBUG] restart task -> end");
		selfmessage(Text);
	}
	if(iNext){
		if(g_debug){
			snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER-DEBUG] restart task iNext -> calculate next");
			selfmessage(Text);
		}
		calculate_tasks();
	}
}
 
calculate_tasks(){
	new Text[MAX_TEXT_LENGTH];
	new settimer;
	new iNextTimer;
	new i;
	if (getvar("mp_timelimit")*60+2 != g_timelimit){
		if(g_debug){
			snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER-DEBUG] calculate next -> restart_tasks");
			selfmessage(Text);
		}
		restart_tasks(1);
	}else{
		map_time();
		if(g_debug){
			snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER-DEBUG] calculate next -> searching task for %i sec",g_time);
			selfmessage(Text);
		}
		for(i=g_tm_pointer;i<=g_tm_line;i++){
			iNextTimer=strtonum(Time[i]);
			if(g_time>iNextTimer){
				settimer=g_time-iNextTimer;
				g_TimerIndex=set_timer("tm_warn",settimer,0);
				g_tm_pointer=i;
				break;
			}
		}
		if(g_debug){
			snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER-DEBUG] calculate next -> found task '%i -- %s'",iNextTimer,Execute[g_tm_pointer]);
			selfmessage(Text);
		}
	}
}
 
public tm_warn(Timer,Repeat,HLUser,HLParam){
	new Text[MAX_TEXT_LENGTH];
	new iNextTimer;
	new i;
	new a;
	g_TimerIndex=0;
	if(g_debug){
		snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER-DEBUG] tm_warn start");
		selfmessage(Text);
	}
	if(!g_stop){
	        if (getvar("mp_timelimit")*60+2 != g_timelimit){
	        	if(g_debug){
				snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER-DEBUG] tm_warn -> restart_tasks");
				selfmessage(Text);
			}
	        	restart_tasks(1);
	        }else{
	        	if(g_debug){
				snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER-DEBUG] tm_warn -> execute");
				selfmessage(Text);
			}
			execute(Execute[g_tm_pointer]);
			g_tm_pointer++;
			map_time();
			/*Alle Tasks ausführen, die auch zur selben Zeit stattfinden sollen*/
			for(i=g_tm_pointer;i<=g_tm_line;i++){
				iNextTimer=strtonum(Time[i]);
				if(g_time==iNextTimer){
					execute(Execute[g_tm_pointer]);
					a++;
				}else{
					break;
				}
			}
			g_tm_pointer+=a;
			calculate_tasks();
		}
	}
	return PLUGIN_CONTINUE;
}
 
execute(Data[]){
	new Text[MAX_TEXT_LENGTH];
	new Command[MAX_DATA_LENGTH];
	new Param[MAX_DATA_LENGTH];
	if(strncmp(Data,"admin_",6)==0){
		strsep(Data," ",Command,MAX_DATA_LENGTH,Param,MAX_DATA_LENGTH);
		plugin_exec(Command,Param);
	}else{
		exec(Data);
	}
	if(g_debug==1){
		snprintf(Text,MAX_TEXT_LENGTH,"[TIME_MANAGER-DEBUG] execute -> %s wurde ausgefuehrt!",Data);
		selfmessage(Text);
	}
	return PLUGIN_CONTINUE;
}
 
read_file(){
	new TextFile[MAX_TEXT_LENGTH];
	new Text[MAX_TEXT_LENGTH];
	new Data[MAX_DATA_LENGTH];
	new iLine;
	new i;
 
        snprintf(TextFile,MAX_TEXT_LENGTH,"%s%s",TextFileDir,File);
 
	if(fileexists(TextFile)){
		/*iLine=filesize(TextFile);*/
		iLine=filesize(TextFile);
		if(iLine>MAX_LINE){
				iLine=MAX_LINE;
		}
		for(i=0;i<=iLine;i++){
			strinit(Data);
			readfile(TextFile,Data,i+1,MAX_DATA_LENGTH);
			if(strlen(Data)!=0 && strcmp(Data,"")!=0 && strncmp(Data,"/",1)!= 0){
        			strsep(Data," ",Time[g_tm_line],MAX_NUMBER_LENGTH,Execute[g_tm_line],MAX_DATA_LENGTH);
        			g_tm_line++;
        		}
        	}
        	g_tm_line-=1;
        	if(g_debug==1){
        		snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER-DEBUG] %i Befehle eingelesen",g_tm_line);
        		selfmessage(Text);
        	}
        }else{
        	snprintf(Text,MAX_TEXT_LENGTH,"[TIME-MANAGER] Finde %s nicht!!!!",TextFile);
        	selfmessage(Text);
        }
	return PLUGIN_CONTINUE;
}
 
/*Alles zum Timeleft*/
public HandleSay(HLCommand,HLData,HLUserName,UserIndex) {
	new Data[MAX_DATA_LENGTH];
	new User[MAX_NAME_LENGTH];
 
	convert_string(HLData,Data,MAX_DATA_LENGTH);
	convert_string(HLUserName,User,MAX_NAME_LENGTH);
 
	strstripquotes(Data);
	if (streq(Data, "timeleft")==1) {
		time_change(User);
	}
	return PLUGIN_CONTINUE;
}
 
allowsound(User[]){
	new Info[MAX_NUMBER_LENGTH];
	new iInfo;
	new Authid[MAX_AUTHID_LENGTH];
	get_userAuthID(User,Authid,MAX_AUTHID_LENGTH);
	if(strcmp(Authid,"BOT")!=0){
		get_userinfo(User,Key,Info,MAX_NUMBER_LENGTH);
		iInfo=strtonum(Info);
		if(strlen(Info)==0 || iInfo > 0){/*damit wird automatisch immer der Sound auf 1 gesetzt,wenn kein setinfo vorhanden, bis 'stop' eingegeben wird*/
			return 1;
		}
	}
	return 0;
}
 
speak_timeleft(minutes,seconds,User[]){
	new Text[MAX_TEXT_LENGTH];
	new Minutes[MAX_NUMBER_LENGTH];
	new Seconds[MAX_NUMBER_LENGTH];
	if(allowsound(User)){
		numtoword(minutes,Minutes,MAX_NUMBER_LENGTH);
	        numtoword(seconds,Seconds,MAX_NUMBER_LENGTH);
	        snprintf(Text,MAX_DATA_LENGTH,"fvox/%s minutes %s seconds remaining",Minutes,Seconds ); 
		speakto(User,Text);
	}
}
 
/*Big THX to SR71GOKU for this code!*/
stock do_numtoword(iNum,str[],iLevel,iLength) {
 
	/* If there is more than one group of 3, then take care of the others first. */
	if(iNum >= 1000) do_numtoword(iNum / 1000,str,iLevel + 1,iLength);
 
	/* Grab the the first 3 digits only */
	iNum %= 1000;	
 
	/* Isolate each digit */
	new _hundreds = iNum / 100;
	new _tens = (iNum / 10) % 10;
	new _ones = iNum % 10;
 
	/* Take care of the teen numbers */
	if(_tens == 1 && _ones != 0) {
		snprintf(str,iLength,"%s%s%s%s",str,HundredsLib[_hundreds],TeensLib[_ones],GroupNamesLib[iLevel]);
	} else {
		snprintf(str,iLength,"%s%s%s%s%s",str,HundredsLib[_hundreds], TensLib[_tens], OnesLib[_ones],GroupNamesLib[iLevel]);
	}
 
	if(iLevel==0) str[strlen(str)-1] = 0; /* Gets rid of the trailing space*/
	return 1;
}
 
stock numtoword(iNum,str[],iLength) {
	/* Empties the first char of the string */
	str[0] = 0;
	str[iLength-1] = 0;
	if(iNum == 0) {
		snprintf(str,iLength,"zero");
		return 1;
	}
	if(iNum < 0) {
		iNum *= -1;
		snprintf(str,iLength,"negative ");
	}
 
	return do_numtoword(iNum,str,0,iLength); 
}