/*
*	Created:			27.12.09
*	Author:				009
*	Last Modifed:		-
*	Description:		Стриммер 3D текстов, изменение любого параметра 
*/

#if defined _mode_3dtexts_included
  #endinput
#endif

#define _mode_3dtexts_included
#pragma library mode_3dtexts

// --------------------------------------------------
// includes
// --------------------------------------------------
#include "mode_debug"
#include "mode_interiors"
#include "mode_core"

// --------------------------------------------------
// defines
// --------------------------------------------------
#define MAX_STREAM_3DTEXTS 2000
#define TEXTS3D_DISTANCE 100.0
#define MAX_3DTEXT_STRING 512
#define INVALID_MODE_3DTEXT_ID -1

// --------------------------------------------------
// enums
// --------------------------------------------------
enum Mode3DTextsCoordInfo {
	Float:cPos[3],
	cModeInteriorId,
	cVirtualWorldId
};
enum Mode3DTextsAttachInfo {
	aType,
	aAttachedTo
};
enum Mode3DTextsInfo {
	bool:tActive,
	tText[MAX_3DTEXT_STRING],
	tColor,
	Float:tDrawDistance,
	tLOS,
	tCoordinates[Mode3DTextsCoordInfo],
	tAttach[Mode3DTextsAttachInfo]
};
enum Mode3DTextsPlayerInfo {
	PlayerText3D:p3DTextId[MAX_STREAM_3DTEXTS],
	pAttached3DTextId
};

// --------------------------------------------------
// news
// --------------------------------------------------
new Mode3DTexts[MAX_STREAM_3DTEXTS][Mode3DTextsInfo],
	Mode3DTexts_Player[MAX_PLAYERS][Mode3DTextsPlayerInfo],
	Mode3DTexts_Vehicle[MAX_VEHICLES],
	Mode3DTextsOffset,
	Mode3DTextsCount;

// --------------------------------------------------
// natives list (for pawno functions list)
// --------------------------------------------------
/*
native CreateMode3DText(Text[],Color,Float:X,Float:Y,Float:Z,Float:DrawDistance,ModeInterior,Premise,LOS);
native DestroyMode3DText(text3did);
native GetMode3DTextPos(text3did,&Float:X,&Float:Y,&Float:Z);
native SetMode3DTextPos(text3did,Float:X,Float:Y,Float:Z);
native GetMode3DTextModeInterior(text3did);
native SetMode3DTextModeInterior(text3did,modeinterior);
native GetMode3DTextVirtualWorld(text3did);
native SetMode3DTextVirtualWorld(text3did,virtualworld);
native AttachMode3DTextToPlayer(text3did,playerid,Float:oX,Float:oY,Float:oZ);
native AttachMode3DTextToVehicle(text3did,vehicleid,Float:oX,Float:oY,Float:oZ);
native DeAttachMode3DText(text3did);
native IsMode3DTextAttached(text3did);
native GetMode3DTextText(text3did);
native SetMode3DTextText(text3did,Text[]);
native GetMode3DTextColor(text3did);
native SetMode3DTextColor(text3did,Color);
native Float:GetMode3DTextDrawDistance(text3did);
native SetMode3DTextDrawDistance(text3did,Float:DrawDistance);
native IsMode3DTextNeedToShow(playerid,text3did);
*/

// --------------------------------------------------
// stocks
// --------------------------------------------------
stock CreateMode3DText(Text[],Color,Float:X,Float:Y,Float:Z,Float:DrawDistance,ModeInterior,VirtualWorld,LOS)
{
	Debug(DEBUG_START,"CreateMode3DText(%s,%d,%f,%f,%f,%f,%d,%d,%d)",Text,Color,X,Y,Z,DrawDistance,ModeInterior,VirtualWorld,LOS);
	for(new text3did = Mode3DTextsOffset;text3did < MAX_STREAM_3DTEXTS;text3did++)
	{
		if(Mode3DTexts[text3did][tActive] == true) continue;
		Debug(DEBUG_ACTION,"Finded free slot,id = %d , set main data",text3did);
		Mode3DTexts[text3did][tActive] = true;
		format(Mode3DTexts[text3did][tText],MAX_3DTEXT_STRING,Text);
		Mode3DTexts[text3did][tColor] = Color;
		Mode3DTexts[text3did][tDrawDistance] = DrawDistance;
		Mode3DTexts[text3did][tLOS] = LOS;
		Debug(DEBUG_ACTION,"Set coordinates data");
		Mode3DTexts[text3did][tCoordinates][cPos][0] = X;
		Mode3DTexts[text3did][tCoordinates][cPos][1] = Y;
		Mode3DTexts[text3did][tCoordinates][cPos][2] = Z;
		Mode3DTexts[text3did][tCoordinates][cModeInteriorId] = ModeInterior;
		Mode3DTexts[text3did][tCoordinates][cVirtualWorldId] = VirtualWorld;
		Debug(DEBUG_ACTION,"Set attach data");
		Mode3DTexts[text3did][tAttach][aType] = TEXT3D_ATTACH_NONE;
		Mode3DTexts[text3did][tAttach][aAttachedTo] = INVALID_TEXT3D_ATTACH_ID;
		Debug(DEBUG_ACTION,"Set offset data(old: %d,%d)",Mode3DTextsOffset,Mode3DTextsCount);
		Mode3DTextsOffset = text3did;
		if(Mode3DTextsCount < text3did) Mode3DTextsCount = text3did;
		Debug(DEBUG_ACTION,"New offset data: %d,%d",Mode3DTextsOffset,Mode3DTextsCount);
		Debug(DEBUG_END,"CreateMode3DText(reason: complete, id = %d)",text3did);
		return text3did;
	}
	Debug(DEBUG_END,"CreateMode3DText(reason: all slots used)");
	print("[WARNING] Mode 3dtexts -> CreateMode3DText (all slots used)");
	return 0;
}

