View Single Post
Emp`
AMX Mod X Plugin Approver
Join Date: Aug 2005
Location: Decapod 10
Old 06-10-2009 , 15:07   Re: Pawn Picture Tutorial
Reply With Quote #3


Structure [top]

All code has a type of structure to follow, you cannot just put random pieces of code in random spots and expect it to work.
In a warehouse, you cannot put a door on the roof and expect people to be able to walk in through it. You do not want to put a doorway in the middle of someone's office.
You need to place your code in the correct places.

Here is the order of items that most plugins are created:


Large Comment [structure] [top]
At the begining of a plugin's code there can be a large comment. The comment usually talks about the plugin, what changes have been made, or other things. This is just friendly for people trying to read the code, so they know what the code is going to do. However, most plugins do not contain this, and just jump into the next part.


Includes [structure] [top]
Before you start any other code, one will want to include some libraries. Wait what? You can think of them as stores. We only want to go to stores that have the things we want.

We wouldn't go to Ralphs and BestBuy if we are trying to buy a computer, we would just go to BestBuy.

What do the libraries do? They allow you to use natives from other places.
Some libraries have their own forwards already too. You can think of it as if the stores are sending you information about the store.

Almost every plugin will contain: #include <amxmodx> as it has the basic natives for creating a plugin.
The amxmodx include file also contains the forwards plugin_init and plugin_precache.

Once you have your includes setup, you can start with some actual code.


Defines [structure] [top]
These are just helpers for people. They help keep code constant in multiple areas.
In the format: #define DEFINE_NAME definition
DEFINE_NAME is what will be replaced in the code.
definition is what it will be replaced with.
  • Note that most people use CAPS to indicate that something does not change.

So if we have: #define MAX_PLAYERS 32
Everywhere in the code that has MAX_PLAYERS, it will change to 32.

Some plugins don't use any self-made defines and just continue to the next thing.


Global Variables [structure] [top]
Okay, you should have an understanding of variables and this is a small little addon.
If a variable is global it can be accessed everywhere in your warehouse.
Usually people place a "g" at the begining of a global variable's name to indicate that it is global.
So if we wanted to make a global variable, we would simply do:
Code:
new gVariableName
Some plugins don't use any global variables and just continue to the next thing.


Plugin Loading [structure] [top]
As talked about before, this is where the forward plugin_init comes into effect.
In most cases, plugins have their plugin_init in the form:
Code:
public plugin_init()
{
	register_plugin( "Plugin Name", "Plugin Version", "Plugin Author" )

	//Add all extra stuff here
}
Extra stuff can be anything, such as registering cvars, events, or forwards.

Another core part to some plugins is precaching. This is usually done in the forward plugin_precache.
Precaching tells the server that we are going to use this model, sprites, or sound so make sure the players connecting have these files.
If the player does not have this file, then they download it.

If you use a model, sprite, or sound in your plugin, you should precache it or else when you try to use it, the server will most likely crash.
It is usually done in this format:
Code:
public plugin_precache
{
	//For models:
	precache_model("models/model_name.mdl")

	//For sprites:
	precache_model("sprites/sprite_name.spr")

	//For sounds:
	precache_sound("sound_name.wav")
	// Note that it is recommended that sounds are .wav files
}
  • Note that there can be subfolders in the file's location Eg:
    Code:
    "models/folder/model.mdl"
  • Note that plugin_precache usually happens before plugin_init

Now that our plugin is loaded, we can actually do some things now.


Functions and Forwards [structure] [top]
First I should mention that the only thing that serperates Functions and Forwards is that Forwards are declared public and can be accessed by other plugins/modules.

Functions are only accessible from the plugin they are created in. Otherwise, they behave exactly the same.

I'm going to stop refering to them serparetly, and instead only refer to them as functions.
If it has public in front, assume it is a forward.

Functions are usually created in the format:
Code:
FunctionName(parameters)
{
}
And they execute all the code within the brackets.
You cannot create a function within another function.
If you create a variable inside a function, it is only accessible in that function.


Statements and Loops [structure] [top]
There are several types of statements and loops, and here are the more common.
  • if( ){ }
  • if( ){ }else{ }
  • switch( ){ case CONST:{ } case CONST2:{ } default:{ } }
  • for( { }; ( ); { } ){ }
  • while( ){ }
  • do{ } while( )

The main parts of the statements and loops are the conditional ( ) and the action { }.
  • if : statement : If the conditional is true, execute the action. Eg:
    Code:
    if( variable == 1 )
    {
    		//if variable == 1 execute this code
    }
  • if...else : statement : If the conditional is true, execute the action, otherwise execute the second action. Eg:
    Code:
    if( variable == 1 )
    {
    		//if variable == 1 execute this code
    }
    else
    {
    		//if variable != 1 execute this code
    }
  • switch : statement : Executes the corresponding action. There can be any amount of cases and the default is not required. Eg:
    Code:
    switch( variable )
    {
    	case 0:
    	{
    		//if variable == 0 execute this code
    	}
    	case 1:
    	{
    		//if variable == 1 execute this code
    	}
    	default:
    	{
    		//if variable is not any of the preceding cases execute this code
    	}
    }
  • for : loop : Executes the first action when starting. Checks the middle conditional, if true it stops the loop. At the end of the last action, it executes the second action. Eg:
    Code:
    for( new variable; variable < 5; variable++ )
    {
    	//this code will be executed with the following values for variable: 0, 1, 2, 3, 4
    }
  • while : loop : Checks conditional, if true it executes the action. Eg:
    Code:
    while( Function() )
    {
    	//this code will be executed until Function() returns false
    }
  • do...while : loop : Executes the action at least once, it repeats the action until the conditional is false. Eg:
    Code:
    do
    {
    	//this code will be executed at least once, and more until Function() returns false
    }
    while( Function() )
  • Extras for loops:
    • break : stops a loop
    • continue : goes to the next sequence of a loop
  • Be careful not to get stuck in an infinite loop!


Brackets [structure] [top]
Types of Brackets:
  • Curly-Brackets: { }
  • Square-Brackets: [ ]
  • Parenthesis: ( )
First of all, you need to make sure that you have a matching close bracket/parenthesis for each opening bracket/parenthesis.

In most conditions for square-brackets and parenthesis, you will want to have the closing part on the same line.
On the other hand, curly-brackets are mainly used for multiple lines.

Curly-brackets can be used to represent a length of code that needs to be executed.
By default, the compiler assumes that there will only be a single line of code to execute. However, to execute more than one, you can use Curly-Brackets.
Eg:
Code:
if( variable )
	Function();
	//Function is the only part within the if statement
	Function2();
	//Function2 is not within the if statement
Code:
if( variable )
{
	Function();
	//Function is in the if statement
	Function2();
	//and so is Function2
}

White-Space and Indentation [structure] [top]
White-Space (spaces, tabs, new lines) do not effect performance, but greatly effect being able to read the code.
For indentation, a common rule of thumb is, between every new set of curly-brackets add another tab. You can either use tabs or spaces, but as long as they are the same.
Code:
Function()
{
	new variable, variable2

	if( variable )
	{

		//added a tab for new curly brackets

		if( variable2 )
		{

			//added another tab

		}

	}
}
This helps keep your code readable. Every time you show someone with code that is not indented properly, a kitten dies.
If you try to compile your code and it does not have proper indentation, it will give you a warning for "loose indentation".



Tips and Tricks for Getting Started [top]

! (not):
The exclamation mark can be substituted with the word not.
For example, if you have
Code:
if( !is_user_alive(id) )
It means: if the user is not alive.
Additionally, this can be applied to variables. If you have:
Code:
if( !variable )
It means: if the variable is zeroed

Operator shortcuts:
Code:
//If you have to do something like this
variable = variable + other_variable
//you can shorten your code to
variable += other_variable
//this works with all operators (+,-,*,/,etc.)
Increase/Decrease by one:
Code:
//If you find yourself adding or subtracting one, you can use this shortcut
variable++ //this increases by one
variable-- //this decreases by one
To clear a string:
Code:
string_name[0] = '^0'
Natives with extra formatting
Some natives require extra formatting, the most common are:
  • format
  • formatex
  • log_amx
  • client_print
When formatting a string:
  • %d and %i : replaces with the corresponding integer parameter
    %f : replaces with the corresponding float parameter
    %s : replaces with the corresponding string parameter

Using set_task
If you need something to happen after an amount of time, use the native set_task.
Code:
// The parameters break down as such:
// * Float:time - Interval of timer in second. (minimum 0.1 seconds)
// * function[] - A string that contains the public function to run on the timer.
// * id - A unique id to assign to the task.
// * parameter - An array contain data to send to the timer function.
// * len - Size of the array to send to the timer function.
// * flags - One of the following:
// -- "a" - Repeat task a specified number of times
// -- "b" - Loop task infinitely
// -- "c" - do task on time after a map timeleft
// -- "d" - do task on time before a map timeleft
// * repeat - If flags is "a", specifies the number of times to repeat the task. 
set_task ( Float:time, const function[], id = 0, parameter[]="", len = 0, flags[]="", repeat = 0 )
  • Note that the function being called needs to be declared as public.
  • Try to understand this thread


Other Help [top]

Introduction to Pawn - an introduction to the Pawn language

Introduction to AMXX Scripting - an introduction to creating plugins

Pawn Tutorial - an introduction to Pawn for more advanced users

Programming for starters - another basic tutorial for learning Pawn

Beginner Scripting Tutorial - a small tutorial for creating your first plugin

Selective Introduction to AMXX scripting - covers some things for making a plugin

Scripting Tutorial - old tutorial with an example .sma

Video Guide for Local Compiling - a guide to compiling on your computer

Compiling Errors - a list of errors one may encounter while compiling

Tutorial for Half-Life Position, Velocity, and Angles

List of CS/CZ/DOD Events/Messages - list of forwards for CS/CZ/DOD

Good Programming Habits - habits that coders should try to follow

Code Styling - more styling that coders should try to follow

Entities: what they are and how to use them - guide to entities (objects in the game)

Messages (Temp Entities, Game Events, etc.) - introduction to messages (effects)

Cvar Information - information about cvars and how to use them in your code


Donations [top]

(Click to Donate)


Last edited by Emp`; 05-17-2020 at 20:31. Reason: fixed images, thanks addons_zz
Emp` is offline
Send a message via AIM to Emp` Send a message via MSN to Emp` Send a message via Yahoo to Emp` Send a message via Skype™ to Emp`