You are viewing our Forum Archives. To view or take place in current topics click here.
[CoD] Complete Scripting Tutorial
Posted:

[CoD] Complete Scripting TutorialPosted:

coolbunny1234
  • Rigged Luck
Status: Offline
Joined: Aug 09, 200915Year Member
Posts: 6,493
Reputation Power: 8063
Motto: The Original Bunny
Motto: The Original Bunny
Status: Offline
Joined: Aug 09, 200915Year Member
Posts: 6,493
Reputation Power: 8063
Motto: The Original Bunny
For now this topic will be here, idk what forum to post this in...

This is a multi-tutorial topic that should cover the basics of coding. This took me a few weeks to create, and some of the explanations are from other websites explaining things better than I could. I created this tutorial so people will stop bugging me and so people can learn how to do what I do. Please stop asking me to teach you how to code patches now lol.

Arrays



Arrays are extremely helpful when it comes to doing the same thing to several different objects, such as moving a few platforms by a certain amount in a map, or storing lots of related variables.
To create an array we simply type...
 arrayName = [];

Now, to add an object/variable to this array, we can simply use:
array(array.size) = "a string variable";

Whenever you see array.size, the .size does not mean it's dimensions, but the amount of items in the array. So if an array contains 1 piece of data, the array.size is 1. To retrieve an items from an array, you can use array[0] for the first object/var stored in it, and then array[1] and so on for successive items.
Going back to the example above, we could retrieve the data by using array[0]. The first item in an array is listed as 0, the second as 1, and so on. This means that by using array(array.size) = "blah";, we can add new items to it because of the offset of 1.

A common use for an array is to call a function on all of the players in the game. This can be done by using an array with a FOR loop. To start with we must get our array of players, and instead of using the above method of defining an array and adding custom data, we can use a builtin function.
players = getEntArray("player", "classname");

So, our array has been defined as "players", or more accurately, "players[]".
Inside "players[]" is every player on the server, and now all we need to do is use the array to thread a function to each player. So, here we have a for loop to do such a thing:

 for(i = 0; i < players.size; i++)
 {
   players[i] thread function();
 }

That's our loop to go through every player and call function(); on them.
Remember, 'i' is a variable not a letter, so 'i' is substitued with the number of the loop. In the first loop, 'i' equals 0, so:

players[0] thread function();

is executed.
Arrays are a complicated part of scripting, but once you have them understood, they are one of the most useful things in the game.




Using Variables



Variables can be used in several ways, but in all cases they are used to store some data for the duration of the game. Variables come in different forms: integers, floats, entities, strings, arrays and booleans, there are also several different ways variables can be stored.
A simple variable is simply declared using
variable = data;