stock DestroyMode3DText(text3did)
{
	Debug(DEBUG_START,"DestroyMode3DText(%d)",text3did);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"DestroyMode3DText(reason: error)");
		printf("[ERROR] Mode 3dtexts -> DestroyMode3DText (try destroy not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	Debug(DEBUG_ACTION,"Delete main data",text3did);
	Mode3DTexts[text3did][tActive] = false;
	format(Mode3DTexts[text3did][tText],MAX_3DTEXT_STRING,"");
	Mode3DTexts[text3did][tColor] = 0;
	Mode3DTexts[text3did][tDrawDistance] = 0.0;
	Mode3DTexts[text3did][tLOS] = 0;
	Debug(DEBUG_ACTION,"Delete coordinates data");
	for(new i = 0;i < 3;i++) Mode3DTexts[text3did][tCoordinates][cPos][i] = 0.0;
	Mode3DTexts[text3did][tCoordinates][cModeInteriorId] = 0;
	Mode3DTexts[text3did][tCoordinates][cVirtualWorldId] = 0;
	Debug(DEBUG_ACTION,"Delete attach data");
	switch(Mode3DTexts[text3did][tAttach][aType])
	{
		case TEXT3D_ATTACH_PLAYER: Mode3DTexts_Player[ Mode3DTexts[text3did][tAttach][aAttachedTo] ][pAttached3DTextId] = INVALID_MODE_3DTEXT_ID;
		case TEXT3D_ATTACH_VEHICLE: Mode3DTexts_Vehicle[ Mode3DTexts[text3did][tAttach][aAttachedTo] ] = INVALID_MODE_3DTEXT_ID;
	}
	Mode3DTexts[text3did][tAttach][aType] = TEXT3D_ATTACH_NONE;
	Mode3DTexts[text3did][tAttach][aAttachedTo] = INVALID_TEXT3D_ATTACH_ID;
	for(new playerid = 0;playerid <= GetMaxPlayer();playerid++)
	{
		if(!IsPlayerConnected(playerid)) continue;
		if(Mode3DTexts_Player[playerid][p3DTextId][text3did] == INVALID_3DTEXT_ID) continue;
		DeletePlayer3DTextLabel(playerid,Mode3DTexts_Player[playerid][p3DTextId][text3did]);
		Mode3DTexts_Player[playerid][p3DTextId][text3did] = INVALID_3DTEXT_ID;
	}
	Debug(DEBUG_ACTION,"Delete offset data(old: %d,%d)",Mode3DTextsOffset,Mode3DTextsCount);
	if(Mode3DTextsOffset > text3did) Mode3DTextsOffset = text3did;
	if(Mode3DTextsCount == text3did) 
	{
		do Mode3DTextsCount--;
		while((Mode3DTexts[ Mode3DTextsCount ][tActive] == false) && (Mode3DTextsCount > 0));
	}
	Debug(DEBUG_ACTION,"New offset data: %d,%d",Mode3DTextsOffset,Mode3DTextsCount);
	Debug(DEBUG_END,"DestroyMode3DText(reason: complete)");
	return 1;
}

stock GetMode3DTextPos(text3did,&Float:X,&Float:Y,&Float:Z)
{
	Debug(DEBUG_START,"GetMode3DTextPos(%d)",text3did);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"GetMode3DTextPos(reason: error)");
		printf("[ERROR] Mode 3dtexts -> GetMode3DTextPos (try get pos not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	switch(Mode3DTexts[text3did][tAttach][aType])
	{
		case TEXT3D_ATTACH_NONE:
		{
			Debug(DEBUG_ACTION,"3DText not attached");
			X = Mode3DTexts[text3did][tCoordinates][cPos][0];
			Y = Mode3DTexts[text3did][tCoordinates][cPos][1];
			Z = Mode3DTexts[text3did][tCoordinates][cPos][2];
			Debug(DEBUG_END,"GetMode3DTextPos(reason: complete)");
			return 1;
		}
		case TEXT3D_ATTACH_PLAYER:
		{
			Debug(DEBUG_ACTION,"3DText attached to player");
			if(!IsPlayerConnected(Mode3DTexts[text3did][tAttach][aAttachedTo]))
			{
				Debug(DEBUG_END,"GetMode3DTextPos(reason: error)");
				printf("[ERROR] Mode 3dtexts -> GetMode3DTextPos (3dtext attached to offline player, text3did = %d, playerid = %d)",text3did,Mode3DTexts[text3did][tAttach][aAttachedTo]);
				return 0;
			}
			new Float:angle;
			GetPlayerFacingAngle(Mode3DTexts[text3did][tAttach][aAttachedTo],angle);	
			GetPlayerPos(Mode3DTexts[text3did][tAttach][aAttachedTo],X,Y,Z);
			Debug(DEBUG_ACTION,"player pos: %f,%f,%f angle %f",X,Y,Z,angle);
			X += (Mode3DTexts[text3did][tCoordinates][cPos][0] * floatsin(-(angle - 90.0), degrees)) + (Mode3DTexts[text3did][tCoordinates][cPos][1] * floatsin(-angle, degrees));
			Y += (Mode3DTexts[text3did][tCoordinates][cPos][0] * floatcos(-(angle - 90.0), degrees)) + (Mode3DTexts[text3did][tCoordinates][cPos][1] * floatcos(-angle, degrees));
			Z += Mode3DTexts[text3did][tCoordinates][cPos][2];
			Debug(DEBUG_END,"GetMode3DTextPos(reason: complete)");
			return 1;
		}
		case TEXT3D_ATTACH_VEHICLE: 
		{
			Debug(DEBUG_ACTION,"3DText attached to vehicle");
			new Float:angle;
			GetVehicleZAngle(Mode3DTexts[text3did][tAttach][aAttachedTo],angle);	
			GetVehiclePos(Mode3DTexts[text3did][tAttach][aAttachedTo],X,Y,Z);
			Debug(DEBUG_ACTION,"vehicle pos: %f,%f,%f angle %f",X,Y,Z,angle);
			X += (Mode3DTexts[text3did][tCoordinates][cPos][0] * floatsin(-(angle - 90.0), degrees)) + (Mode3DTexts[text3did][tCoordinates][cPos][1] * floatsin(-angle, degrees));
			Y += (Mode3DTexts[text3did][tCoordinates][cPos][0] * floatcos(-(angle - 90.0), degrees)) + (Mode3DTexts[text3did][tCoordinates][cPos][1] * floatcos(-angle, degrees));
			Z += Mode3DTexts[text3did][tCoordinates][cPos][2];
			Debug(DEBUG_END,"GetMode3DTextPos(reason: complete)");
			return 1;
		}
	}
	Debug(DEBUG_END,"GetMode3DTextPos(reason: error)");
	printf("[ERROR] Mode 3dtexts -> GetMode3DTextPos (unknown 3dtext's status, text3did = %d)",text3did);
	return 0;
}

