13.06.2016, 23:20
(
Last edited by IllidanS4; 16/06/2016 at 01:39 PM.
)
i_pvars
Download
IntroductionDownload
In my long-term gamemode project, I ran into the issue of maintaining lots and lots of PVars. It was simple – I had troubles remembering which PVar does what, didn't have any list of them, and often put typos or differences hard to notice in them, like "color" vs. "colour". The first of the features of this include is the ability to quicky "declare" a PVar and then use it.
It's really straightforward:
Code:
PVAR:SKIN = "plrskin"; //int
Code:
SetPVarInt(playerid, PVAR_SKIN, GetPlayerSkin(playerid));
- It's short – this declaration is shorter than every else, thus saving script size.
- It's easy to notice – you can even highlight the keyword PVAR if you use a custom script editor. It distinguishes the variable from all others – its internal value is not important, rather that it's a PVar.
- Its value is stored only once – reusing defines copies their value each time you use them. If you use them many times, you'll have your AMX littered with duplicates. The advantage of being a variable is that the value is stored only once.
- It's stock – you won't get any warning if you don't use the PVar, and it's internal value will be lost during compilation in that case, saving AMX size.
- It's const – it will prevent you from accidentally changing the PVar's internal name, which's not what you usually would want.
There was only one minor issue during the development of this – SA-MP functions like SetPVarInt etc. have "varname[]" as their parameter and not "const varname[]" as they should (because they're not changing the value). I had to use some #emit tricks to circumvent this limitation, and as a bonus, all PVar functions have "const varname[]" now.
This was the first feature of this plugin, and now comes the most important one:
PVar arrays!
It's probable that you already have a per-player array in your script. Maybe the list of all weapons a player has, for anti-cheat purposes, or something else. However, the size of such array grows rapidly with increasing its size. A complete killer is the following one:
Code:
new plrPickupCommands[MAX_PLAYERS][MAX_PICKUPS][128];
That's why it's advisable to use a PVar for a large array, especially when you don't intend to fill all cells in the array. I've already seen another PVar array system, and it used format to put the index inside the PVar's name. This script doesn't do that. Favouring speed, this script instead modifies a preallocated space inside the PVar's name and puts the index there, converting it to a 4-byte code, and then using the PVar name as usual. Because PVar names are case-insensitive, one character in the code has only 229 possible values (skipping the range of lowercase letters). This limits the total possible number of indices a bit, but it's still higher than the maximum possible value of an integer.
Enough talk, how to use it?
Declaring a PVar array is as simple as declaring a normal PVar:
Code:
PVARR:PICKUP_COMMANDS = "onpickup";
There's a special syntax for accessing a PVar Array:
Code:
SetPVarString(playerid, PVAR_ARRAY<PICKUP_COMMANDS>[pickupid], cmd);
There are also some additional functions in the include:
Code:
IsPVarSet(playerid, const varname[]);
Code:
SetPVarBool(playerid, const varname[], bool:bool_value)
Code:
GetPVarBool(playerid, const varname[]);
Code:
DecodePVarArrayName(varname[], &trim=0);
Code:
ReformatPVarArrayName(varname[], size = sizeof(varname));
I use this system intensively in my script, so it should be bug-free mostly. Still, if you find an issue, I'll gladly fix it.
That's all. Have fun with PVars!