/*
									Gate Maker - seif_gate
*/
/*x---------------------------------Important-------------------------------------x*/
//**INCLUDES**//
#include <a_samp>
//**PRAGMAS**//

//**MISC**//

/*x---------------------------------Defining-------------------------------------x*/
//**COLORS*//
#define GREEN 			0x21DD00FF
#define RED 			0xE60000FF
#define ADMIN_RED 		0xFB0000FF
#define YELLOW 			0xFFFF00FF
#define ORANGE 			0xF97804FF
#define LIGHTRED 		0xFF8080FF
#define LIGHTBLUE 		0x00C2ECFF
#define PURPLE 			0xB360FDFF
#define PLAYER_COLOR 	0xFFFFFFFF
#define BLUE 			0x1229FAFF
#define LIGHTGREEN 		0x38FF06FF
#define DARKPINK 		0xE100E1FF
#define DARKGREEN 		0x008040FF
#define ANNOUNCEMENT 	0x6AF7E1FF
#define GRAY 			0xCECECEFF
#define PINK 			0xD52DFFFF
#define DARKGREY    	0x626262FF
#define AQUAGREEN   	0x03D687FF
#define NICESKY 		0x99FFFFAA
#define WHITE 			0xFFFFFFFF
#define BLACK           0x000000FF
//**MISC**//
#define function%0(%1) forward %0(%1); public %0(%1)

#if !defined SendFormatMessage
	new FALSE = false;
	#pragma unused FALSE
	#define SendFormatMessage(%1,%2,%3,%4) do{ new str[128]; format(str, sizeof str, %3, %4); SendClientMessage(%1, %2, str); } while(FALSE)
#endif

#define MAX_GATE_MODELS				5           // increase this to the maximum gate objects added in the file GateObjects.txt
#define MAX_GATES                   50          // Max gates that can be created in-game using this editor.
//**VARIABLES**//
new GateModel[MAX_GATE_MODELS];
new GateID[MAX_GATES];
new GateModelNumber[MAX_GATES];
new MaxGates;
new PlayerEditingGate[MAX_PLAYERS];
new playergatetime[MAX_PLAYERS];
new PlayerEdit[MAX_PLAYERS];

new Text:GateText_BG;
new Text:GateText_Info[MAX_GATES];

new Text3D:GateTextLabel[MAX_GATES];
// **FORWARDS** //

/*x---------------------------------CallBacks-------------------------------------x*/
public OnFilterScriptInit()
{
	if (!fexist("GateObjects.txt"))
	{
		new File:e = fopen("GateObjects.txt", io_write);
		fwrite(e, " ");
		fclose(e);
	}
	new File:file = fopen("GateObjects.txt", io_read);
	if (file)
	{
	    new read[64];
	    MaxGates = 0;
	    while (fread(file, read, sizeof read))
	    {
	        GateModel[MaxGates] = strval(read);
	        MaxGates++;
	    }
	}
	MaxGates--;
	fclose(file);
	
	GateText_BG = TextDrawCreate(458.000000,173.000000,"  Gate Info~n~~n~~n~~n~~n~~n~~n~~n~~n~~n~~n~~n~");
	TextDrawUseBox(GateText_BG,1);
	TextDrawBoxColor(GateText_BG,0x00000066);
	TextDrawTextSize(GateText_BG,570.000000,0.000000);
	TextDrawAlignment(GateText_BG,0);
	TextDrawBackgroundColor(GateText_BG,0x000000ff);
	TextDrawFont(GateText_BG,2);
	TextDrawLetterSize(GateText_BG,0.400000,1.350000);
	TextDrawColor(GateText_BG,0xffffffff);
	TextDrawSetProportional(GateText_BG,1);
	for(new g; g < MAX_GATES; g++)
	{
		GateText_Info[g] = TextDrawCreate(470.000000,195.000000,"~y~~h~ID: ~w~1~n~~y~Model: ~w~2 ~n~~y~X: ~w~1000.0 ~n~~y~Y: ~w~1000.0 ~n~~y~Z: ~w~1000.0 ~n~~y~rX: ~w~1000.0 ~n~~y~rY: ~w~1000.0 ~n~~y~rZ: ~w~1000.0");
		TextDrawAlignment(GateText_Info[g],0);
		TextDrawBackgroundColor(GateText_Info[g],0x000000ff);
		TextDrawFont(GateText_Info[g],1);
		TextDrawLetterSize(GateText_Info[g],0.400000,1.650000);
		TextDrawColor(GateText_Info[g],0xffffffff);
		TextDrawSetOutline(GateText_Info[g],1);
		TextDrawSetProportional(GateText_Info[g],1);
		TextDrawSetShadow(GateText_Info[g],1);
		
		GateID[g] = -1;
		GateModelNumber[g] = -1;
	}
	
	for(new playerid, m = GetMaxPlayers(); playerid < m; playerid++) PlayerEditingGate[playerid] = -1;

    print("<|-----------------------------------------|>");
 	print("  .:[ - Gate Maker seif_gate by Seif - ]:.");
	print("<|-----------------------------------------|>");
	return 1;
}