stock SetMode3DTextPos(text3did,Float:X,Float:Y,Float:Z)
{
	Debug(DEBUG_START,"SetMode3DTextPos(%d)",text3did);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"SetMode3DTextPos(reason: error)");
		printf("[ERROR] Mode 3dtexts -> SetMode3DTextPos (try set pos not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	switch(Mode3DTexts[text3did][tAttach][aType])
	{
		case TEXT3D_ATTACH_NONE:
		{
			Debug(DEBUG_ACTION,"3DText not attached");
			Mode3DTexts[text3did][tCoordinates][cPos][0] = X;
			Mode3DTexts[text3did][tCoordinates][cPos][1] = Y;
			Mode3DTexts[text3did][tCoordinates][cPos][2] = Z;
			Debug(DEBUG_ACTION,"destroy 3dtext for players and show on new pos");
			for(new playerid = 0;playerid <= GetMaxPlayer();playerid++)
			{
				if(!IsPlayerConnected(playerid)) continue;
				if(Mode3DTexts_Player[playerid][p3DTextId][text3did] == INVALID_3DTEXT_ID) continue;
				DeletePlayer3DTextLabel(playerid,Mode3DTexts_Player[playerid][p3DTextId][text3did]);
				Mode3DTexts_Player[playerid][p3DTextId][text3did] = INVALID_3DTEXT_ID;
				if(IsMode3DTextNeedToShow(playerid,text3did)) Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],INVALID_PLAYER_ID,INVALID_VEHICLE_ID,Mode3DTexts[text3did][tLOS]);
			}
			Debug(DEBUG_END,"SetMode3DTextPos(reason: complete)");
			return 1;
		}
		case TEXT3D_ATTACH_PLAYER:
		{
			Debug(DEBUG_ACTION,"3DText attached to player");
			if(!IsPlayerConnected(Mode3DTexts[text3did][tAttach][aAttachedTo]))
			{
				Debug(DEBUG_END,"SetMode3DTextPos(reason: error)");
				printf("[ERROR] Mode 3dtexts -> SetMode3DTextPos (3dtext attached to offline player, text3did = %d, playerid = %d)",text3did,Mode3DTexts[text3did][tAttach][aAttachedTo]);
				return 0;
			}
			Mode3DTexts[text3did][tCoordinates][cPos][0] = X;
			Mode3DTexts[text3did][tCoordinates][cPos][1] = Y;
			Mode3DTexts[text3did][tCoordinates][cPos][2] = Z;
			Debug(DEBUG_ACTION,"destroy 3dtext for players and show on new pos");
			for(new playerid = 0;playerid <= GetMaxPlayer();playerid++)
			{
				if(!IsPlayerConnected(playerid)) continue;
				if(Mode3DTexts_Player[playerid][p3DTextId][text3did] == INVALID_3DTEXT_ID) continue;
				DeletePlayer3DTextLabel(playerid,Mode3DTexts_Player[playerid][p3DTextId][text3did]);
				Mode3DTexts_Player[playerid][p3DTextId][text3did] = INVALID_3DTEXT_ID;
				if(IsMode3DTextNeedToShow(playerid,text3did)) Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],Mode3DTexts[text3did][tAttach][aAttachedTo],INVALID_VEHICLE_ID,Mode3DTexts[text3did][tLOS]);
			}
			Debug(DEBUG_END,"SetMode3DTextPos(reason: complete)");
			return 1;
		}
		case TEXT3D_ATTACH_VEHICLE: 
		{
			Debug(DEBUG_ACTION,"3DText attached to vehicle");
			Mode3DTexts[text3did][tCoordinates][cPos][0] = X;
			Mode3DTexts[text3did][tCoordinates][cPos][1] = Y;
			Mode3DTexts[text3did][tCoordinates][cPos][2] = Z;
			Debug(DEBUG_ACTION,"destroy 3dtext for players and show on new pos");
			for(new playerid = 0;playerid <= GetMaxPlayer();playerid++)
			{
				if(!IsPlayerConnected(playerid)) continue;
				if(Mode3DTexts_Player[playerid][p3DTextId][text3did] == INVALID_3DTEXT_ID) continue;
				DeletePlayer3DTextLabel(playerid,Mode3DTexts_Player[playerid][p3DTextId][text3did]);
				Mode3DTexts_Player[playerid][p3DTextId][text3did] = INVALID_3DTEXT_ID;
				if(IsMode3DTextNeedToShow(playerid,text3did)) Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],INVALID_PLAYER_ID,Mode3DTexts[text3did][tAttach][aAttachedTo],Mode3DTexts[text3did][tLOS]);
			}
			Debug(DEBUG_END,"SetMode3DTextPos(reason: complete)");
			return 1;
		}
	}
	Debug(DEBUG_END,"SetMode3DTextPos(reason: error)");
	printf("[ERROR] Mode 3dtexts -> SetMode3DTextPos (unknown 3dtext's status, text3did = %d)",text3did);
	return 0;
}

