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


The last type of variable we will be addressing is the Floating Point or Float for short.
To create a Float variable we use:
Code:
new Float:variable_name


Floats can be almost any rational number (oh no another math term!)
You can tell it is a Float because the number always has a decimal point.
Here are some examples of values you can set:
  • ..., -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, ...
  • ..., -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, ...
  • 3.567, 2859.92, 28.3
Basically it can be any number with a decimal.
  • Note that Floats start with the value 0.0


Okay, so here is a recap of variables:
  • Variable Names - Can be named almost anything, but better to be named something similar to what it is used for.
  • Names should only have: letters, numbers, and underscores
  • Variables hold numbers. They do nothing but pretend to be the number they are holding.
  • There are three main types of variables: Integers, Bools, Floats
  • Integers are whole numbers. They start with a value of 0
  • Bools are true or false. They start with a value of false
  • Floats are numbers with decimals. They start with a value of 0.0


Arrays and Strings [top]

These are simple things to remember with variables.

Arrays can be thought of as a row of boxes grouped together.


To create an array, we use similar code to creating a variable:
Code:
new array_name[4]
  • Note that all the boxes share the same name
  • The number in square-brackets is how many boxes to create

If we want to create an array of 10 boxes, we would do:
Code:
new array_name[10]
When referencing the individual boxes, we use:
Code:
array_name[box_number]
  • Note that the box numbers are zero-based, so if we want the first box: array_name[0], second box: array_name[1], third box: array_name[2], etc.
  • Note that you cannot do array_name[-1], there are no negatively placed boxes.
  • If creating new array_name[3] there is no fourth box, so you cannot do array_name[3]
  • The last box you can use is the # created with -1. Ie.
    • array[4] has 4 boxes, 4-1 == 3, last box number is 3
    • array[11] has 11 boxes, 11-1 == 10, last box number is 10
    • array[32] has 32 boxes, 32-1 == 31, last box number is 31
  • You have to use integers within square-brackets

If we want to initialize an array with values, you do the following:
Code:
new array[5] = {
	10,	//this is for the first box
	3,		//second box
	600,	//third box
	-5,	//fourth box
	20	//fifth and final box. notice it does not have a comma after its value
}
Why would you want an array? Here is an example:
  • You know that there is a max of 32 players in the server.
  • Let's say we want to know how many kills each player has
  • We would then create new kills_array[32] and use kills_array[ id - 1 ] for each player
  • Note that we do "-1" because the first player will use the first box, second player uses second box, etc.
  • However, most people do not like using the "-1", so instead we create the array with max players +1 == 32 + 1 == 33
  • new kills_array[33] then we can just use kills_array[ id ]

"So what else about arrays?" you might ask. Well we can declare types of arrays just like variables:
Code:
new Float:array[3]
new bool:array[32]
Now I know your next question, "why...?"

Well, here is one common example:
  • A players origin (location) in a map is represented by 3 floating points. One is their X position, one is their Y position, and you guessed it, the last is their Z position.
  • In the HalfLife Engine, the Z position is a players height in the map.
  • We then would create:
    Code:
    new Float:Origin[3]
    X == first box, Y == second box, Z == third box
  • Then we could increase their height by 50 units:
    Code:
    Origin[2] = Origin[2] + 50.0

Okay... now onto Strings.

Strings are basically arrays used to represent words, phrases, and any other text that might be seen.

For example, we can create an array to hold a players name.
Code:
new Name[32]
Now each box we are going to assign a number that represents a different ASCII character.
  • 'A' to 'Z' characters are the numbers 65 to 90
  • 'a' to 'z' characters are the numbers 97 to 122
However, we don't want to memorize every single number for each character, so instead we use apostrophes around the character.
So we can do:
Code:
new Name[32]
Name[0] = 'M'
Name[1] = 'y'
Name[2] = ' '
Name[3] = 'N'
Name[4] = 'a'
Name[5] = 'm'
Name[6] = 'e'
Name[7] = '^0'
  • Note that each box holds one character.
  • Note that we use '^0' to identify the end of a string.
  • Our code results in: Name == "My Name"

However, we do not want to have to do each letter one by one, that would be rediculous! So instead we can initialize (start) the string with:
Code:
new Name[32] = "My Name"
And it produces the same end result.

That is a quick guide for Arrays and Strings, so here is a recap:
  • Create an array with 3 boxes with: new array_name[3]
  • To reference a box, we use the box number - 1 because they are zero-based (starting with 0)
  • In an array of 10 boxes, you cannot reference box[10]
  • You can declare a type on an array just like you would with a variable: new Float:array[3] and new Bool:array[6]
  • Strings are arrays with values representing ASCII characters with '^0' at the end of the string


Functions [top]

Think of them as these machines that you have in your warehouse. You need to activate them, then they do something.