public OnFilterScriptExit()
{
	TextDrawDestroy(GateText_BG);
    for(new g; g < MAX_GATES; g++)
	{
		TextDrawDestroy(GateText_Info[g]);
		Delete3DTextLabel(GateTextLabel[g]);
		if (IsValidObject(g) && GateID[g] != -1) DestroyObject(g);
	}
	return 1;
}

public OnPlayerConnect(playerid)
{
	PlayerEditingGate[playerid] = -1;
	return 1;
}

public OnPlayerDisconnect(playerid, reason)
{
	return 1;
}

public OnPlayerSpawn(playerid)
{
	return 1;
}

public OnPlayerDeath(playerid, killerid, reason)
{
	return 1;
}

public OnVehicleSpawn(vehicleid)
{
	return 1;
}

public OnVehicleDeath(vehicleid, killerid)
{
	return 1;
}

public OnPlayerText(playerid, text[])
{
	return 1;
}

public OnPlayerCommandText(playerid, cmdtext[])
{
    new cmd[128], idx, ent[10][128];
	if (seifcmd(cmdtext, cmd, "/addgate", idx, ent, ent[0]))
	{
	    if (!strlen(ent[0]))
		{
			SendFormatMessage(playerid, ORANGE, "USAGE: /addgate [model(0-%d)]", MaxGates);
			return 1;
		}
	    new model = strval(ent[0]);
	    if (model < 0 || model > MaxGates)
		{
			SendFormatMessage(playerid, RED, "Model IDs: 0 to %d", MaxGates);
			return 1;
		}
	    
	    new Float:X, Float:Y, Float:Z, Float:A;
	    GetPlayerPos(playerid, X, Y, Z);
	    GetPlayerFacingAngle(playerid, A);
	    X += (5.0 * floatsin(-A, degrees));
	    Y += (5.0 * floatcos(-A, degrees));
	    new gateid = CreateObject(GateModel[model], X, Y, Z, 0.0, 0.0, 0.0);
		GateID[gateid] = gateid;
		GateModelNumber[gateid] = model;
		format(cmdtext, 128, "Gate ID: %d\nModel #: %d", gateid, model);
		GateTextLabel[gateid] = Create3DTextLabel(cmdtext, GRAY, X, Y, Z, 30.0, 0);
	    SendFormatMessage(playerid, GREEN, "* Gate ID %d. Type '/editgate %d' to edit it, /delgate to delete it.", gateid, gateid);
		return 1;
	}
	if (seifcmd(cmdtext, cmd, "/editgate", idx, ent, ent[0]))
	{
	    if (PlayerEditingGate[playerid] != -1) return SendClientMessage(playerid, RED, "You're already editing a gate!");
	    if (!strlen(ent[0])) return SendClientMessage(playerid, ORANGE, "USAGE: /editgate [gateid]");
	    new id = strval(ent[0]);
	    if (!IsValidObject(GateID[id]))
		{
			SendFormatMessage(playerid, RED, "Gate %d doesn't exist.", id);
			return 1;
		}

	    new Float:X, Float:Y, Float:Z, Float:rx, Float:ry, Float:A, gateid = GateID[id];
	    GetObjectPos(GateID[id], X, Y, Z);
	    GetObjectRot(GateID[id], rx, ry, A);
	    X -= (5.0 * floatsin(-A, degrees));
	    Y -= (5.0 * floatcos(-A, degrees));
	    SetPlayerCameraPos(playerid, X, Y, Z);
	    X += (5.0 * floatsin(-A, degrees));
	    Y += (5.0 * floatcos(-A, degrees));
	    SetPlayerCameraLookAt(playerid, X, Y, Z);
	    PlayerEditingGate[playerid] = GateID[id];
	    PlayerEdit[playerid] = 1;
	    Delete3DTextLabel(GateTextLabel[gateid]);
	    TogglePlayerControllable(playerid, false);
	    SendFormatMessage(playerid, GREEN, "* Editing gate # %d.", gateid);
	    SendClientMessage(playerid, YELLOW, "CONTROLS: up/down key to chose what to edit on the menu | left/right key to edit the gate ...");
	    SendClientMessage(playerid, YELLOW, "CONTROLS: Enter/F key to confirm editing the gate | /saveallgates to save all gates.");
	    playergatetime[playerid] = SetTimerEx("EditGate", 100, 1, "d", playerid);
		return 1;
	}
	if (seifcmd(cmdtext, cmd, "/delgate", idx, ent, ent[0]))
	{
	    if (PlayerEditingGate[playerid] != -1) return SendClientMessage(playerid, RED, "You can't delete a gate while editing a gate! Press Enter/F to stop editing.");
	    if (!strlen(ent[0])) return SendClientMessage(playerid, ORANGE, "USAGE: /delgate [gateid]");
	    new id = strval(ent[0]);
	    if (!IsValidObject(GateID[id]))
		{
			SendFormatMessage(playerid, RED, "Gate %d doesn't exist.", id);
			return 1;
		}

	    GateModelNumber[GateID[id]] = -1;
	    Delete3DTextLabel(GateTextLabel[GateID[id]]);
	    DestroyObject(GateID[id]);
	    GateID[id] = -1;
	    SendFormatMessage(playerid, GREEN, "* Gate # %d deleted.", id);
	    SendClientMessage(playerid, YELLOW, "CONTROLS: up/down key to chose what to edit on the menu | left/right key to edit the gate ...");
	    SendClientMessage(playerid, YELLOW, "CONTROLS: Enter/F key to confirm editing the gate | /saveallgates to save all gates.");
	    playergatetime[playerid] = SetTimerEx("EditGate", 100, 1, "d", playerid);
		return 1;
	}
	if (!strcmp(cmdtext, "/saveallgates", true))
	{
	    new gcount;
	    new filemode:mode = (fexist("GatePositions.txt") ? io_append : io_write);
	    new File:file = fopen("GatePositions.txt", mode);
	    if (file)
	    {
	        new Float:x, Float:y, Float:z;
	        new Float:rx, Float:ry, Float:rz;
	        for(new o; o < MAX_GATES; o++)
	        {
	            if (!IsValidObject(o) || GateID[o] == -1) continue;
	            GetObjectPos(o, x, y, z);
	            GetObjectRot(o, rx, ry, rz);
	            format(cmdtext, 128, "CreateObject(%d, %f, %f, %f, %f, %f, %f); // Gate Maker seif_gate by Seif\n", GateModel[GateModelNumber[o]], x, y, z, rx, ry, rz);
	            fwrite(file, cmdtext);
	            gcount++;
	        }
	        fclose(file);
	    }
	    SendFormatMessage(playerid, LIGHTGREEN, "* %d gates saved!", gcount);
	    return 1;
	}
	return 0;
}