stock GetMode3DTextModeInterior(text3did)
{
	Debug(DEBUG_START,"GetMode3DTextModeInterior(%d)",text3did);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"GetMode3DTextModeInterior(reason: error)");
		printf("[ERROR] Mode 3dtexts -> GetMode3DTextModeInterior (try get mode interior not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	switch(Mode3DTexts[text3did][tAttach][aType])
	{
		case TEXT3D_ATTACH_NONE,TEXT3D_ATTACH_VEHICLE:
		{
			Debug(DEBUG_END,"GetMode3DTextModeInterior(reason: complete)");
			return Mode3DTexts[text3did][tCoordinates][cModeInteriorId];
		}
		case TEXT3D_ATTACH_PLAYER:
		{
			Debug(DEBUG_ACTION,"3DText attached to player");
			if(!IsPlayerConnected(Mode3DTexts[text3did][tAttach][aAttachedTo]))
			{
				Debug(DEBUG_END,"GetMode3DTextModeInterior(reason: error)");
				printf("[ERROR] Mode 3dtexts -> GetMode3DTextModeInterior (3dtext attached to offline player, text3did = %d, playerid = %d)",text3did,Mode3DTexts[text3did][tAttach][aAttachedTo]);
				return 0;
			}
			Debug(DEBUG_END,"GetMode3DTextModeInterior(reason: complete)");
			return GetPlayerModeInterior(Mode3DTexts[text3did][tAttach][aAttachedTo]);
		}
	}
	Debug(DEBUG_END,"GetMode3DTextModeInterior(reason: error)");
	printf("[ERROR] Mode 3dtexts -> GetMode3DTextModeInterior (unknown 3dtext's status, text3did = %d)",text3did);
	return 0;
}

stock SetMode3DTextModeInterior(text3did,modeinterior)
{
	Debug(DEBUG_START,"SetMode3DTextModeInterior(%d,%d)",text3did,modeinterior);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"SetMode3DTextModeInterior(reason: error)");
		printf("[ERROR] Mode 3dtexts -> SetMode3DTextModeInterior (try set mode interior not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	switch(Mode3DTexts[text3did][tAttach][aType])
	{
		case TEXT3D_ATTACH_NONE:
		{
			Debug(DEBUG_END,"SetMode3DTextModeInterior(reason: complete)");
			Mode3DTexts[text3did][tCoordinates][cModeInteriorId] = modeinterior;
			return 1;
		}
		case TEXT3D_ATTACH_PLAYER,TEXT3D_ATTACH_VEHICLE:
		{
			Debug(DEBUG_END,"SetMode3DTextModeInterior(reason: error)");
			printf("[ERROR] Mode 3dtexts -> SetMode3DTextModeInterior (try set mode interior attached 3D text, text3did = %d)",text3did);
			return 0;
		}
	}
	Debug(DEBUG_END,"SetMode3DTextModeInterior(reason: error)");
	printf("[ERROR] Mode 3dtexts -> SetMode3DTextModeInterior (unknown 3dtext's status, text3did = %d)",text3did);
	return 0;
}

stock GetMode3DTextVirtualWorld(text3did)
{
	Debug(DEBUG_START,"GetMode3DTextVirtualWorld(%d)",text3did);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"GetMode3DTextVirtualWorld(reason: error)");
		printf("[ERROR] Mode 3dtexts -> GetMode3DTextVirtualWorld (try get world not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	switch(Mode3DTexts[text3did][tAttach][aType])
	{
		case TEXT3D_ATTACH_NONE,TEXT3D_ATTACH_VEHICLE:
		{
			Debug(DEBUG_END,"GetMode3DTextVirtualWorld(reason: complete)");
			return Mode3DTexts[text3did][tCoordinates][cVirtualWorldId];
		}
		case TEXT3D_ATTACH_PLAYER:
		{
			Debug(DEBUG_ACTION,"3DText attached to player");
			if(!IsPlayerConnected(Mode3DTexts[text3did][tAttach][aAttachedTo]))
			{
				Debug(DEBUG_END,"GetMode3DTextVirtualWorld(reason: error)");
				printf("[ERROR] Mode 3dtexts -> GetMode3DTextVirtualWorld (3dtext attached to offline player, text3did = %d, playerid = %d)",text3did,Mode3DTexts[text3did][tAttach][aAttachedTo]);
				return 0;
			}
			Debug(DEBUG_END,"GetMode3DTextVirtualWorld(reason: complete)");
			return GetPlayerPremise(Mode3DTexts[text3did][tAttach][aAttachedTo]);
		}
	}
	Debug(DEBUG_END,"GetMode3DTextVirtualWorld(reason: error)");
	printf("[ERROR] Mode 3dtexts -> GetMode3DTextVirtualWorld (unknown 3dtext's status, text3did = %d)",text3did);
	return 0;
}

