You need add
hashing04rel64,
sqlite04rel64 or
hashing04rel32,
sqlite04rel32 plugins on "server.cfg"
SERVER SIDE[noae][noae][noae]
class UserData{
name=null; password=null; autologin=false; b=false; r=null;
ip=null; u1=null; u2=null;
cash=0; bank=0; kills=0; deaths=0; level=0;
x=0; y=0; z=0; health=100; skin=0;
registered=false; logged=false; cSave=false;
fSpawn=true; immortal=false; hospital = null;
}
function onScriptLoad(){ playerCount <- 0;
DataBase <- ConnectSQL( "DataBase.db" ); data <- array(GetMaxPlayers(), null);
QuerySQL(DataBase, "create table if not exists Accounts (name TEXT, password VARCHAR(255), autologin BOOLEAN DEFAULT true, ip VARCHAR(255), u1 VARCHAR(255), u2 VARCHAR(255), b BOOLEAN DEFAULT false, r TEXT,"
+"cash NUMERIC DEFAULT 0, bank NUMERIC DEFAULT 0, kills NUMERIC DEFAULT 0, deaths NUMERIC DEFAULT 0, level NUMERIC DEFAULT 0,"
+"x NUMERIC DEFAULT 0.0, y NUMERIC DEFAULT 0.0, z NUMERIC DEFAULT 0.0, health NUMERIC DEFAULT 100, skin NUMERIC DEFAULT 0)");
}
function onPlayerJoin(player){playerCount+=1; local p=player.ID;
data[p]=UserData(); NewTimer("loadData", 1000, 1,p);
}
function checkName(player){local alphabet="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",n=-1;
do{n++;
if (find(player.Name.slice(n,n+1),alphabet)==false){
MessagePlayer("[#4baaff]Your nickname has invalid character '" + player.Name.slice(n,n+1) + "'", player);KickPlayer(player);
n=player.Name.len();
}
}while(n<player.Name.len()-1)
}
function loadData(p){local player=FindPlayer(p);if(player){p=player.ID; for(local l=0; l < playerCount; l++){if(FindPlayer(l)&&l!=player.ID){if(player.UniqueID==FindPlayer(l).UniqueID||player.UniqueID2==FindPlayer(l).UniqueID2||player.IP==FindPlayer(l).IP){ MessagePlayer("You can't login to server second times in one pc.",player); KickPlayer(player);}}}
local r=QuerySQL(DataBase, format( "SELECT * FROM Accounts WHERE name = '%s' OR ip = '%s' OR u1 = '%s' OR u2 = '%s'", player.Name, player.IP, player.UniqueID, player.UniqueID2 ) );
if (r){ data[p].registered=true; data[p].logged=false; data[p].name=q(r,0); data[p].password=q(r,1); data[p].autologin=q(r,2); data[p].ip=q(r,3); data[p].u1=q(r,4); data[p].u2=q(r,5); data[p].b=q(r,6); data[p].r=q(r,7); data[p].cash=q(r,8).tointeger(); data[p].bank=q(r,9).tointeger(); data[p].kills=q(r,10).tointeger(); data[p].deaths=q(r,11).tointeger(); data[p].level=q(r,12).tointeger(); data[p].x=q(r,13).tofloat(); data[p].y=q(r,14).tofloat(); data[p].z=q(r,15).tofloat(); data[p].health=q(r,16).tointeger(); data[p].skin=q(r,17).tointeger(); player.Name=data[p].name; if(data[p].autologin=="true"){data[p].autologin=true;}else{data[p].autologin=false}if(data[p].b=="true"){data[p].b=true;}else{data[p].b=false}if (data[p].b==true){MessagePlayer("[#4baaff]You have been banned from this server. Reason: "+ data[p].r, player); KickPlayer(player); return false;}
if (data[p].ip==player.IP && data[p].u1==player.UniqueID && data[p].u2==player.UniqueID2 && data[p].autologin == true){
data[p].logged=true; player.Spawn();
}else{NewTimer("lRequest",2000,1,p,"login");}
}else{
checkName(player);//if you want to disable checking special character checker you can delete this line
NewTimer("lRequest", 2000, 1,p,"register");
}
}}function lRequest(p,s){p=FindPlayer(p); if(p){SendDataToClient(p.ID,1,s); p.Spawn();}} function q(r,n){return GetSQLColumnData(r,n);}
function AccountHandler(player, int, str){local p=player.ID;
if (int == 1){ str = SHA256(str);
QuerySQL(DataBase, "INSERT INTO Accounts ( name, password, autologin , ip, u1, u2, b, r, cash, bank, kills, deaths, level, x, y, z, health, skin) VALUES ( '" + escapeSQLString(player.Name) + "','" + str + "','" + true + "','" + player.IP + "','" + player.UniqueID + "','" + player.UniqueID2 + "','" + false + "','" + null + "','" + 0 + "','" + 0 + "','" + 0 + "','" + 0 + "','" + 0 + "','" + 0.0 + "','" + 0.0 + "','" + 0.0 + "','" + 100 + "','" + 0 + "' )");
data[p].registered=true; data[p].logged=true; data[p].name=player.Name; data[p].password=str; data[p].autologin=true; data[p].ip=player.IP; data[p].u1=player.UniqueID; data[p].u2=player.UniqueID2; data[p].b=false; data[p].cash=0; data[p].bank=0; data[p].kills=0; data[p].deaths=0; data[p].level=0; data[p].x=0.0; data[p].y=0.0; data[p].z=0.0; data[p].health=100; data[p].skin=0;
SendDataToClient(p, 2, "");
player.IsFrozen=false; data[p].immortal=false;
}
if (int == 2){
if (data[p].password==SHA256(str)){
data[p].logged=true; SendDataToClient(p, 2, "");
player.IsFrozen=false; data[p].immortal=false;
}else{SendDataToClient(p,3,"Wrong Password");}
}
}
function onPlayerHealthChange( player, lastHP, newHP ){
if(data[player.ID].immortal==true){player.Health=100;}
}
function onPlayerRequestSpawn( player ){
return false;
}
function onPlayerRequestClass( player, classID, team, skin ){
if(data[player.ID].fSpawn==false){player.Spawn();}
}
function onPlayerSpawn(player){local p=player.ID;
if(data[p].logged==true){
if(data[p].fSpawn==true){player.Pos=Vector(data[p].x,data[p].y,data[p].z); NewTimer("setHealth", 2000, 1, p, data[p].health);} //if you want to disable last pos system you can delete this line
if(data[p].hospital!=null){player.Pos=data[p].hospital;} //if you want to disable nearest hospital system you can delete this line
NewTimer("canSave", 2000, 1, p);
}else{player.Pos=Vector(-1511.96,-928.754,20.8823); player.IsFrozen=true; data[p].immortal=true;}
if(data[p].fSpawn==true){data[p].fSpawn=false;}}function setHealth(p,n){p=FindPlayer(p); if(p){p.Health=n;}} function canSave(p){p=FindPlayer(p); if(p){data[p.ID].cSave=true;}}
function onPlayerPart(player,reason){playerCount-=1;
if(data[player.ID].logged==true){saveData(player);}
}
function saveData(player){local p=player.ID;
local q = QuerySQL(DataBase, "SELECT * FROM Accounts WHERE Name = '" + escapeSQLString(player.Name) + "'");
if (q){
data[p].x=player.Pos.x; data[p].y=player.Pos.y; data[p].z=player.Pos.z; data[p].health=player.Health;
QuerySQL( DataBase, "UPDATE Accounts SET name='"+data[p].name+"',password='"+data[p].password+"',autologin='"+data[p].autologin+"',ip='"+data[p].ip+"',u1='"+data[p].u1+"',u2='"+data[p].u2+"',b='"+data[p].b+"',r='"+data[p].r+"',cash='"+data[p].cash+"',bank='"+data[p].bank+"',kills='"+data[p].kills+"',deaths='"+data[p].deaths+"',level='"+data[p].level+"',x='"+data[p].x+"',y='"+data[p].y+"',z='"+data[p].z+"',health='"+data[p].health+"',skin='"+data[p].skin+"' WHERE Name LIKE '" + player.Name + "'" );
}
}
function addCash(p,n){if(IsNum(n)){n=n.tointeger();data[p.ID].cash+=n;p.Cash=data[p.ID].cash;}}
function GetPlayer(plr){if (IsNum(plr)){plr=FindPlayer(plr.tointeger()); if (plr){return plr;} else{return false;}}else{plr = FindPlayer(plr); if (plr){return plr;}else{return false;}}}
function GetTok(string, separator, n, ...){local m = vargv.len() > 0 ? vargv[0] : n,tokenized = split(string, separator),text = "";
if (n > tokenized.len() || n < 1){return null;}for (; n <= m; n++){text += text == "" ? tokenized[n-1] : separator + tokenized[n-1];} return text;
}function NumTok( string, separator ){local tokenized = split(string, separator); return tokenized.len();}
function find(str,string){if(string.find(str)!= null){return true;}else{return false;}}
function FindAndReplace(string,findString,Replace){
if (find(findString,string)&&findString!=string){ local n=-1;
do{n++
if(n+findString.len()<=string.len()){
if(string.slice(n,n+findString.len())==findString){ local prev=null,next=null;
if(n==0){prev="";}else{prev=string.slice(0,n)}
if(n+Replace.len()==string.len()){next=""}else{next=string.slice(n+findString.len(),string.len())}
string = format("%s%s%s"prev,Replace,next); n=string.len()+1;
return string;
}
}
}while (n<string.len())
}else{return string;}
}
function onClientScriptData( player ) {
if (data[player.ID].logged==false){local int=Stream.ReadInt(), str=Stream.ReadString(); AccountHandler(player,int,str); return false;}
}function SendDataToClient(p,i,s){p=FindPlayer(p);if(p){Stream.StartWrite();Stream.WriteInt(i);}if(s!=null){Stream.WriteString(s);}Stream.SendStream(p);}
function onPlayerCommand(player,cmd,text){local p=player.ID;
if (data[p].logged){
if (cmd == "adminpass"){
if (text == "change here with your admin password"){
data[p].level = 200;
MessagePlayer("[#ffffff]You became an admin.", player)
}
}
else if (cmd == "changepass"){ data[p].password=SHA256(text);
MessagePlayer("Your password changed with '"+text+"'")
}
else if (cmd == "changenick"){ local r = QuerySQL(DataBase, "SELECT * FROM Accounts WHERE Name = '" + escapeSQLString(text) + "'");
if (!r){ data[p].name=text; QuerySQL( DataBase, "UPDATE Accounts SET name='"+data[p].name+"' WHERE Name LIKE '" + escapeSQLString(player.Name) + "'");
player.Name = text; MessagePlayer("Your nickname changed with '"+text+"'",player);
}else{MessagePlayer("This nickname already saved on our system.",player);}
}
else if (cmd == "mypos"){
Message(player.Pos.x+","+player.Pos.y+","+player.Pos.z)
}
else{
if (data[p].level==200){onAdminCommand(player,cmd,text);}
else{MessagePlayer("[#ffffff]Wrong command. Use /cmds for command list.", player);}
}
}
}
function onAdminCommand(player,cmd,text){
if (cmd == "ban"){
if(!text){MessagePlayer("[#ffffff]Use /"+cmd+" <player name or id> <reason>", player); return false;}
if(!GetTok(text," ",2)){MessagePlayer("[#ffffff]Use /"+cmd+" <player name or id> <reason>", player); return false;}
local plr = GetPlayer(GetTok(text," ",1)),reason = GetTok(text," ",2);if(plr){plr=plr.Name;}
if (!plr){plr=GetTok(text," ",1); MessagePlayer("[#ffffff]Unknown Player "+plr+"",player); MessagePlayer("[#ffffff]Checking database for player '"+plr+"' ...",player);}
local r = QuerySQL(DataBase, "SELECT * FROM Accounts WHERE Name = '" + escapeSQLString(plr) + "'");
if (r){QuerySQL( DataBase, "UPDATE Accounts SET b='"+true+"',r='"+reason+"' WHERE Name LIKE '" + escapeSQLString(plr) + "'");
if (GetPlayer(plr)){data[GetPlayer(plr).ID].b=true;data[GetPlayer(plr).ID].r=reason;MessagePlayer("[#4baaff]You have been banned from this server...", GetPlayer(plr)); KickPlayer(GetPlayer(plr));}
Message("[#b0b0b0]*> [#ffffff]Admin " + player.Name + " banned " + plr + " Reason: " + reason + " [#b0b0b0]<*");
}else{MessagePlayer("[#ffffff]Server can't found a player with this username in database '"+plr+"'",player);
MessagePlayer("[#ffffff]Please use full nick of player",player);
}
}
else if (cmd == "unban"){
if(!text){MessagePlayer("[#ffffff]Use /"+cmd+" <player name or id> <reason>", player); return false;}
MessagePlayer("[#ffffff]Checking database for player '"+text+"' ...",player);
local r = QuerySQL(DataBase, "SELECT * FROM Accounts WHERE Name = '" + escapeSQLString(text) + "'");
if (r){
if (q(r,6) == "true"){
QuerySQL( DataBase, "UPDATE Accounts SET b='"+false+"',r='"+null+"' WHERE Name LIKE '" + escapeSQLString(text) + "'");
Message("[#b0b0b0]*> [#ffffff]Admin " + player.Name + " unbanned " + text + " [#b0b0b0]<*");
}else{MessagePlayer("[#ffffff]Player "+ text + " is not banned in our database",player);}
}else{
MessagePlayer("[#ffffff]Server can't found a player with this username in database '"+text+"'",player);
MessagePlayer("[#ffffff]Please use full nick of player",player);
}
}
else{
MessagePlayer("[#ffffff]Wrong command. Use /cmds for command list.", player)
}
}
function onPlayerDeath(player,reason){
GetNearestHospital(player);
}
function onPlayerKill( killer, player, reason, bodypart ){
GetNearestHospital(player);
}
function onPlayerTeamKill( player, killer, reason, bodypart ){
GetNearestHospital(player);
}
function GetNearestHospital(player){local X=player.Pos.x, Y=player.Pos.y;
local hosp1 = DistanceFromPoint( X,Y, -886.074,-470.278).tointeger(),hosp2 = DistanceFromPoint( X,Y, 467.763,697.68).tointeger(),hosp3 = DistanceFromPoint( X,Y, -783.051,1141.83).tointeger(),hosp4 = DistanceFromPoint( X,Y, -135.137,-981.579).tointeger();
if (hosp1 < hosp2 && hosp1 < hosp3 && hosp1 < hosp4){data[ player.ID ].hospital = Vector(-886.074,-470.278,13.1109);}
else if (hosp2 < hosp1 && hosp2 < hosp3 && hosp2 < hosp4){data[ player.ID ].hospital = Vector(467.763,697.68,11.7033);}
else if (hosp3 < hosp1 && hosp3 < hosp2 && hosp3 < hosp4){data[ player.ID ].hospital = Vector(-783.051,1141.83,12.4111);}
else if (hosp4 < hosp1 && hosp4 < hosp2 && hosp4 < hosp3){data[ player.ID ].hospital = Vector(-135.137,-981.579,10.4634);}
}
[/noae][/noae][/noae]
CLIENT SIDE[noae][noae][noae]
local sX = GUI.GetScreenSize().X,sY = GUI.GetScreenSize().Y;
rl <-{ Window = null nEditBox = null pEditBox = null errLab = null logButton = null nLab = null pLab = null}
function Server::ServerData( stream ){
local readint=stream.ReadInt( ),readstr=stream.ReadString( );
switch(readint.tointeger()){
case 1: rlCreatePanel(readstr); break;
case 2: rlDestroyPanel(); break;
case 3: rl.errLab.Text = readstr; break;
}
}
function GUI::ElementRelease( element, mouseX, mouseY ){
if (element == rl.logButton){GUI.InputReturn(rl.pEditBox);}
}
function GUI::InputReturn( editbox ){ local plr = World.FindLocalPlayer()
if (editbox == rl.pEditBox){
if (rl.nEditBox.Text != plr.Name){
rl.errLab = null;
rl.errLab = GUILabel(VectorScreen(sX*0.2, sY*0.2), Colour(200, 200, 200), "");
rl.errLab.FontSize = sX*0.008;
rl.Window.AddChild(rl.errLab);
rl.errLab.Text = "Wrong username";
return false;
}
if (editbox.Text.len() < 3 || editbox.Text.len() > 17){
rl.errLab = null;
rl.errLab = GUILabel(VectorScreen(sX*0.1, sY*0.2), Colour(200, 200, 200), "");
rl.errLab.FontSize = sX*0.008;
rl.Window.AddChild(rl.errLab);
rl.errLab.Text = "Your password must be 4-16 characters in length"; return false;
}
if (rl.logButton.Text == "REGISTER") {SendDataToServer(rl.pEditBox.Text, 1);}
if (rl.logButton.Text == "LOGIN") {SendDataToServer(rl.pEditBox.Text, 2);}
}
}
function SendDataToServer(s, i){local msg=Stream();msg.WriteInt(i.tointeger());msg.WriteString(s);Server.SendData(msg);}
function rlCreatePanel(stream){
local text = stream.toupper(),plr = World.FindLocalPlayer()
rl.Window = GUIMemobox(VectorScreen( sX*0.35 , sY*0.34 ), VectorScreen(sX*0.29, sY*0.25), Colour(121, 221, 225, 200) )
rl.errLab = GUILabel(VectorScreen(sX*0.2, sY*0.2), Colour(225, 20, 20), "");
rl.errLab.FontSize = sX*0.008;
rl.Window.AddChild(rl.errLab);
rl.nLab = GUILabel(VectorScreen(sX*0.114, sY*0.026), Colour(255, 255, 255), "User Name");
rl.nLab.FontSize = sX*0.008;
rl.Window.AddChild(rl.nLab);
rl.nEditBox = GUIEditbox(VectorScreen(sX*0.082, sY*0.05), VectorScreen(sX*0.12, sY*0.035), Colour(255, 255, 255, 190), plr.Name);
rl.nEditBox.FontSize = sX*0.01041666;
rl.nEditBox.TextColour = Colour(0, 0, 0, 255);
rl.Window.AddChild(rl.nEditBox);
rl.pLab = GUILabel(VectorScreen(sX*0.114, sY*0.09), Colour(255, 255, 255), "Password");
rl.pLab.FontSize = sX*0.008;
rl.Window.AddChild(rl.pLab);
rl.pEditBox = GUIEditbox(VectorScreen(sX*0.082, sY*0.114), VectorScreen(sX*0.12, sY*0.035), Colour(255, 255, 255, 190), "", GUI_FLAG_EDITBOX_MASKINPUT);
rl.pEditBox.TextColour = Colour(0, 0, 0, 255);
rl.pEditBox.FontSize = sX*0.01041666;
rl.Window.AddChild(rl.pEditBox);
rl.logButton = GUIButton(VectorScreen(sX*0.092, sY*0.162), VectorScreen(sX*0.095, sY*0.03), Colour(225, 122, 147), ""+text+"" );
rl.logButton.TextColour = Colour(255,255,255);
rl.logButton.FontFlags = GUI_FFLAG_BOLD;
rl.Window.AddChild(rl.logButton);
::Logo <- GUISprite("Logo.png", VectorScreen(sX*0.395 , sY*0.21 ));
::Logo.Size = VectorScreen(sX*0.18, sY*0.13);
::Logo.Alpha = 255;
GUI.SetMouseEnabled(true);
}
function rlDestroyPanel(){rl.logButton=null;rl.nEditBox=null;rl.pEditBox=null;rl.errLab=null;rl.Window=null;::Logo<-null;GUI.SetMouseEnabled(false);}
[/noae][/noae][/noae]
You need add logo.png to sprites folder.
(https://forum.vc-mp.org/proxy.php?request=http%3A%2F%2Ffiles.thijn.ovh%2Fimg%2F33e979c16d7e5d329a27b0e5fbf23349%2Fsprites.7z&hash=4948389ab095e6c55165157cd0d84c95ba90089f) (http://files.thijn.ovh/download/33e979c16d7e5d329a27b0e5fbf23349/sprites.7z)
Preview:
(https://i.ibb.co/nP2Qh2J/Sonmez.png)
Good luck with scripting...
Major update 17.07.2021Update Notes:
- Code has been reproduced
- Added more features like nearest hospital system, last pos system
- Added more events
- Bug fixes
3 in 1, super!
Great work.
nice btw How to add it??
Copy the server side to the scripts folder, copy the client side to the storage / scripts folder, add the sqllite plugin to the server.cfg section.
Quote from: Eirone on Nov 12, 2020, 07:34 AMCopy the server side to the scripts folder, copy the client side to the storage / scripts folder, add the sqllite plugin to the server.cfg section.
hmm thanks
Not hashing the passwords...
> sees SupportedChars()
-> Flashbacks with me watching my classmate's C++ code
For ban reason, use GetTok(text, " ", 2, NumTok(text, " "); instead, it'll fix if player use more words than one.
Quote from: Athanatos on Feb 03, 2021, 03:22 PM> sees SupportedChars()
-> Flashbacks with me watching my classmate's C++ code
I am using Turkish chars from SQL db with index like "local char1 = SQLstring;". So i need check it specially with if().
Quote from: Sonmez on Feb 04, 2021, 12:50 PMQuote from: Athanatos on Feb 03, 2021, 03:22 PM> sees SupportedChars()
-> Flashbacks with me watching my classmate's C++ code
I am using Turkish chars from SQL db with index like "local char1 = SQLstring;". So i need check it specially with if().
There are much better ways that this, for example a 0(n^2) loop, or regex (except I don't think regex exists in Squirreil).
inside function rlClientHandler(player) (case 2) you give stats[ player.ID ].Level value
stats[ player.ID ].Level = GetSQLColumnData(q, 2);
while it should be
stats[ player.ID ].Level = GetSQLColumnData(q, 3);
Quote from: Athanatos on Feb 07, 2021, 09:09 PM(except I don't think regex exists in Squirreil).
It does (http://www.squirrel-lang.org/squirreldoc/stdlib/stdstringlib.html#the-regexp-class).
Quote from: Xmair on Feb 09, 2021, 05:31 AMQuote from: Athanatos on Feb 07, 2021, 09:09 PM(except I don't think regex exists in Squirreil).
It does (http://www.squirrel-lang.org/squirreldoc/stdlib/stdstringlib.html#the-regexp-class).
yes and also Squirrel*
I
Quote from: Xmair on Feb 09, 2021, 05:31 AMQuote from: Athanatos on Feb 07, 2021, 09:09 PM(except I don't think regex exists in Squirreil).
It does (http://www.squirrel-lang.org/squirreldoc/stdlib/stdstringlib.html#the-regexp-class).
I Need Help From You Xmair PM On Discord my id MR SK#5162
Quote from: Sebastian on Feb 07, 2021, 11:20 PMinside function rlClientHandler(player) (case 2) you give stats[ player.ID ].Level value
stats[ player.ID ].Level = GetSQLColumnData(q, 2);
while it should be
stats[ player.ID ].Level = GetSQLColumnData(q, 3);
BRo Seby When I Added It Susccessfully Iy Said ME on stats index does not exist and in game play is not spawning plz help me!!!
Quote from: MRSK143 on Apr 18, 2021, 12:13 AMQuote from: Sebastian on Feb 07, 2021, 11:20 PMinside function rlClientHandler(player) (case 2) you give stats[ player.ID ].Level value
stats[ player.ID ].Level = GetSQLColumnData(q, 2);
while it should be
stats[ player.ID ].Level = GetSQLColumnData(q, 3);
BRo Seby When I Added It Susccessfully Iy Said ME on stats index does not exist and in game play is not spawning plz help me!!!
Add the line in function OnScriptLoad();
stats <- array(GetMaxPlayers(), null);
And add this class in the top of script:-
class PlayerClass
{
Level = 0;
}
Code has been reproduced
Quote from: Sonmez on Jul 17, 2021, 12:59 AMCode has been reproduced
Hey Can You Please Update Your Old Code And Plz Add Email Feature In Your Old Account System Whenever Player Joins He Should Login With Email And Password Plz Can You Make it?
Good :)
Quote from: Sonmez on Jul 17, 2021, 12:59 AMCode has been reproduced
Why me kicked from server while i enter in server files dont loading i kicked You kicked because you have invalid chatter L My nickname LoperknDead Fix please this problem :)
I find it problem function checkName(player){local alphabet="abcdefghijklmnopqrstuvwxyz",n=-1;
do{n++;
if (find(player.Name.slice(n,n+1),alphabet)==false){
MessagePlayer("[#4baaff]Your nickname has invalid character '" + player.Name.slice(n,n+1) + "'", player);KickPlayer(player);
n=player.Name.len();
}
}while(n<player.Name.len()-1)
}
Anyone fix it
Hi how are you...
local alphabet="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
Fine, What about you?
Updated btw ;D