Commands: /newduel , /duel
Any questions, suggestions or constructive criticisms can be left in the comments, in advance, thank you very much.
Review: https://www.youtube.com/watch?v=DcVRFbofSsE&feature=youtu.be
Server Side:
[spoiler]
Put in OnScriptLoad:
[noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae]dofile("scripts/_DuelSystem.nut");
[/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae]
Put in OnPlayerPart:
[noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae] if( Duels[player.World] && ( Duels[player.World].Player1.Name == player.Name || Duels[player.World].Player2.Name == player.Name ) )
{
DuelSystem.EndDuel(player.World);
}
if( Invitations[player.ID] && Invitations[player.ID].Accepted == false ) DuelSystem.DenyInvitation(player, "Quit");
[/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae]
Put in OnPlayerCommand:
[noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae]if ( cmd.tolower() == "newduel" || cmd.tolower() == "duel" ) DuelSystem.onPlayerCommand( player, cmd.tolower(), text )
[/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae]
Put in OnPlayerKill:
[noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae] if( Duels[player.World] && ( Duels[player.World].Player1.Name == player.Name || Duels[player.World].Player2.Name == player.Name ) )
{
DuelSystem.AddKill(player.Team, player.World);
}
[/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae]
Put in onClientScriptData:
[noae][noae][noae][noae][noae]local string = Stream.ReadString();
switch ( string )
{
case "DuelDeny":
{
onPlayerCommand( player , "duel", "deny");
}
break;
case "DuelAccept":
{
onPlayerCommand( player , "duel", "accept");
}
break;
}
[/noae][/noae][/noae][/noae][/noae]
Put in onPlayerRequestClass:
[noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae] if( Duels[player.World] && ( Duels[player.World].Player1.Name == player.Name || Duels[player.World].Player2.Name == player.Name ) )
{
player.Spawn();
DuelSystem.Respawn(player);
}
[/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae]
Put in OnPlayerSpawn:
[noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae] if( Duels[player.World] && ( Duels[player.World].Player1.Name == player.Name || Duels[player.World].Player2.Name == player.Name ) )
{
player.Spawn();
DuelSystem.Respawn(player);
}
[/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae]
Put at the end of the main.nut:
[noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae]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 SendDataToClient( player, ... )
{
if( vargv[0] )
{
local byte = vargv[0],
len = vargv.len();
if( 1 > len ) devprint( "ToClent <" + byte + "> No params specified." );
else
{
Stream.StartWrite();
Stream.WriteByte( byte );
for( local i = 1; i < len; i++ )
{
switch( typeof( vargv[i] ) )
{
case "integer": Stream.WriteInt( vargv[i] ); break;
case "string": Stream.WriteString( vargv[i] ); break;
case "float": Stream.WriteFloat( vargv[i] ); break;
}
}
if( player == null ) Stream.SendStream( null );
else if( typeof( player ) == "instance" ) Stream.SendStream( player );
else devprint( "ToClient <" + byte + "> Player is not online." );
}
}
else devprint( "ToClient: Even the byte wasn't specified..." );
}
[/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae]
Create a file .nut called _DuelSystem with the following code:
PasteBin: https://pastebin.com/RaBqihk2
[spoiler]
[noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae][noae]Duels <- array( 3000, null ); //This Array will store the duels data
Invitations <- array( GetMaxPlayers(), null );//This Array will store the invitatios data
class DuelClass //This data will be saved in the duels array.
{
Player1 = null;
Player2 = null;
Player1Kills = 0;
Player2Kills = 0;
MaxKills = 0;
}
DuelSystem <- {
//Function responsible for sending requests for duels
function SendInvitation(player, player2, KillsToWin)
{
MessagePlayer("[#81F79F]You have received a duel invitation from the player [#FF5733]"+ player.Name +"[#81F79F]. You must kill him [#FF5733]"+KillsToWin+ " [#81F79F]times to win", player2);
MessagePlayer("[#81F79F]You have sent the invitation to a duel to the player [#FF5733]"+ player2.Name +"[#81F79F]. Kills to Win: [#FF5733]"+ KillsToWin +"[#81F79F].", player);
Invitations[player.ID] =
{
Sent = player2
Kills = KillsToWin
InvitedBy = player
Accepted = false
};
Invitations[player2.ID] =
{
Sent = player
Kills = KillsToWin
InvitedBy = player
Accepted = false
};
SendDataToClient( player2, 0x02, player.Name );
}
//Function responsible for denying requests for duels
function DenyInvitation(player, reason)
{
local plr = Invitations[player.ID].Sent;
MessagePlayer(player+ " [#81F79F]canceled the duel invitation. Reason: [#FF5733]"+reason+".", plr);
if (reason != "Quit") MessagePlayer("[#81F79F]You have successfully canceled the duel", player); //
SendDataToClient( plr, 0x02, "cancel");
Invitations[plr.ID] = null;
Invitations[player.ID] = null;
}
//This function is executed when accepting duels
function StartDuel(player1, player2, kills)
{
local World = (rand() % 3000).tointeger();
Duels[ World ] = DuelClass();
Duels[World].Player1 = player1;
Duels[World].Player2 = player2;
Duels[World].MaxKills = kills;
player1.World = World;
player1.Pos = Vector(-1759.98, -193.022, 14.8683);
player1.Team = 1;
player2.World = World;
player2.Team = 2;
player2.Pos = Vector(-1763.34, -127.249, 14.8683);
Invitations[player2.ID].Accepted = true;
Invitations[player1.ID].Accepted = true;
SayKills(World);
Message("[#FF5733]" + player1.Name + "[#81F79F] has started a duel against [#FF5733]"+ player2.Name +"[#81F79F]. Kills to win: [#FF5733]"+ kills +"[#81F79F].");
}
function EndDuel(World)
{
local winner, loser, result;
if( Duels[World].Player1Kills < Duels[World].Player2Kills )
{
winner = Duels[World].Player2.Name;
loser = Duels[World].Player1.Name;
result = Duels[World].Player2Kills +" - "+ Duels[World].Player1Kills;
}
else
{
winner = Duels[World].Player1.Name;
loser = Duels[World].Player2.Name;
result = Duels[World].Player1Kills +" - "+ Duels[World].Player2Kills;
}
local player1 = Duels[World].Player1;
local player2 = Duels[World].Player2;
SendDataToClient( player1, 0x03, "DuelEnd|DuelEnd|DuelEnd");
SendDataToClient( player2, 0x03, "DuelEnd|DuelEnd|DuelEnd");
player1.World = 0;
player1.Select();
player2.World = 0;
player2.Select();
Invitations[player1.ID] = null;
Invitations[player2.ID] = null;
Duels[World] = null;
Message("[#FF5733]" + winner + " [#81F79F]won a duel to [#FF5733]"+ loser +"[#81F79F]. Result: [#FF5733]"+ result +".");
}
function AddKill(team, World)
{
if (team == 1)
{
Duels[World].Player1Kills++;
DuelSystem.SayKills(World);
if ( Duels[World].MaxKills <= Duels[World].Player1Kills ) DuelSystem.EndDuel(World);
}
else
{
Duels[World].Player2Kills++;
DuelSystem.SayKills(World);
if ( Duels[World].MaxKills <= Duels[World].Player2Kills ) DuelSystem.EndDuel(World);
}
}
function SayKills(World)
{
local msg = Duels[World].Player1.Name+" "+ Duels[World].Player1Kills +"|"+ Duels[World].Player2Kills+" "+ Duels[World].Player2.Name;
SendDataToClient( Duels[World].Player1, 0x03, msg + "|Kills to Win: " + Duels[World].MaxKills);
SendDataToClient( Duels[World].Player2, 0x03, msg + "|Kills to Win: " + Duels[World].MaxKills);
}
function Respawn(player)
{
if ( Duels[player.World].Player1.Name == player.Name )
{
player.Pos = Vector(-1759.98, -193.022, 14.8683);
player.Team = 1;
}
else
{
player.Pos = Vector(-1763.34, -127.249, 14.8683);
player.Team = 2;
}
}
// =========================== Commands ========================== //
function onPlayerCommand(player, cmd, text)
{
if (cmd == "newduel")
{
if(!text) MessagePlayer("[#81F79F]/newduel Nick KillsToWin", player);
else if ( !GetPlayer(GetTok(text, " ", 1)) ) MessagePlayer("[#81F79F]/newduel Nick KillsToWin", player);
else if ( GetPlayer(GetTok(text, " ", 1)).Name == player.Name ) MessagePlayer("[#81F79F]You can't invite yourself.", player);
else if ( !IsNum(GetTok(text, " ", 2)) ) MessagePlayer("[#81F79F]/newduel Nick KillsToWin", player);
else if ( Invitations[ player.ID ] && Invitations[ player.ID ].Accepted == true) MessagePlayer("[#81F79F]You cannot create an invitation while in a duel.", player);
else if ( Invitations[ player.ID ] ) MessagePlayer("[#81F79F]You have already created a grieving invitation.", player);
else if ( Invitations[ GetPlayer(GetTok(text, " ", 1)).ID ] && Invitations[ GetPlayer(GetTok(text, " ", 1)).ID ].Accepted == true ) MessagePlayer("[#81F79F]He is participating in a duel.", player);
else if ( Invitations[ GetPlayer(GetTok(text, " ", 1)).ID ] ) MessagePlayer("[#81F79F]He has already been invited to a duel", player);
else
{
local kills = GetTok(text, " ", 2);
local plr = GetPlayer(GetTok(text, " ", 1));
DuelSystem.SendInvitation(player, plr, kills);
}
}
else if (cmd == "duel")
{
if( !text ) MessagePlayer("[#81F79F]/duel accept/deny", player);
else
{
local subcommand = GetTok(text, " ", 1);
switch (subcommand.tolower())
{
case "accept":
if ( !Invitations[ player.ID ] ) MessagePlayer("[#81F79F]Nobody has invited you to a duel.", player);
else if ( Invitations[ player.ID ] && Invitations[ player.ID ].InvitedBy.Name == player.Name ) MessagePlayer("[#81F79F]You cannot accept your own duel", player);
else if ( Invitations[ player.ID ] && Invitations[ player.ID ].Accepted == true) MessagePlayer("[#81F79F]You can't accept while you're in a duel.", player);
else DuelSystem.StartDuel(player, Invitations[ player.ID ].Sent, Invitations[ player.ID ].Kills.tointeger() );
break;
case "deny":
case "cancel":
if ( !Invitations[ player.ID ] ) MessagePlayer("[#81F79F]Nobody has invited you to a duel.", player);
else if ( Invitations[ player.ID ] && Invitations[ player.ID ].Accepted == true) MessagePlayer("[#81F79F]You can't accept while you're in a duel.", player);
else if ( Invitations[ player.ID ] && Invitations[ player.ID ].InvitedBy.Name == player.Name ) DuelSystem.DenyInvitation(player, "Canceled");
else DuelSystem.DenyInvitation(player, "Denied.");
break;
default:
MessagePlayer("[#81F79F]/duel accept/deny", player);
}
}
}
}
};
[/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae][/noae]
[/spoiler]
[/spoiler]
Client-Side:
[spoiler]
Put in Server::ServerData:
[noae][noae][noae][noae][noae][noae] local type = stream.ReadByte();
local string = stream.ReadString();
switch( type )
{
case 0x02:
{
if(string == "cancel")
{
InvitationDuel.Menu = null;
InvitationDuel.ButtonCancel = null;
InvitationDuel.ButtonAccept = null;
}
else
{
GUI.SetMouseEnabled(true);
InvitationDuel.Menu <- GUIWindow(VectorScreen(sX * 0.66, sY * 0.64), VectorScreen(sX * 0.28, sY * 0.160), Colour(0, 0, 0, 900), string + " has challenged you to a 10-kills duel");
InvitationDuel.Menu.RemoveFlags( GUI_FLAG_WINDOW_RESIZABLE | GUI_FLAG_WINDOW_CLOSEBTN );
InvitationDuel.Menu.FontFlags = ( GUI_FFLAG_BOLD );
InvitationDuel.ButtonAccept = GUIButton( );
InvitationDuel.ButtonAccept.Size = VectorScreen( 140, 50 );
InvitationDuel.ButtonAccept.Colour = Colour( 89, 193, 43 );
InvitationDuel.ButtonAccept.TextColour = Colour( 0, 0, 0 );
InvitationDuel.ButtonAccept.Pos = VectorScreen( sX * 0.0205, sY * 0.030);
InvitationDuel.ButtonAccept.Text = "Accept";
InvitationDuel.ButtonAccept.FontFlags = ( GUI_FFLAG_BOLD );
InvitationDuel.ButtonCancel = GUIButton( );
InvitationDuel.ButtonCancel.Size = VectorScreen( 140, 50 );
InvitationDuel.ButtonCancel.Colour = Colour( 219, 0, 0 );
InvitationDuel.ButtonCancel.TextColour = Colour( 0, 0,0 );
InvitationDuel.ButtonCancel.Pos = VectorScreen( sX * 0.1419, sY * 0.030 );
InvitationDuel.ButtonCancel.Text = "Decline";
InvitationDuel.ButtonCancel.FontFlags = ( GUI_FFLAG_BOLD );
InvitationDuel.Menu.AddChild(InvitationDuel.ButtonAccept);
InvitationDuel.Menu.AddChild(InvitationDuel.ButtonCancel);
}
}
break;
case 0x03:
{
local scores = split(string, "|");
local Player1 = scores[0];
local Player2 = scores[1];
local KillsToWin = scores[2];
if(Player1 != "DuelEnd")
{
DuelScore.Player1 = GUILabel(VectorScreen(sX * 0.76, sY * 0.25),Colour(255,170,0), Player1 + " - " + Player2);
DuelScore.KillsToWin = GUILabel(VectorScreen(sX * 0.76, sY * 0.29),Colour(255,170,0), KillsToWin);
DuelScore.Player1.FontSize = 20;
DuelScore.KillsToWin.FontSize = 20;
DuelScore.Player1.FontFlags = ( GUI_FFLAG_BOLD );
DuelScore.KillsToWin.FontFlags = ( GUI_FFLAG_BOLD );
DuelScore.Player1.TextAlignment = ( GUI_ALIGN_LEFT );
DuelScore.KillsToWin.TextAlignment = ( GUI_ALIGN_LEFT );
}
else
{
DuelScore.Player1 = null;
DuelScore.KillsToWin = null;
}
}
break;
default:
break;
}
[/noae][/noae][/noae][/noae][/noae][/noae]
Put in GUI::ElementRelease:
[noae][noae][noae][noae][noae][noae]switch (element)
{
case InvitationDuel.ButtonAccept:
{
local Data = Stream();
Data.WriteString(" DuelAccept");
Server.SendData(Data);
GUI.SetMouseEnabled(false);
InvitationDuel.Menu = null;
InvitationDuel.ButtonCancel = null;
InvitationDuel.ButtonAccept = null;
}
break;
case InvitationDuel.ButtonCancel:
{
local Data = Stream();
Data.WriteString(" DuelDeny");
Server.SendData(Data);
GUI.SetMouseEnabled(false);
InvitationDuel.Menu = null;
InvitationDuel.ButtonCancel = null;
InvitationDuel.ButtonAccept = null;
}
break;
}
[/noae][/noae][/noae][/noae][/noae][/noae]
Put at the end of the main.nut (CLIENT SIDE):
[noae][noae][noae][noae][noae][noae]InvitationDuel <-
{
UserName = null
Menu = null
ButtonAccept = null
ButtonCancel = null
}
DuelScore <-
{
Menu = null
Player1 = null
Player2 = null
KillsToWin = null
}
sX <- GUI.GetScreenSize().X;
sY <- GUI.GetScreenSize().Y;
[/noae][/noae][/noae][/noae][/noae][/noae]
[/spoiler]
Nice and easy.
Would look better with GUI contribution when about invitation with accept/decline and score
Quote from: Sebastian on Oct 13, 2019, 08:02 AMNice and easy.
Would look better with GUI contribution when about invitation with accept/decline and score
The system now has a GUI, Thanks for your suggestion ;D.
https://www.youtube.com/embed/DcVRFbofSsE?
That's just awesome! That's how a duel system should look like, in vcmp 0.4
I'll use it but mod it, to give the gui vice city style. Nice job
Quote from: Sebastian on Oct 13, 2019, 02:38 PMThat's just awesome! That's how a duel system should look like, in vcmp 0.4
Woow, irony? xd, Thanks anyway ;D
Quote from: Gulk2 on Oct 13, 2019, 08:03 PMI'll use it but mod it, to give the gui vice city style. Nice job
What style would that be?
I will gladly change it, but I need an example of the gui what you want.
This font is the official one used in VC for subtitles,
https://fonts2u.com/sf-arborcrest-heavy.font
VC contains other fonts too.
what if sender decide to cancel their request? i think you forgot about it?!
Quote from: Saiyan Attack on Oct 18, 2019, 08:44 PMwhat if sender decide to cancel their request? i think you forgot about it?!
I think you haven't seen the video, the system has to accept and deny duels. '-'
i have seen it and i have also seen your command /duel cancel - that can use only for those user who sent request of duel ... and i want to tell you about when sender cancel their duel request and then the popup window should remove automatically ....
Quote from: Saiyan Attack on Oct 19, 2019, 01:37 AMi have seen it and i have also seen your command /duel cancel - that can use only for those user who sent request of duel ... and i want to tell you about when sender cancel their duel request and then the popup window should remove automatically ....
Code updated. Thanks for notifying xD
Thanks bro i really needed it <3
i m making Battle royale server if you help me its cool :X
Quote from: =RK=MarineForce on Nov 09, 2019, 07:49 AMThanks bro i really needed it <3
You're welcome ;D
Quote from: =RK=MarineForce on Nov 09, 2019, 07:49 AMi m making Battle royale server if you help me its cool :X
Sure, no problem, talk to me in discord ;).
My discord is: (ARG)Maximiliano#3058