stock SetMode3DTextVirtualWorld(text3did,virtualworld)
{
	Debug(DEBUG_START,"SetMode3DTextVirtualWorld(%d,%d)",text3did,virtualworld);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"SetMode3DTextVirtualWorld(reason: error)");
		printf("[ERROR] Mode 3dtexts -> SetMode3DTextVirtualWorld (try set world not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	switch(Mode3DTexts[text3did][tAttach][aType])
	{
		case TEXT3D_ATTACH_NONE:
		{
			Debug(DEBUG_END,"SetMode3DTextVirtualWorld(reason: complete)");
			Mode3DTexts[text3did][tCoordinates][cVirtualWorldId] = virtualworld;
			return 1;
		}
		case TEXT3D_ATTACH_PLAYER,TEXT3D_ATTACH_VEHICLE:
		{
			Debug(DEBUG_END,"SetMode3DTextVirtualWorld(reason: error)");
			printf("[ERROR] Mode 3dtexts -> SetMode3DTextVirtualWorld (try set world attached 3D text, text3did = %d)",text3did);
			return 0;
		}
	}
	Debug(DEBUG_END,"SetMode3DTextVirtualWorld(reason: error)");
	printf("[ERROR] Mode 3dtexts -> SetMode3DTextVirtualWorld (unknown 3dtext's status, text3did = %d)",text3did);
	return 0;
}

stock AttachMode3DTextToPlayer(text3did,playerid,Float:oX,Float:oY,Float:oZ)
{
	Debug(DEBUG_START,"AttachMode3DTextToPlayer(%d,%d,%f,%f,%f)",text3did,playerid,oX,oY,oZ);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"AttachMode3DTextToPlayer(reason: error)");
		printf("[ERROR] Mode 3dtexts -> AttachMode3DTextToPlayer (try attach not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	if(Mode3DTexts[text3did][tAttach][aType] != TEXT3D_ATTACH_NONE)
	{
		Debug(DEBUG_END,"AttachMode3DTextToPlayer(reason: error)");
		printf("[ERROR] Mode 3dtexts -> AttachMode3DTextToPlayer (try attach also attached 3dtext, text3did = %d)",text3did);
		return 0;
	}
	if(!IsPlayerConnected(playerid))
	{
		Debug(DEBUG_END,"AttachMode3DTextToPlayer(reason: error)");
		printf("[ERROR] Mode 3dtexts -> AttachMode3DTextToPlayer (try attach 3dtext to offline player, text3did = %d, playerid = %d)",text3did,playerid);
		return 0;
	}
	Debug(DEBUG_ACTION,"set attaching data");
	Mode3DTexts[text3did][tCoordinates][cPos][0] = oX;
	Mode3DTexts[text3did][tCoordinates][cPos][1] = oY;
	Mode3DTexts[text3did][tCoordinates][cPos][2] = oZ;
	Mode3DTexts[text3did][tAttach][aType] = TEXT3D_ATTACH_PLAYER;
	Mode3DTexts[text3did][tAttach][aAttachedTo] = playerid;
	Debug(DEBUG_ACTION,"destroy 3dtext for players and show attached");
	for(new player = 0;player <= GetMaxPlayer();player++)
	{
		if(!IsPlayerConnected(player)) continue;
		if(Mode3DTexts_Player[player][p3DTextId][text3did] == INVALID_3DTEXT_ID) continue;
		DeletePlayer3DTextLabel(player,Mode3DTexts_Player[player][p3DTextId][text3did]);
		Mode3DTexts_Player[player][p3DTextId][text3did] = INVALID_3DTEXT_ID;
		if(IsMode3DTextNeedToShow(player,text3did)) Mode3DTexts_Player[player][p3DTextId][text3did] = CreatePlayer3DTextLabel(player,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],Mode3DTexts[text3did][tAttach][aAttachedTo],INVALID_VEHICLE_ID,Mode3DTexts[text3did][tLOS]);
	}
	Debug(DEBUG_END,"AttachMode3DTextToPlayer(reason: complete)");
	return 1;
}

stock AttachMode3DTextToVehicle(text3did,vehicleid,Float:oX,Float:oY,Float:oZ)
{
	Debug(DEBUG_START,"AttachMode3DTextToVehicle(%d,%d,%f,%f,%f)",text3did,vehicleid,oX,oY,oZ);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"AttachMode3DTextToVehicle(reason: error)");
		printf("[ERROR] Mode 3dtexts -> AttachMode3DTextToVehicle (try attach not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	if(Mode3DTexts[text3did][tAttach][aType] != TEXT3D_ATTACH_NONE)
	{
		Debug(DEBUG_END,"AttachMode3DTextToVehicle(reason: error)");
		printf("[ERROR] Mode 3dtexts -> AttachMode3DTextToVehicle (try attach also attached 3dtext, text3did = %d)",text3did);
		return 0;
	}
	Debug(DEBUG_ACTION,"set attaching data");
	Mode3DTexts[text3did][tCoordinates][cPos][0] = oX;
	Mode3DTexts[text3did][tCoordinates][cPos][1] = oY;
	Mode3DTexts[text3did][tCoordinates][cPos][2] = oZ;
	Mode3DTexts[text3did][tAttach][aType] = TEXT3D_ATTACH_VEHICLE;
	Mode3DTexts[text3did][tAttach][aAttachedTo] = vehicleid;
	Debug(DEBUG_ACTION,"destroy 3dtext for players and show attached");
	for(new player = 0;player <= GetMaxPlayer();player++)
	{
		if(!IsPlayerConnected(player)) continue;
		if(Mode3DTexts_Player[player][p3DTextId][text3did] == INVALID_3DTEXT_ID) continue;
		DeletePlayer3DTextLabel(player,Mode3DTexts_Player[player][p3DTextId][text3did]);
		Mode3DTexts_Player[player][p3DTextId][text3did] = INVALID_3DTEXT_ID;
		if(IsMode3DTextNeedToShow(player,text3did)) Mode3DTexts_Player[player][p3DTextId][text3did] = CreatePlayer3DTextLabel(player,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],INVALID_PLAYER_ID,Mode3DTexts[text3did][tAttach][aAttachedTo],Mode3DTexts[text3did][tLOS]);
	}
	Debug(DEBUG_END,"AttachMode3DTextToVehicle(reason: complete)");
	return 1;
}