function EditGate(playerid)
{
	if (PlayerEditingGate[playerid] == -1)
	{
	    PlayerEdit[playerid] = 0;
	    KillTimer(playergatetime[playerid]);
	    return 1;
	}
	
	new gateid = PlayerEditingGate[playerid];
	new keys, updown, leftright;
	GetPlayerKeys(playerid, keys, updown, leftright);
	new Float:X, Float:Y, Float:Z, Float:rx, Float:ry, Float:rz;
    GetObjectPos(gateid, X, Y, Z);
    GetObjectRot(gateid, rx, ry, rz);
    new Float:speed = 0.1;
    
    if (updown == KEY_UP)
    {
        if (PlayerEdit[playerid] == 1) PlayerEdit[playerid] = 7;
        else PlayerEdit[playerid]--;
    }
    else if (updown == KEY_DOWN)
    {
        if (PlayerEdit[playerid] == 7) PlayerEdit[playerid] = 1;
        else PlayerEdit[playerid]++;
    }
	if (leftright == KEY_RIGHT)
	{
	    if (keys == KEY_SPRINT) speed = 0.5;
	    if (PlayerEdit[playerid] == 1)
	    {
			if (GateModelNumber[gateid] == MaxGates) GateModelNumber[gateid] = 0;
			else GateModelNumber[gateid]++;
	        DestroyObject(gateid);
	        
	        gateid = CreateObject(GateModel[GateModelNumber[gateid]], X, Y, Z, rx, ry, rz);
	        GateID[gateid] = gateid;
	    }
	    else if (PlayerEdit[playerid] == 2)
		{
			SetObjectPos(gateid, X+speed, Y, Z);
	    }
	    else if (PlayerEdit[playerid] == 3)
		{
			SetObjectPos(gateid, X, Y+speed, Z);
	    }
	    else if (PlayerEdit[playerid] == 4)
		{
			SetObjectPos(gateid, X, Y, Z+speed);
	    }
	    else if (PlayerEdit[playerid] == 5)
		{
			SetObjectRot(gateid, rx+speed, ry, rz);
	    }
	    else if (PlayerEdit[playerid] == 6)
		{
			SetObjectRot(gateid, rx, ry+speed, rz);
	    }
	    else if (PlayerEdit[playerid] == 7)
		{
			SetObjectRot(gateid, rx, ry, rz+speed);
	    }
    	X -= (5.0 * floatsin(-rz, degrees));
	    Y -= (5.0 * floatcos(-rz, degrees));
	    SetPlayerCameraPos(playerid, X, Y, Z);
	    X += (5.0 * floatsin(-rz, degrees));
	    Y += (5.0 * floatcos(-rz, degrees));
	    SetPlayerCameraLookAt(playerid, X, Y, Z);
	    X -= (10.0 * floatsin(-rz, degrees));
	    Y -= (10.0 * floatcos(-rz, degrees));
	    SetPlayerPos(playerid, X, Y, Z);
	    X += (10.0 * floatsin(-rz, degrees));
	    Y += (10.0 * floatcos(-rz, degrees));
	}
	else if (leftright == KEY_LEFT)
	{
	    if (keys == KEY_SPRINT) speed = 0.5;
	    if (PlayerEdit[playerid] == 1)
	    {
			if (GateModelNumber[gateid] == 0) GateModelNumber[gateid] = MaxGates;
			else GateModelNumber[gateid]--;
	        DestroyObject(gateid);

	        gateid = CreateObject(GateModel[GateModelNumber[gateid]], X, Y, Z, rx, ry, rz);
	        GateID[gateid] = gateid;
	    }
	    else if (PlayerEdit[playerid] == 2)
		{
			SetObjectPos(gateid, X-speed, Y, Z);
	    }
	    else if (PlayerEdit[playerid] == 3)
		{
			SetObjectPos(gateid, X, Y-speed, Z);
	    }
	    else if (PlayerEdit[playerid] == 4)
		{
			SetObjectPos(gateid, X, Y, Z-speed);
	    }
	    else if (PlayerEdit[playerid] == 5)
		{
			SetObjectRot(gateid, rx-speed, ry, rz);
	    }
	    else if (PlayerEdit[playerid] == 6)
		{
			SetObjectRot(gateid, rx, ry-speed, rz);
	    }
	    else if (PlayerEdit[playerid] == 7)
		{
			SetObjectRot(gateid, rx, ry, rz-speed);
	    }
    	X -= (5.0 * floatsin(-rz, degrees));
	    Y -= (5.0 * floatcos(-rz, degrees));
	    SetPlayerCameraPos(playerid, X, Y, Z);
	    X += (5.0 * floatsin(-rz, degrees));
	    Y += (5.0 * floatcos(-rz, degrees));
	    SetPlayerCameraLookAt(playerid, X, Y, Z);
	    X -= (10.0 * floatsin(-rz, degrees));
	    Y -= (10.0 * floatcos(-rz, degrees));
	    SetPlayerPos(playerid, X, Y, Z);
	    X += (10.0 * floatsin(-rz, degrees));
	    Y += (10.0 * floatcos(-rz, degrees));
	}
	new txt[256];
    switch (PlayerEdit[playerid])
	{
		case 1: format(txt, sizeof txt, "~y~~h~ID: ~w~%d~n~~r~Model: ~b~~<~%d~>~ ~n~~y~X: ~w~%f ~n~~y~Y: ~w~%f ~n~~y~Z: ~w~%f ~n~~y~rX: ~w~%f ~n~~y~rY: ~w~%f ~n~~y~rZ: ~w~%f", gateid, GateModelNumber[gateid], X, Y, Z, rx, ry, rz);
        case 2: format(txt, sizeof txt, "~y~~h~ID: ~w~%d~n~~y~Model: ~w~%d ~n~~r~X: ~b~~<~%f~>~ ~n~~y~Y: ~w~%f ~n~~y~Z: ~w~%f ~n~~y~rX: ~w~%f ~n~~y~rY: ~w~%f ~n~~y~rZ: ~w~%f", gateid, GateModelNumber[gateid], X, Y, Z, rx, ry, rz);
        case 3: format(txt, sizeof txt, "~y~~h~ID: ~w~%d~n~~y~Model: ~w~%d ~n~~y~X: ~w~%f ~n~~r~Y: ~b~~<~%f~>~ ~n~~y~Z: ~w~%f ~n~~y~rX: ~w~%f ~n~~y~rY: ~w~%f ~n~~y~rZ: ~w~%f", gateid, GateModelNumber[gateid], X, Y, Z, rx, ry, rz);
        case 4: format(txt, sizeof txt, "~y~~h~ID: ~w~%d~n~~y~Model: ~w~%d ~n~~y~X: ~w~%f ~n~~y~Y: ~w~%f ~n~~r~Z: ~b~~<~%f~>~ ~n~~y~rX: ~w~%f ~n~~y~rY: ~w~%f ~n~~y~rZ: ~w~%f", gateid, GateModelNumber[gateid], X, Y, Z, rx, ry, rz);
        case 5: format(txt, sizeof txt, "~y~~h~ID: ~w~%d~n~~y~Model: ~w~%d ~n~~y~X: ~w~%f ~n~~y~Y: ~w~%f ~n~~y~Z: ~w~%f ~n~~r~rX: ~b~~<~%f~>~ ~n~~y~rY: ~w~%f ~n~~y~rZ: ~w~%f", gateid, GateModelNumber[gateid], X, Y, Z, rx, ry, rz);
        case 6: format(txt, sizeof txt, "~y~~h~ID: ~w~%d~n~~y~Model: ~w~%d ~n~~y~X: ~w~%f ~n~~y~Y: ~w~%f ~n~~y~Z: ~w~%f ~n~~y~rX: ~w~%f ~n~~r~rY: ~b~~<~%f~>~ ~n~~y~rZ: ~w~%f", gateid, GateModelNumber[gateid], X, Y, Z, rx, ry, rz);
        case 7: format(txt, sizeof txt, "~y~~h~ID: ~w~%d~n~~y~Model: ~w~%d ~n~~y~X: ~w~%f ~n~~y~Y: ~w~%f ~n~~y~Z: ~w~%f ~n~~y~rX: ~w~%f ~n~~y~rY: ~w~%f ~n~~r~rZ: ~b~~<~%f~>~", gateid, GateModelNumber[gateid], X, Y, Z, rx, ry, rz);
	}
	TextDrawSetString(GateText_Info[gateid], txt);
	TextDrawShowForPlayer(playerid, GateText_BG);
	TextDrawShowForPlayer(playerid, GateText_Info[gateid]);
	
	if (keys == KEY_SECONDARY_ATTACK)
	{
	    PlayerEdit[playerid] = 0;
	    PlayerEditingGate[playerid] = -1;
	    KillTimer(playergatetime[playerid]);
	    SetCameraBehindPlayer(playerid);
	    TogglePlayerControllable(playerid, true);
	    format(txt, 128, "Gate ID: %d\nModel #: %d", gateid, GateModelNumber[gateid]);
		GateTextLabel[gateid] = Create3DTextLabel(txt, GRAY, X, Y, Z, 30.0, 0);
		TextDrawHideForPlayer(playerid, GateText_BG);
		TextDrawHideForPlayer(playerid, GateText_Info[gateid]);
	}
	return 1;
}

stock strtok(const string[], &index)
{
	new length = strlen(string);
	while ((index < length) && (string[index] <= ' '))
	{
		index++;
	}

	new offset = index;
	new result[64];
	while ((index < length) && (string[index] > ' ') && ((index - offset) < (sizeof(result) - 1)))
	{
		result[index - offset] = string[index];
		index++;
	}
	result[index - offset] = EOS;
	return result;
}

seifcmd(realcmdvar[], cmdvar[128], cmd[], index, const entry[][128], {Float,_}:...)
{
	cmdvar = strtok(realcmdvar, index);
	if (strcmp(cmdvar, cmd, true)) return 0;

	new argcount = numargs();
	new argument;
	for(new a = 5; a < argcount; a++)
	{
	    setarg(a, getarg(a), a+1);
	    entry[argument] = strtok(realcmdvar, index);
	    argument++;
	}
	return 1;
}