To activate a function in code:
Code:
FunctionName()
Some machines spit something out that weird looking exhaust hole. This value is called the return value.
Some machines return whether or not they worked, while others return other values.
In order to save a return value, one can think of putting a box (variable) under the exhaust hole.
You can do this by:
Code:
variable_name = FunctionName()
  • Note that functions can return different types of variables: Float:AnotherFunction() would need:
    Code:
    new Float:variable
    variable = AnotherFunction()

But don't stop there! Some functions don't just need to be activated, they need parameteres as well.

Think of putting a number into the hole on top or dumping a variable's number into the hole.

Code:
FunctionName( 1 )
and
Code:
new variable = 1
FunctionName( variable )
do the same thing.
  • Note that variable does not lose its value, it still contains the value it went in with

Some functions need multiple parameters:

Code:
FunctionName( parameter, parameter2, parameter3 )
  • Note that parameters can be any type of variable: FunctionName( Float:parameter, Bool:parameter2 )
  • Note that you must supply similar parameter types, if a function is declared with a float, passing a boolean will give you a warning
  • Parameters can be either variables or arrays

And some functions do not return anything ( 0 will be returned by default ):


Hold your horses though, we cannot use a function yet. We still need to create a function.

Here is an example function that returns the first parameter plus five.
Code:
AddFive( number )
{
	new plus_five
	plus_five = number + 5
	return plus_five
}
  • Note that a function's name has the same rules as variable names (try to only use letters, numbers, and underscores)

Now that we have that function in our code, somewhere else in our plugin, we can use it:
Code:
new variable
variable = AddFive( 0 )
//note that variable == 0 + 5 == 5
new second_variable
second_variable = AddFive( variable )
//note second_variable == variable + 5 == 5 + 5 == 10
So a recap of functions:
  • Functions are like machines in your warehouse that do something
  • Some functions need specific parameters in order to be activated
  • Parameter types are dependent on how the function is declared (created)
  • Some functions return a value
  • Return values depend on how the function is declared (created)
  • You need to create them in order to use them somewhere else


Natives [top]

These are very similar to functions because that is basically what they are. Natives are machines that are not in your warehouse.
You can think of them as shortcuts to another warehouse's machine.

They have the same form as a function:
Code:
NativeName(parameter, parameter2)
  • They can have parameters
  • They can return values
  • You do not create them in your code, they exist somewhere else


Forwards [top]

Now these are going to be one of the key things that make your code work.
You can think of them as your ports of the warehouse or communication with the outside world.

In order for your code to do something, you need to be told of an event.
Some simple events or forwards for games would be when someone spawns or dies.
But wait! Your code doesn't let anyone know that it wants to be told about that information!

There are two core forwards that you will need to know about:
  • plugin_init : when your code is first contacted to know what information it will be needing
  • plugin_precache : when your code is contacted to know what it will need for building things (such as models, sprites, and sound)
    • Note that this is usually called before plugin_init

If we want to know when a player spawns, we would then register the forward during plugin_init then the forward will be called everytime it occurs.
There are several different ways to register forwards so I will not go into it here right now.

Looking at this thread we see that we can register the forward with this native:
Code:
RegisterHam(Ham_Spawn, "player", "fwHamPlayerSpawnPost", 1)
Great, now the outside world knows that we want to know when a player is spawned, but where are we going to send that information?

A common parameter to register natives is a public function name. Basically it is the location we are sending it to.
Looking back at the native
Code:
RegisterHam(Ham_Spawn, "player", "fwHamPlayerSpawnPost", 1)
the third argument is the public function name.

So now we have to create that function like so:
Code:
public fwHamPlayerSpawnPost(iPlayer)
{
        if ( is_user_alive( iPlayer ) )
        {
                // player spawned
        }
}
  • Note that this function has public in front so it can interract with the outside world

Another part to most forwards are the returns. Different forwards use different types of returns, but for now we will just talk about:
  • PLUGIN_HANDLED
  • PLUGIN_CONTINUE
  • PLUGIN_HANDLED_MAIN

Returns let the world know what to do once you received the information.
  • Note that if you don't return a value, 0 is returned by default.

PLUGIN_HANDLED says to stop the information from being sent anywhere else. It will stop it from going to other plugins and stop it from going to the server.
PLUGIN_CONTINUE says to do nothing. Everything will continue as normal, other plugins and the server will get the information.
PLUGIN_HANDLED_MAIN says to stop the information from being sent to the server. It will go to other plugins, but not the server.
  • Note that these are just for some forwards. In a FakeMeta forward, it will want FMRES_* returns. In a Ham forward, it will want HAM_* returns.
  • It is important to use the correct returns because you may return something unintended. For example: PLUGIN_HANDLED is the same value as FMRES_IGNORED but if you return PLUGIN_HANDLED in a FakeMeta forward, it will not stop it. Just always try to use the correct returns.
  • Note that some forwards (ex. plugin_init()) ignore return values

Continue to the next section of the guide

Last edited by Emp`; 05-17-2020 at 20:29. 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`