stock DeAttachMode3DText(text3did)
{
	Debug(DEBUG_START,"DeAttachMode3DText(%d)",text3did);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"DeAttachMode3DText(reason: error)");
		printf("[ERROR] Mode 3dtexts -> DeAttachMode3DText (try deattach not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	if(Mode3DTexts[text3did][tAttach][aType] == TEXT3D_ATTACH_NONE)
	{
		Debug(DEBUG_END,"DeAttachMode3DText(reason: error)");
		printf("[ERROR] Mode 3dtexts -> DeAttachMode3DText (try deattach not attached 3dtext, text3did = %d)",text3did);
		return 0;
	}
	Debug(DEBUG_ACTION,"delete attaching data");
	switch(Mode3DTexts[text3did][tAttach][aType])
	{
		case TEXT3D_ATTACH_PLAYER:
		{
			Debug(DEBUG_ACTION,"3DText attached to player");
			if(!IsPlayerConnected(Mode3DTexts[text3did][tAttach][aAttachedTo]))
			{
				Debug(DEBUG_END,"DeAttachMode3DText(reason: error)");
				printf("[ERROR] Mode 3dtexts -> DeAttachMode3DText (3dtext attached to offline player, text3did = %d, playerid = %d)",text3did,Mode3DTexts[text3did][tAttach][aAttachedTo]);
				return 0;
			}
			new Float:angle,
				Float:X,
				Float:Y,
				Float:Z;
			GetPlayerFacingAngle(Mode3DTexts[text3did][tAttach][aAttachedTo],angle);	
			GetPlayerPos(Mode3DTexts[text3did][tAttach][aAttachedTo],X,Y,Z);
			Debug(DEBUG_ACTION,"player pos: %f,%f,%f angle %f",X,Y,Z,angle);
			X += (Mode3DTexts[text3did][tCoordinates][cPos][0] * floatsin(-(angle - 90.0), degrees)) + (Mode3DTexts[text3did][tCoordinates][cPos][1] * floatsin(-angle, degrees));
			Y += (Mode3DTexts[text3did][tCoordinates][cPos][0] * floatcos(-(angle - 90.0), degrees)) + (Mode3DTexts[text3did][tCoordinates][cPos][1] * floatcos(-angle, degrees));
			Z += Mode3DTexts[text3did][tCoordinates][cPos][2];
		}
		case TEXT3D_ATTACH_VEHICLE: 
		{
			Debug(DEBUG_ACTION,"3DText attached to vehicle");
			new Float:angle,
				Float:X,
				Float:Y,
				Float:Z;
			GetVehicleZAngle(Mode3DTexts[text3did][tAttach][aAttachedTo],angle);	
			GetVehiclePos(Mode3DTexts[text3did][tAttach][aAttachedTo],X,Y,Z);
			Debug(DEBUG_ACTION,"player pos: %f,%f,%f angle %f",X,Y,Z,angle);
			X += (Mode3DTexts[text3did][tCoordinates][cPos][0] * floatsin(-(angle - 90.0), degrees)) + (Mode3DTexts[text3did][tCoordinates][cPos][1] * floatsin(-angle, degrees));
			Y += (Mode3DTexts[text3did][tCoordinates][cPos][0] * floatcos(-(angle - 90.0), degrees)) + (Mode3DTexts[text3did][tCoordinates][cPos][1] * floatcos(-angle, degrees));
			Z += Mode3DTexts[text3did][tCoordinates][cPos][2];
		}
	}
	Mode3DTexts[text3did][tCoordinates][cPos][0] = X;
	Mode3DTexts[text3did][tCoordinates][cPos][1] = Y;
	Mode3DTexts[text3did][tCoordinates][cPos][2] = Z;
	Mode3DTexts[text3did][tAttach][aType] = TEXT3D_ATTACH_NONE;
	Mode3DTexts[text3did][tAttach][aAttachedTo] = 0;
	Debug(DEBUG_ACTION,"destroy 3dtext for players and show deattached");
	for(new player = 0;player <= GetMaxPlayer();player++)
	{
		if(!IsPlayerConnected(player)) continue;
		if(Mode3DTexts_Player[player][p3DTextId][text3did] == INVALID_3DTEXT_ID) continue;
		DeletePlayer3DTextLabel(player,Mode3DTexts_Player[player][p3DTextId][text3did]);
		Mode3DTexts_Player[player][p3DTextId][text3did] = INVALID_3DTEXT_ID;
		if(IsMode3DTextNeedToShow(player,text3did)) Mode3DTexts_Player[player][p3DTextId][text3did] = CreatePlayer3DTextLabel(player,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],INVALID_PLAYER_ID,INVALID_VEHICLE_ID,Mode3DTexts[text3did][tLOS]);
	}
	Debug(DEBUG_END,"DeAttachMode3DText(reason: complete)");
	return 1;
}

stock IsMode3DTextAttached(text3did)
{
	Debug(DEBUG_START,"DeAttachMode3DText(%d)",text3did);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"DeAttachMode3DText(reason: error)");
		printf("[ERROR] Mode 3dtexts -> DeAttachMode3DText (get attach status not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	Debug(DEBUG_END,"DeAttachMode3DText(reason: complete)");
	if(Mode3DTexts[text3did][tAttach][aType] == TEXT3D_ATTACH_NONE) return 0;
	return 1;
}