This variable can be used in the current function and any function that passes it as an argument, or is called on it (so it'd be used as 'self').

Variables can be global (which can be used in all threads without needing to be called) by using the
level.variable = data;

or they can be assigned to entities individually
entity.variable = data;

for things like player.health (integer, already built-in, but can be modified) and level.teamBased (boolean).




Creating Functions



A custom function is a good way to use repeat sections of code more efficiently. For example, if you often use the same sequence of code, you can template them into a custom function. Imagine this is your code...

{
 wait 1;
 brush1 moveZ(320, 5);
 brush1 waittill("movedone");
 wait 1;
 brush2 moveZ(540, 3);
 brush2 waittill("movedone");
}

This can be simplified using a custom function, lets call this function "_moveEnt" (it is common practice to use an underscore as the first character of a function)
_moveEnt(ent, dist, time)

As the above shows, we are going to need 3 arguements, ent (entity), dist (distance) and time.
Now lets look at the full code with custom function in use...
 {
   _moveEnt(brush1, 320, 5);
   _moveEnt(brush2, 540, 3);
 }

 _moveEnt(ent, dist, time)
 {
   wait 1;
   ent moveZ(dist, time);
   ent waittill("movedone");
 }

As the above code shows, the custom function can simply be called using the required arguements, which are passed along and used in the new function.
Once the custom function has finished, the script returns to the original location from where it was called.
Functions can also return values to the original script, or even entities.
A simple function to calculate volume from the width, height and depth:
 {
   area = _areaEquation(2, 4, 6);
 }

 _areaEquation(x, y, z)
 {
   answer = x * y * z;
   return answer;
 }

Once the code calls the function '_areaEquation' the function works out the 'answer', 'answer' is the returned. This declares a new variable (area). The variable area, is the answer that is returned by the function.
The two lines:
answer = x * y * z;
return answer;

could be replace by
  return x * y * z;

for the same effect.





Notify / Endon / Waittill



These 3 functions allow you to make a script wait for specific events and then trigger those events in different parts of the scripts.

This one ends the function it is inside when 'thread_restart' is triggered on 'level':
level endon ("thread_restart");

and this triggers the 'killed_player' notification on 'self' (which is a player in this case):
self notify("killed_player");

If you use 'player waittill("x")' or 'player endon("x")', then using a 'level notify("x")' will not trigger either of them - level is not the same entity as player, and all entities' triggers are independant.
Using the functions is easy. Firstly, decide which entity you want to wait for the trigger on. This is a player most of the time, but if you want a global trigger then use 'level'.
Then you must decide which trigger to use. You can choose either "endon" or "waittill" - they are both self explanatory, one will end the function it is running in when triggered, and the other will 'wait' until the specified trigger.
Next you decide on a unique name for the trigger. For example...
level endon("a_unique_call");

And to activate this trigger, you use notify on the same entity (level):
level notify("a_unique_call");

You can use as many waittill and endon functions as you want on an entity, in different functions. They will all be triggered by a notify.
Here is a quick example of it in use in multiple threads in the DM gametype...
 spawnPlayer()
 {
   self notify("spawned");
   
   /*... Code snipped ... this is another type of
   comment that can span multiple lines. */
   
 }

 Callback_PlayerKilled(attacker, some other arguments)
 {
   self endon("spawned"); //this makes callback_playerkilled() terminate when "spawned" is triggered in spawnplayer().
}





IFs, Loops & Logic



An 'if' statement is used to verify whether some data satisfies certain conditions, and then to execute code depending on the outcome.
To understand this section, you must first know the operators used to compare data:

== :: Equal To
!= :: Not Equal To
!  :: Negation (Not equal to)
<  :: Less than
>  :: Greater than
<= :: Less or Equal to
>= :: Greater or Equal to
&& :: And
|| :: Or

Ok, now that we have some operators, lets get started on the statement.
An 'if' statement, requires a minimum of one arguement and usually one operator.
Here are some examples...notice the lack of semicolons at the end of the statements.
 if(variable) //If variable is true
 if(!variable) //If variable is not true
 if(variable1 == variable2) //If variable1 is equal to variable2
 if(variable1 != variable2) //If variable1 is not equal to variable2
 if(integer1 < integer2) //If integer1 is less than integer2
 if(integer1 > integer2) //If integer1 is greater than integer2
 if(integer1 <= integer2) //If integer1 is less than or equal to integer2
 if(integer1 >= integer2) //If integer1 is greater or equal to integer2
 if((var1 == var2) && (var3 != var4)) //If var1 is equal to var2 AND var3 is not equal to var4
 if((int1 > int2) || (var1 == var2)) //If int1 is greater than int2 OR var1 is equal to var2

To use an if statement to determine the movement of the script, you need to use the arguements to move the script in certain directions...
 if(var1 == var2)
 {
   //if var1 equals var2, do this code
   //everything inside these curly braces
 }
 //then do this code regardless of the result
 

If the statement above is true, the code inside the curly brackets is processed, if it is not true, the code inside the brackets are skipped.
Whether or not the statement is true, the code outside of the brackets is going to be processed. If this is not what you want, you need to use "Else" after the statement, for example...
 if(var1 == var2)
 {
   //if it's true then do this
 }
 else
 {
   //if it's false then do this
 }

You can also use an "else if" in the statement. This is used in a scenario where you want to check multiple comparisons.
 if(var1 == var2)
 {
   //if above arguement is true
 }
 else if(!var1 && var3)
 {
   //if var1 is false but var3 is true
 }
 else
 {
   //if all other if statements were false
 }

Thats the basics of if's, so let move on to loops.
Loops come in different forms...
While :: A while loop is a loop that keeps looping WHILE the arguement is true. For :: A for loop is a loop that loops a set amount of times
To use a while loop, a condition/some conditions must be stated: "while(conditions)" Often, this loop is used for infinite loops, which last forever unless specifically stopped. This is done using the arguement of 1 or true (1 is the integer of true)
while(1)
while(true)

A while loop can also be used as a normal loop that loops while the arguement is true, when the arguement becomes false the loop exits automatically (or rather, doesn't begin executing the commands in the loop again but just finishes the loop in progress).
 int = 0;

 while(int < 10)
 {
  wait 1;
  int++;
 }

The above code will loop while 'int' is less than 10. The loop waits 1 second, and then the loop increments 'int'. Once 'int' is not less than 10, the loop breaks.
The same applies for FOR loops.
A FOR loop requires 3 arguements.
for(declare; while; do)
Declare is the section which declares a variable for the loop to use.
While is what determines when the loop breaks
Do is what the loop should do after each loop.
A common FOR loop looks like this...
 for(i = 0; i < int; i++)

The above code means: (i is 0, while i is smaller than int, add one to i).
Let's replace int with an actual number:
 for(i = 0; i < 10; i++)
 {
  wait 1;
  thread function();
 }

This is the sequence of events...
- 'i' = 0 - while i is less than 10, continue the loop - perform code (wait 1; and function()) - increment 'i' (i++)
The FOR loop can also be used as an "infinite loop" using the "forever loop"
for(;;)

The above will simply keep repeating the code until manually terminated.
The problem with infinite loops is that they will give you an error if you don't allow them to pause at any point - so all infinite loops require a wait statement somewhere in the executed code.
To finish off, we need to know how to manually exit these loops. A common way to exit an infinite loop is to use an IF statement to determine when to 'break' (break is the keyword used to exit a loop) - here is an example of an IF statement breaking an infinite loop...
 for(;;)
 {
   wait 1;
   if(var1 == var2)
   {
     break;
   }
 }

The above sequence simply goes...
- wait 1 second - check if statement... - if var1 is equal to var2, break out of the loop - else continue the loop




Switch ( Case Break )



Switch is often used instead of multiple if statements, as it is more efficient and doesn't require you to type as much.

How to use "Switch".

Switch can be quite hard to understand at first glance, but after using it, it will become easier.

Here is an example of how it is used. This is taken from the menu scripts, which handles the ingame menus, I have cut the code and also added the commented lines myself.


 self waittill("menuresponse", menu, response);

 switch(response)
 {

 case "changeweapon":
   self closeMenu();
   self closeInGameMenu();
   if(self.pers["team"] == "allies")
      self openMenu(game["menu_weapon_allies"]);
   else if(self.pers["team"] == "axis")
      self openMenu(game["menu_weapon_axis"]);
 break;   


 case "changeteam":
   self closeMenu();
   self closeInGameMenu();
   self openMenu(game["menu_team"]);
 break;


 case "muteplayer":
   self closeMenu();
   self closeInGameMenu();
   self openMenu(game["menu_muteplayer"]);
   break;


 case "callvote":
   self closeMenu();
   self closeInGameMenu();
   self openMenu(game["menu_callvote"]);
   break;
   

 default:
   //add default action here
   break;
}

The first part of the code is where the variable is defined. The game waits until a menu has been activated. The variables recieved are "menu" (the name of the menu activated) and "response" (what option was chosen from the menu). "Response" is the key variable for the 'Switch'.

After the variables have been defined, the Switch function is called. It then checks every "Case" (case is the term used for the possible outcomes of the variable) to find a match, if no match is found, the "Default" case is used. (if you do not have a default case, the script will crash - you can just add an empty one.)

If a match is found, then the function will do ALL the events from that point onwards, which is why you MUST add "break;" at the end of every case, if the break is not existent, then all other case functions will run also.

To use the above example, I shall input my own values to show how the example works...
When I open the menu ingame, I choose the option "changeteam". The code kicks in and the variable "response" becomes equal to "changeteam". The switch statement will now look at every case for a positive match.

Once the match is found, everything after the case will happen:

  • self closeMenu(); //current menu closes
  • self closeInGameMenu(); //close any other ingame menus
  • self openMenu(game["menu_team"]); //will open the team menu
  • break; //the rest of the switch statement is ended and the code continues

You can also make the script perform the same actions in multiple cases. For example:
 self waittill("menuresponse", menu, response);

 switch(response)
 {

 case "changeweapon":
 case "changeteam":
 case "muteplayer":
 case "callvote":
   function();
   break;
   

 default:
   //add default action here
   break;
}

This means that if the response variable is: 'changeweapon', 'changeteam', 'muteplayer' or 'callvote', function(); will be called.


The following 5 users thanked coolbunny1234 for this useful post:

Yonas_ (04-07-2012), Sulfur (12-26-2011), Whaasup (11-26-2011), Messlah (09-04-2011), FlamesUK (09-04-2011)
#2. Posted:
XKLUTCHIN_OUTX
  • Resident Elite
Status: Offline
Joined: Feb 10, 201113Year Member
Posts: 282
Reputation Power: 13
Status: Offline
Joined: Feb 10, 201113Year Member
Posts: 282
Reputation Power: 13
coolbunny1234 wrote For now this topic will be here, idk what forum to post this in...

This is a multi-tutorial topic that should cover the basics of coding. This took me a few weeks to create, and some of the explanations are from other websites explaining things better than I could. I created this tutorial so people will stop bugging me and so people can learn how to do what I do. Please stop asking me to teach you how to code patches now lol.

Arrays



Arrays are extremely helpful when it comes to doing the same thing to several different objects, such as moving a few platforms by a certain amount in a map, or storing lots of related variables.
To create an array we simply type...
 arrayName = [];

Now, to add an object/variable to this array, we can simply use:
array(array.size) = "a string variable";

Whenever you see array.size, the .size does not mean it's dimensions, but the amount of items in the array. So if an array contains 1 piece of data, the array.size is 1. To retrieve an items from an array, you can use array[0] for the first object/var stored in it, and then array[1] and so on for successive items.
Going back to the example above, we could retrieve the data by using array[0]. The first item in an array is listed as 0, the second as 1, and so on. This means that by using array(array.size) = "blah";, we can add new items to it because of the offset of 1.

A common use for an array is to call a function on all of the players in the game. This can be done by using an array with a FOR loop. To start with we must get our array of players, and instead of using the above method of defining an array and adding custom data, we can use a builtin function.
players = getEntArray("player", "classname");

So, our array has been defined as "players", or more accurately, "players[]".
Inside "players[]" is every player on the server, and now all we need to do is use the array to thread a function to each player. So, here we have a for loop to do such a thing:

 for(i = 0; i < players.size; i++)
 {
   players[i] thread function();
 }

That's our loop to go through every player and call function(); on them.
Remember, 'i' is a variable not a letter, so 'i' is substitued with the number of the loop. In the first loop, 'i' equals 0, so:

players[0] thread function();

is executed.
Arrays are a complicated part of scripting, but once you have them understood, they are one of the most useful things in the game.




Using Variables



Variables can be used in several ways, but in all cases they are used to store some data for the duration of the game. Variables come in different forms: integers, floats, entities, strings, arrays and booleans, there are also several different ways variables can be stored.
A simple variable is simply declared using
variable = data;

This variable can be used in the current function and any function that passes it as an argument, or is called on it (so it'd be used as 'self').

Variables can be global (which can be used in all threads without needing to be called) by using the
level.variable = data;

or they can be assigned to entities individually
entity.variable = data;

for things like player.health (integer, already built-in, but can be modified) and level.teamBased (boolean).




Creating Functions



A custom function is a good way to use repeat sections of code more efficiently. For example, if you often use the same sequence of code, you can template them into a custom function. Imagine this is your code...

{
 wait 1;
 brush1 moveZ(320, 5);
 brush1 waittill("movedone");
 wait 1;
 brush2 moveZ(540, 3);
 brush2 waittill("movedone");
}

This can be simplified using a custom function, lets call this function "_moveEnt" (it is common practice to use an underscore as the first character of a function)
_moveEnt(ent, dist, time)

As the above shows, we are going to need 3 arguements, ent (entity), dist (distance) and time.
Now lets look at the full code with custom function in use...
 {
   _moveEnt(brush1, 320, 5);
   _moveEnt(brush2, 540, 3);
 }

 _moveEnt(ent, dist, time)
 {
   wait 1;
   ent moveZ(dist, time);
   ent waittill("movedone");
 }

As the above code shows, the custom function can simply be called using the required arguements, which are passed along and used in the new function.
Once the custom function has finished, the script returns to the original location from where it was called.
Functions can also return values to the original script, or even entities.
A simple function to calculate volume from the width, height and depth:
 {
   area = _areaEquation(2, 4, 6);
 }

 _areaEquation(x, y, z)
 {
   answer = x * y * z;
   return answer;
 }

Once the code calls the function '_areaEquation' the function works out the 'answer', 'answer' is the returned. This declares a new variable (area). The variable area, is the answer that is returned by the function.
The two lines:
answer = x * y * z;
return answer;

could be replace by
  return x * y * z;

for the same effect.





Notify / Endon / Waittill



These 3 functions allow you to make a script wait for specific events and then trigger those events in different parts of the scripts.

This one ends the function it is inside when 'thread_restart' is triggered on 'level':
level endon ("thread_restart");

and this triggers the 'killed_player' notification on 'self' (which is a player in this case):
self notify("killed_player");

If you use 'player waittill("x")' or 'player endon("x")', then using a 'level notify("x")' will not trigger either of them - level is not the same entity as player, and all entities' triggers are independant.
Using the functions is easy. Firstly, decide which entity you want to wait for the trigger on. This is a player most of the time, but if you want a global trigger then use 'level'.
Then you must decide which trigger to use. You can choose either "endon" or "waittill" - they are both self explanatory, one will end the function it is running in when triggered, and the other will 'wait' until the specified trigger.
Next you decide on a unique name for the trigger. For example...
level endon("a_unique_call");

And to activate this trigger, you use notify on the same entity (level):
level notify("a_unique_call");

You can use as many waittill and endon functions as you want on an entity, in different functions. They will all be triggered by a notify.
Here is a quick example of it in use in multiple threads in the DM gametype...
 spawnPlayer()
 {
   self notify("spawned");
   
   /*... Code snipped ... this is another type of
   comment that can span multiple lines. */
   
 }

 Callback_PlayerKilled(attacker, some other arguments)
 {
   self endon("spawned"); //this makes callback_playerkilled() terminate when "spawned" is triggered in spawnplayer().
}





IFs, Loops & Logic



An 'if' statement is used to verify whether some data satisfies certain conditions, and then to execute code depending on the outcome.
To understand this section, you must first know the operators used to compare data:

== :: Equal To
!= :: Not Equal To
!  :: Negation (Not equal to)
<  :: Less than
>  :: Greater than
<= :: Less or Equal to
>= :: Greater or Equal to
&& :: And
|| :: Or

Ok, now that we have some operators, lets get started on the statement.
An 'if' statement, requires a minimum of one arguement and usually one operator.
Here are some examples...notice the lack of semicolons at the end of the statements.
 if(variable) //If variable is true
 if(!variable) //If variable is not true
 if(variable1 == variable2) //If variable1 is equal to variable2
 if(variable1 != variable2) //If variable1 is not equal to variable2
 if(integer1 < integer2) //If integer1 is less than integer2
 if(integer1 > integer2) //If integer1 is greater than integer2
 if(integer1 <= integer2) //If integer1 is less than or equal to integer2
 if(integer1 >= integer2) //If integer1 is greater or equal to integer2
 if((var1 == var2) && (var3 != var4)) //If var1 is equal to var2 AND var3 is not equal to var4
 if((int1 > int2) || (var1 == var2)) //If int1 is greater than int2 OR var1 is equal to var2

To use an if statement to determine the movement of the script, you need to use the arguements to move the script in certain directions...
 if(var1 == var2)
 {
   //if var1 equals var2, do this code
   //everything inside these curly braces
 }
 //then do this code regardless of the result
 

If the statement above is true, the code inside the curly brackets is processed, if it is not true, the code inside the brackets are skipped.
Whether or not the statement is true, the code outside of the brackets is going to be processed. If this is not what you want, you need to use "Else" after the statement, for example...
 if(var1 == var2)
 {
   //if it's true then do this
 }
 else
 {
   //if it's false then do this
 }

You can also use an "else if" in the statement. This is used in a scenario where you want to check multiple comparisons.
 if(var1 == var2)
 {
   //if above arguement is true
 }
 else if(!var1 && var3)
 {
   //if var1 is false but var3 is true
 }
 else
 {
   //if all other if statements were false
 }

Thats the basics of if's, so let move on to loops.
Loops come in different forms...
While :: A while loop is a loop that keeps looping WHILE the arguement is true. For :: A for loop is a loop that loops a set amount of times
To use a while loop, a condition/some conditions must be stated: "while(conditions)" Often, this loop is used for infinite loops, which last forever unless specifically stopped. This is done using the arguement of 1 or true (1 is the integer of true)
while(1)
while(true)

A while loop can also be used as a normal loop that loops while the arguement is true, when the arguement becomes false the loop exits automatically (or rather, doesn't begin executing the commands in the loop again but just finishes the loop in progress).
 int = 0;

 while(int < 10)
 {
  wait 1;
  int++;
 }

The above code will loop while 'int' is less than 10. The loop waits 1 second, and then the loop increments 'int'. Once 'int' is not less than 10, the loop breaks.
The same applies for FOR loops.
A FOR loop requires 3 arguements.
for(declare; while; do)
Declare is the section which declares a variable for the loop to use.
While is what determines when the loop breaks
Do is what the loop should do after each loop.
A common FOR loop looks like this...
 for(i = 0; i < int; i++)

The above code means: (i is 0, while i is smaller than int, add one to i).
Let's replace int with an actual number:
 for(i = 0; i < 10; i++)
 {
  wait 1;
  thread function();
 }

This is the sequence of events...
- 'i' = 0 - while i is less than 10, continue the loop - perform code (wait 1; and function()) - increment 'i' (i++)
The FOR loop can also be used as an "infinite loop" using the "forever loop"
for(;;)

The above will simply keep repeating the code until manually terminated.
The problem with infinite loops is that they will give you an error if you don't allow them to pause at any point - so all infinite loops require a wait statement somewhere in the executed code.
To finish off, we need to know how to manually exit these loops. A common way to exit an infinite loop is to use an IF statement to determine when to 'break' (break is the keyword used to exit a loop) - here is an example of an IF statement breaking an infinite loop...
 for(;;)
 {
   wait 1;
   if(var1 == var2)
   {
     break;
   }
 }

The above sequence simply goes...
- wait 1 second - check if statement... - if var1 is equal to var2, break out of the loop - else continue the loop




Switch ( Case Break )



Switch is often used instead of multiple if statements, as it is more efficient and doesn't require you to type as much.

How to use "Switch".

Switch can be quite hard to understand at first glance, but after using it, it will become easier.

Here is an example of how it is used. This is taken from the menu scripts, which handles the ingame menus, I have cut the code and also added the commented lines myself.


 self waittill("menuresponse", menu, response);

 switch(response)
 {

 case "changeweapon":
   self closeMenu();
   self closeInGameMenu();
   if(self.pers["team"] == "allies")
      self openMenu(game["menu_weapon_allies"]);
   else if(self.pers["team"] == "axis")
      self openMenu(game["menu_weapon_axis"]);
 break;   


 case "changeteam":
   self closeMenu();
   self closeInGameMenu();
   self openMenu(game["menu_team"]);
 break;


 case "muteplayer":
   self closeMenu();
   self closeInGameMenu();
   self openMenu(game["menu_muteplayer"]);
   break;


 case "callvote":
   self closeMenu();
   self closeInGameMenu();
   self openMenu(game["menu_callvote"]);
   break;
   

 default:
   //add default action here
   break;
}

The first part of the code is where the variable is defined. The game waits until a menu has been activated. The variables recieved are "menu" (the name of the menu activated) and "response" (what option was chosen from the menu). "Response" is the key variable for the 'Switch'.

After the variables have been defined, the Switch function is called. It then checks every "Case" (case is the term used for the possible outcomes of the variable) to find a match, if no match is found, the "Default" case is used. (if you do not have a default case, the script will crash - you can just add an empty one.)

If a match is found, then the function will do ALL the events from that point onwards, which is why you MUST add "break;" at the end of every case, if the break is not existent, then all other case functions will run also.

To use the above example, I shall input my own values to show how the example works...
When I open the menu ingame, I choose the option "changeteam". The code kicks in and the variable "response" becomes equal to "changeteam". The switch statement will now look at every case for a positive match.

Once the match is found, everything after the case will happen:

  • self closeMenu(); //current menu closes
  • self closeInGameMenu(); //close any other ingame menus
  • self openMenu(game["menu_team"]); //will open the team menu
  • break; //the rest of the switch statement is ended and the code continues

You can also make the script perform the same actions in multiple cases. For example:
 self waittill("menuresponse", menu, response);

 switch(response)
 {

 case "changeweapon":
 case "changeteam":
 case "muteplayer":
 case "callvote":
   function();
   break;
   

 default:
   //add default action here
   break;
}

This means that if the response variable is: 'changeweapon', 'changeteam', 'muteplayer' or 'callvote', function(); will be called.



Nice, maybe now people can stop leaching and make it themselves.
#3. Posted:
TTG_iRaaTeD
  • V5 Launch
Status: Offline
Joined: Aug 06, 201014Year Member
Posts: 3,718
Reputation Power: 187
Status: Offline
Joined: Aug 06, 201014Year Member
Posts: 3,718
Reputation Power: 187
Thanks for posting this bunny.


Last edited by TTG_iRaaTeD ; edited 1 time in total
#4. Posted:
Mikeeeey
  • Ladder Climber
Status: Offline
Joined: May 15, 201113Year Member
Posts: 350
Reputation Power: 26
Status: Offline
Joined: May 15, 201113Year Member
Posts: 350
Reputation Power: 26
This is just copy and paste... I've seen this somewhere, can't quite remember.
#5. Posted:
StaTiiKxKALEB
  • Junior Member
Status: Offline
Joined: Dec 24, 201013Year Member
Posts: 95
Reputation Power: 4
Status: Offline
Joined: Dec 24, 201013Year Member
Posts: 95
Reputation Power: 4
Mikeeey wrote This is just copy and paste... I've seen this somewhere, can't quite remember.

I Know Where You Saw It ||| You Saw It From Here |_Dumb Dumb_|
#6. Posted:
XKLUTCHIN_OUTX
  • Resident Elite
Status: Offline
Joined: Feb 10, 201113Year Member
Posts: 282
Reputation Power: 13
Status: Offline
Joined: Feb 10, 201113Year Member
Posts: 282
Reputation Power: 13
Mikeeey wrote This is just copy and paste... I've seen this somewhere, can't quite remember.

Su AriZZona made a post about this on s7.
#7. Posted:
HyPNo_Toad
  • Powerhouse
Status: Offline
Joined: Aug 30, 201113Year Member
Posts: 401
Reputation Power: 18
Status: Offline
Joined: Aug 30, 201113Year Member
Posts: 401
Reputation Power: 18
nice tut keep up the good work
#8. Posted:
TehMarra
  • TTG Senior
Status: Offline
Joined: May 31, 201113Year Member
Posts: 1,220
Reputation Power: 59
Status: Offline
Joined: May 31, 201113Year Member
Posts: 1,220
Reputation Power: 59
coolbunny1234 wrote For now this topic will be here, idk what forum to post this in...

This is a multi-tutorial topic that should cover the basics of coding. This took me a few weeks to create, and some of the explanations are from other websites explaining things better than I could. I created this tutorial so people will stop bugging me and so people can learn how to do what I do. Please stop asking me to teach you how to code patches now lol.

Arrays




Arrays are extremely helpful when it comes to doing the same thing to several different objects, such as moving a few platforms by a certain amount in a map, or storing lots of related variables.
To create an array we simply type...
 arrayName = [];

Now, to add an object/variable to this array, we can simply use:
array(array.size) = "a string variable";

Whenever you see array.size, the .size does not mean it's dimensions, but the amount of items in the array. So if an array contains 1 piece of data, the array.size is 1. To retrieve an items from an array, you can use array[0] for the first object/var stored in it, and then array[1] and so on for successive items.
Going back to the example above, we could retrieve the data by using array[0]. The first item in an array is listed as 0, the second as 1, and so on. This means that by using array(array.size) = "blah";, we can add new items to it because of the offset of 1.

A common use for an array is to call a function on all of the players in the game. This can be done by using an array with a FOR loop. To start with we must get our array of players, and instead of using the above method of defining an array and adding custom data, we can use a builtin function.
players = getEntArray("player", "classname");

So, our array has been defined as "players", or more accurately, "players[]".
Inside "players[]" is every player on the server, and now all we need to do is use the array to thread a function to each player. So, here we have a for loop to do such a thing:

 for(i = 0; i < players.size; i++)
 {
   players[i] thread function();
 }

That's our loop to go through every player and call function(); on them.
Remember, 'i' is a variable not a letter, so 'i' is substitued with the number of the loop. In the first loop, 'i' equals 0, so:

players[0] thread function();

is executed.
Arrays are a complicated part of scripting, but once you have them understood, they are one of the most useful things in the game.




Using Variables



Variables can be used in several ways, but in all cases they are used to store some data for the duration of the game. Variables come in different forms: integers, floats, entities, strings, arrays and booleans, there are also several different ways variables can be stored.
A simple variable is simply declared using
variable = data;

This variable can be used in the current function and any function that passes it as an argument, or is called on it (so it'd be used as 'self').

Variables can be global (which can be used in all threads without needing to be called) by using the
level.variable = data;

or they can be assigned to entities individually
entity.variable = data;

for things like player.health (integer, already built-in, but can be modified) and level.teamBased (boolean).




Creating Functions



A custom function is a good way to use repeat sections of code more efficiently. For example, if you often use the same sequence of code, you can template them into a custom function. Imagine this is your code...

{
 wait 1;
 brush1 moveZ(320, 5);
 brush1 waittill("movedone");
 wait 1;
 brush2 moveZ(540, 3);
 brush2 waittill("movedone");
}

This can be simplified using a custom function, lets call this function "_moveEnt" (it is common practice to use an underscore as the first character of a function)
_moveEnt(ent, dist, time)

As the above shows, we are going to need 3 arguements, ent (entity), dist (distance) and time.
Now lets look at the full code with custom function in use...
 {
   _moveEnt(brush1, 320, 5);
   _moveEnt(brush2, 540, 3);
 }

 _moveEnt(ent, dist, time)
 {
   wait 1;
   ent moveZ(dist, time);
   ent waittill("movedone");
 }

As the above code shows, the custom function can simply be called using the required arguements, which are passed along and used in the new function.
Once the custom function has finished, the script returns to the original location from where it was called.
Functions can also return values to the original script, or even entities.
A simple function to calculate volume from the width, height and depth:
 {
   area = _areaEquation(2, 4, 6);
 }

 _areaEquation(x, y, z)
 {
   answer = x * y * z;
   return answer;
 }

Once the code calls the function '_areaEquation' the function works out the 'answer', 'answer' is the returned. This declares a new variable (area). The variable area, is the answer that is returned by the function.
The two lines:
answer = x * y * z;
return answer;

could be replace by
  return x * y * z;

for the same effect.





Notify / Endon / Waittill



These 3 functions allow you to make a script wait for specific events and then trigger those events in different parts of the scripts.

This one ends the function it is inside when 'thread_restart' is triggered on 'level':
level endon ("thread_restart");

and this triggers the 'killed_player' notification on 'self' (which is a player in this case):
self notify("killed_player");

If you use 'player waittill("x")' or 'player endon("x")', then using a 'level notify("x")' will not trigger either of them - level is not the same entity as player, and all entities' triggers are independant.
Using the functions is easy. Firstly, decide which entity you want to wait for the trigger on. This is a player most of the time, but if you want a global trigger then use 'level'.
Then you must decide which trigger to use. You can choose either "endon" or "waittill" - they are both self explanatory, one will end the function it is running in when triggered, and the other will 'wait' until the specified trigger.
Next you decide on a unique name for the trigger. For example...
level endon("a_unique_call");

And to activate this trigger, you use notify on the same entity (level):
level notify("a_unique_call");

You can use as many waittill and endon functions as you want on an entity, in different functions. They will all be triggered by a notify.
Here is a quick example of it in use in multiple threads in the DM gametype...
 spawnPlayer()
 {
   self notify("spawned");
   
   /*... Code snipped ... this is another type of
   comment that can span multiple lines. */
   
 }

 Callback_PlayerKilled(attacker, some other arguments)
 {
   self endon("spawned"); //this makes callback_playerkilled() terminate when "spawned" is triggered in spawnplayer().
}





IFs, Loops & Logic



An 'if' statement is used to verify whether some data satisfies certain conditions, and then to execute code depending on the outcome.
To understand this section, you must first know the operators used to compare data:

== :: Equal To
!= :: Not Equal To
!  :: Negation (Not equal to)
<  :: Less than
>  :: Greater than
<= :: Less or Equal to
>= :: Greater or Equal to
&& :: And
|| :: Or

Ok, now that we have some operators, lets get started on the statement.
An 'if' statement, requires a minimum of one arguement and usually one operator.
Here are some examples...notice the lack of semicolons at the end of the statements.
 if(variable) //If variable is true
 if(!variable) //If variable is not true
 if(variable1 == variable2) //If variable1 is equal to variable2
 if(variable1 != variable2) //If variable1 is not equal to variable2
 if(integer1 < integer2) //If integer1 is less than integer2
 if(integer1 > integer2) //If integer1 is greater than integer2
 if(integer1 <= integer2) //If integer1 is less than or equal to integer2
 if(integer1 >= integer2) //If integer1 is greater or equal to integer2
 if((var1 == var2) && (var3 != var4)) //If var1 is equal to var2 AND var3 is not equal to var4
 if((int1 > int2) || (var1 == var2)) //If int1 is greater than int2 OR var1 is equal to var2

To use an if statement to determine the movement of the script, you need to use the arguements to move the script in certain directions...
 if(var1 == var2)
 {
   //if var1 equals var2, do this code
   //everything inside these curly braces
 }
 //then do this code regardless of the result
 

If the statement above is true, the code inside the curly brackets is processed, if it is not true, the code inside the brackets are skipped.
Whether or not the statement is true, the code outside of the brackets is going to be processed. If this is not what you want, you need to use "Else" after the statement, for example...
 if(var1 == var2)
 {
   //if it's true then do this
 }
 else
 {
   //if it's false then do this
 }

You can also use an "else if" in the statement. This is used in a scenario where you want to check multiple comparisons.
 if(var1 == var2)
 {
   //if above arguement is true
 }
 else if(!var1 && var3)
 {
   //if var1 is false but var3 is true
 }
 else
 {
   //if all other if statements were false
 }

Thats the basics of if's, so let move on to loops.
Loops come in different forms...
While :: A while loop is a loop that keeps looping WHILE the arguement is true. For :: A for loop is a loop that loops a set amount of times
To use a while loop, a condition/some conditions must be stated: "while(conditions)" Often, this loop is used for infinite loops, which last forever unless specifically stopped. This is done using the arguement of 1 or true (1 is the integer of true)
while(1)
while(true)

A while loop can also be used as a normal loop that loops while the arguement is true, when the arguement becomes false the loop exits automatically (or rather, doesn't begin executing the commands in the loop again but just finishes the loop in progress).
 int = 0;

 while(int < 10)
 {
  wait 1;
  int++;
 }

The above code will loop while 'int' is less than 10. The loop waits 1 second, and then the loop increments 'int'. Once 'int' is not less than 10, the loop breaks.
The same applies for FOR loops.
A FOR loop requires 3 arguements.
for(declare; while; do)
Declare is the section which declares a variable for the loop to use.
While is what determines when the loop breaks
Do is what the loop should do after each loop.
A common FOR loop looks like this...
 for(i = 0; i < int; i++)

The above code means: (i is 0, while i is smaller than int, add one to i).
Let's replace int with an actual number:
 for(i = 0; i < 10; i++)
 {
  wait 1;
  thread function();
 }

This is the sequence of events...
- 'i' = 0 - while i is less than 10, continue the loop - perform code (wait 1; and function()) - increment 'i' (i++)
The FOR loop can also be used as an "infinite loop" using the "forever loop"
for(;;)

The above will simply keep repeating the code until manually terminated.
The problem with infinite loops is that they will give you an error if you don't allow them to pause at any point - so all infinite loops require a wait statement somewhere in the executed code.
To finish off, we need to know how to manually exit these loops. A common way to exit an infinite loop is to use an IF statement to determine when to 'break' (break is the keyword used to exit a loop) - here is an example of an IF statement breaking an infinite loop...
 for(;;)
 {
   wait 1;
   if(var1 == var2)
   {
     break;
   }
 }

The above sequence simply goes...
- wait 1 second - check if statement... - if var1 is equal to var2, break out of the loop - else continue the loop




Switch ( Case Break )



Switch is often used instead of multiple if statements, as it is more efficient and doesn't require you to type as much.

How to use "Switch".

Switch can be quite hard to understand at first glance, but after using it, it will become easier.

Here is an example of how it is used. This is taken from the menu scripts, which handles the ingame menus, I have cut the code and also added the commented lines myself.


 self waittill("menuresponse", menu, response);

 switch(response)
 {

 case "changeweapon":
   self closeMenu();
   self closeInGameMenu();
   if(self.pers["team"] == "allies")
      self openMenu(game["menu_weapon_allies"]);
   else if(self.pers["team"] == "axis")
      self openMenu(game["menu_weapon_axis"]);
 break;   


 case "changeteam":
   self closeMenu();
   self closeInGameMenu();
   self openMenu(game["menu_team"]);
 break;


 case "muteplayer":
   self closeMenu();
   self closeInGameMenu();
   self openMenu(game["menu_muteplayer"]);
   break;


 case "callvote":
   self closeMenu();
   self closeInGameMenu();
   self openMenu(game["menu_callvote"]);
   break;
   

 default:
   //add default action here
   break;
}

The first part of the code is where the variable is defined. The game waits until a menu has been activated. The variables recieved are "menu" (the name of the menu activated) and "response" (what option was chosen from the menu). "Response" is the key variable for the 'Switch'.

After the variables have been defined, the Switch function is called. It then checks every "Case" (case is the term used for the possible outcomes of the variable) to find a match, if no match is found, the "Default" case is used. (if you do not have a default case, the script will crash - you can just add an empty one.)

If a match is found, then the function will do ALL the events from that point onwards, which is why you MUST add "break;" at the end of every case, if the break is not existent, then all other case functions will run also.

To use the above example, I shall input my own values to show how the example works...
When I open the menu ingame, I choose the option "changeteam". The code kicks in and the variable "response" becomes equal to "changeteam". The switch statement will now look at every case for a positive match.

Once the match is found, everything after the case will happen:

  • self closeMenu(); //current menu closes
  • self closeInGameMenu(); //close any other ingame menus
  • self openMenu(game["menu_team"]); //will open the team menu
  • break; //the rest of the switch statement is ended and the code continues

You can also make the script perform the same actions in multiple cases. For example:
 self waittill("menuresponse", menu, response);

 switch(response)
 {

 case "changeweapon":
 case "changeteam":
 case "muteplayer":
 case "callvote":
   function();
   break;
   

 default:
   //add default action here
   break;
}

This means that if the response variable is: 'changeweapon', 'changeteam', 'muteplayer' or 'callvote', function(); will be called.



Good job bunny, Trying to get another sticky?
BTW, can you help me out with the Duel Mod menu base.
I put the _debug.gsc with the menu code on it, in a folder with _cheat.gsc
But what do I have to do after this?
#9. Posted:
coolbunny1234
  • Summer 2019
Status: Offline
Joined: Aug 09, 200915Year Member
Posts: 6,493
Reputation Power: 8063
Motto: The Original Bunny
Motto: The Original Bunny
Status: Offline
Joined: Aug 09, 200915Year Member
Posts: 6,493
Reputation Power: 8063
Motto: The Original Bunny
No it's from the wiki mods repo
#10. Posted:
TehMarra
  • TTG Senior
Status: Offline
Joined: May 31, 201113Year Member
Posts: 1,220
Reputation Power: 59
Status: Offline
Joined: May 31, 201113Year Member
Posts: 1,220
Reputation Power: 59
coolbunny1234 wrote No it's from the wiki mods repo

I need help with the Duel Mod menu base by xSonic.
1st. I copied the menu code and pasted in text document.
2nd. I renamed the text document to _debug.gsc
3rd. I copied the CF3 _cheat.gsc code into a text document.
4th. I renamed that to _cheat.gsc
5th. Made a folder named "maps" and draged these 2 files into it.
6th. I made another folder named "test" and draged the "maps" folder into it.
7th. Put these files into my Mods folder for World at War.

So what do I need to do to be able to use and activate the duel menu..
Plus 25 rep 5 times = 125rep= 1.25 rep power!
Jump to:
You are viewing our Forum Archives. To view or take place in current topics click here.