stock GetMode3DTextText(text3did)
{
	Debug(DEBUG_START,"GetMode3DTextText(%d)",text3did);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"GetMode3DTextText(reason: error)");
		printf("[ERROR] Mode 3dtexts -> GetMode3DTextText (get text not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	Debug(DEBUG_END,"GetMode3DTextText(reason: complete)");
	return Mode3DTexts[text3did][tText];
}

stock SetMode3DTextText(text3did,Text[])
{
	Debug(DEBUG_START,"SetMode3DTextText(%d,%s)",text3did,text);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"SetMode3DTextText(reason: error)");
		printf("[ERROR] Mode 3dtexts -> SetMode3DTextText (set text not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	format(Mode3DTexts[text3did][tText],MAX_3DTEXT_STRING,Text);
	for(new playerid = 0;playerid <= GetMaxPlayer();playerid++)
	{
		if(!IsPlayerConnected(playerid)) continue;
		if(Mode3DTexts_Player[playerid][p3DTextId][text3did] == INVALID_3DTEXT_ID) continue;
		DeletePlayer3DTextLabel(playerid,Mode3DTexts_Player[playerid][p3DTextId][text3did]);
		Mode3DTexts_Player[playerid][p3DTextId][text3did] = INVALID_3DTEXT_ID;
		if(IsMode3DTextNeedToShow(playerid,text3did))
		{
			switch(Mode3DTexts[text3did][tAttach][aType])
			{
				case TEXT3D_ATTACH_NONE: Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],INVALID_PLAYER_ID,INVALID_VEHICLE_ID,Mode3DTexts[text3did][tLOS]);
				case TEXT3D_ATTACH_PLAYER: Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],Mode3DTexts[text3did][tAttach][aAttachedTo],INVALID_VEHICLE_ID,Mode3DTexts[text3did][tLOS]);
				case TEXT3D_ATTACH_VEHICLE: Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],INVALID_PLAYER_ID,Mode3DTexts[text3did][tAttach][aAttachedTo],Mode3DTexts[text3did][tLOS]);
			}
		}
	}
	Debug(DEBUG_END,"SetMode3DTextText(reason: complete)");
	return 1;
}

stock GetMode3DTextColor(text3did)
{
	Debug(DEBUG_START,"GetMode3DTextColor(%d)",text3did);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"GetMode3DTextColor(reason: error)");
		printf("[ERROR] Mode 3dtexts -> GetMode3DTextColor (get color not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	Debug(DEBUG_END,"GetMode3DTextColor(reason: complete)");
	return Mode3DTexts[text3did][tColor];
}

stock SetMode3DTextColor(text3did,Color)
{
	Debug(DEBUG_START,"SetMode3DTextColor(%d,%d)",text3did,Color);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"SetMode3DTextColor(reason: error)");
		printf("[ERROR] Mode 3dtexts -> SetMode3DTextColor (set color not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	Mode3DTexts[text3did][tColor] = Color;
	for(new playerid = 0;playerid <= GetMaxPlayer();playerid++)
	{
		if(!IsPlayerConnected(playerid)) continue;
		if(Mode3DTexts_Player[playerid][p3DTextId][text3did] == INVALID_3DTEXT_ID) continue;
		DeletePlayer3DTextLabel(playerid,Mode3DTexts_Player[playerid][p3DTextId][text3did]);
		Mode3DTexts_Player[playerid][p3DTextId][text3did] = INVALID_3DTEXT_ID;
		if(IsMode3DTextNeedToShow(playerid,text3did))
		{
			switch(Mode3DTexts[text3did][tAttach][aType])
			{
				case TEXT3D_ATTACH_NONE: Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],INVALID_PLAYER_ID,INVALID_VEHICLE_ID,Mode3DTexts[text3did][tLOS]);
				case TEXT3D_ATTACH_PLAYER: Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],Mode3DTexts[text3did][tAttach][aAttachedTo],INVALID_VEHICLE_ID,Mode3DTexts[text3did][tLOS]);
				case TEXT3D_ATTACH_VEHICLE: Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],INVALID_PLAYER_ID,Mode3DTexts[text3did][tAttach][aAttachedTo],Mode3DTexts[text3did][tLOS]);
			}
		}
	}
	Debug(DEBUG_END,"SetMode3DTextColor(reason: complete)");
	return 1;
}

stock Float:GetMode3DTextDrawDistance(text3did)
{
	Debug(DEBUG_START,"GetMode3DTextDrawDistance(%d)",text3did);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"GetMode3DTextDrawDistance(reason: error)");
		printf("[ERROR] Mode 3dtexts -> GetMode3DTextDrawDistance (get draw distance not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	Debug(DEBUG_END,"GetMode3DTextDrawDistance(reason: complete)");
	return Mode3DTexts[text3did][tDrawDistance];
}

stock SetMode3DTextDrawDistance(text3did,Float:DrawDistance)
{
	Debug(DEBUG_START,"SetMode3DTextDrawDistance(%d,%f)",text3did,DrawDistance);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"SetMode3DTextDrawDistance(reason: error)");
		printf("[ERROR] Mode 3dtexts -> SetMode3DTextDrawDistance (set draw distance not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	Mode3DTexts[text3did][tDrawDistance] = DrawDistance;
	for(new playerid = 0;playerid <= GetMaxPlayer();playerid++)
	{
		if(!IsPlayerConnected(playerid)) continue;
		if(Mode3DTexts_Player[playerid][p3DTextId][text3did] == INVALID_3DTEXT_ID) continue;
		DeletePlayer3DTextLabel(playerid,Mode3DTexts_Player[playerid][p3DTextId][text3did]);
		Mode3DTexts_Player[playerid][p3DTextId][text3did] = INVALID_3DTEXT_ID;
		if(IsMode3DTextNeedToShow(playerid,text3did))
		{
			switch(Mode3DTexts[text3did][tAttach][aType])
			{
				case TEXT3D_ATTACH_NONE: Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],INVALID_PLAYER_ID,INVALID_VEHICLE_ID,Mode3DTexts[text3did][tLOS]);
				case TEXT3D_ATTACH_PLAYER: Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],Mode3DTexts[text3did][tAttach][aAttachedTo],INVALID_VEHICLE_ID,Mode3DTexts[text3did][tLOS]);
				case TEXT3D_ATTACH_VEHICLE: Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],INVALID_PLAYER_ID,Mode3DTexts[text3did][tAttach][aAttachedTo],Mode3DTexts[text3did][tLOS]);
			}
		}
	}
	Debug(DEBUG_END,"SetMode3DTextDrawDistance(reason: complete)");
	return 1;
}

stock IsMode3DTextNeedToShow(playerid,text3did)
{
	Debug(DEBUG_START,"IsMode3DTextNeedToShow(%d,%d)",playerid,text3did);
	if(Mode3DTexts[text3did][tActive] == false)
	{
		Debug(DEBUG_END,"IsMode3DTextNeedToShow(reason: error)");
		printf("[ERROR] Mode 3dtexts -> IsMode3DTextNeedToShow (try check not created 3D text, text3did = %d)",text3did);
		return 0;
	}
	if(!IsPlayerConnected(playerid))
	{
		Debug(DEBUG_END,"IsMode3DTextNeedToShow(reason: error)");
		printf("[ERROR] Mode 3dtexts -> IsMode3DTextNeedToShow (try check offline player, playerid = %d)",playerid);
		return 0;
	}
	Debug(DEBUG_ACTION,"Get current coordinates");
	new Float:pos[3],
		modeinterior = GetMode3DTextModeInterior(text3did),
		virtualworld = GetMode3DTextVirtualWorld(text3did);
	GetMode3DTextPos(text3did,pos[0],pos[1],pos[2]);
	Debug(DEBUG_END,"IsMode3DTextNeedToShow(reason: complete)");
	if(!IsPlayerInRangeOfPoint(playerid,TEXTS3D_DISTANCE,pos[0],pos[1],pos[2])) return 0;
	if((GetPlayerModeInterior(playerid) != modeinterior) && (modeinterior != -1)) return 0;
	if((GetPlayerVirtualWorld(playerid) != virtualworld) && (virtualworld != -1)) return 0;
	return 1;
}

// --------------------------------------------------
// Obligatory functions
// --------------------------------------------------

Mode3DText_OnGameModeInit()
{
	Debug(DEBUG_START,"Mode3DText_OnGameModeInit");
	print("Mode 3dtexts system loaded.");
	Debug(DEBUG_END,"Mode3DText_OnGameModeInit");
}

Mode3DText_OnPlayerUpdate(playerid)
{
	Debug(DEBUG_START,"Mode3DText_OnPlayerUpdate(%d)",playerid);
	for(new text3did = 0;text3did <= Mode3DTextsCount;text3did++)
	{
		if(Mode3DTexts[text3did][tActive] == false) continue;
		
		if(Mode3DTexts_Player[playerid][p3DTextId][text3did] == INVALID_3DTEXT_ID)
		{
			if(IsMode3DTextNeedToShow(playerid,text3did))
			{
				switch(Mode3DTexts[text3did][tAttach][aType])
				{
					case TEXT3D_ATTACH_NONE: Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],INVALID_PLAYER_ID,INVALID_VEHICLE_ID,Mode3DTexts[text3did][tLOS]);
					case TEXT3D_ATTACH_PLAYER: Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],Mode3DTexts[text3did][tAttach][aAttachedTo],INVALID_VEHICLE_ID,Mode3DTexts[text3did][tLOS]);
					case TEXT3D_ATTACH_VEHICLE: Mode3DTexts_Player[playerid][p3DTextId][text3did] = CreatePlayer3DTextLabel(playerid,Mode3DTexts[text3did][tText],Mode3DTexts[text3did][tColor],Mode3DTexts[text3did][tCoordinates][cPos][0],Mode3DTexts[text3did][tCoordinates][cPos][1],Mode3DTexts[text3did][tCoordinates][cPos][2],Mode3DTexts[text3did][tDrawDistance],INVALID_PLAYER_ID,Mode3DTexts[text3did][tAttach][aAttachedTo],Mode3DTexts[text3did][tLOS]);
				}
			}
		}
		else if(!IsMode3DTextNeedToShow(playerid,text3did))
		{
			DeletePlayer3DTextLabel(playerid,Mode3DTexts_Player[playerid][p3DTextId][text3did]);
			Mode3DTexts_Player[playerid][p3DTextId][text3did] = INVALID_3DTEXT_ID;
		}
	}
	Debug(DEBUG_END,"Mode3DText_OnPlayerUpdate(reason: complete)");
}

Mode3DText_ResetStat(playerid)
{
	Debug(DEBUG_START,"Mode3DText_OnPlayerUpdate(%d)",playerid);
	for(new text3did = 0;text3did < MAX_STREAM_3DTEXTS;text3did++) Mode3DTexts_Player[playerid][p3DTextId][text3did] = INVALID_3DTEXT_ID;
	Mode3DTexts_Player[playerid][pAttached3DTextId] = INVALID_3DTEXT_ID;
	Debug(DEBUG_END,"Mode3DText_OnPlayerUpdate(reason: complete)");
}