the sourcepawn transitional syntax wiki [
https://wiki.alliedmods.net/SourcePa...itional_Syntax ] horribly explains methodmaps.
This tutorial will aim to give a better understanding, especially to beginners...
In a nutshell, Methodmaps are basically class-like functions for enums
According to Bailopan, "Methodmaps are syntactic transformations only. That is, x.y() on methodmap Z is transformed into a function call that looks like Z_y(x)." -
https://forums.alliedmods.net/showpo...&postcount=365
As you can see, methodmaps can help make life a bit easier. Let's begin!
It should be known that
methodmaps do not need to be attached to a enum to work. You can have a solo methodmap work by itself, but if you want custom types/tags, then you will be needing an enum.
Because methodmaps are similar to classes, the first part of a methodmap you
need is a constructor!
Through messing around with the compiler and such, I've found that Constructors must always have the same name as the Methodmap they're operating from as well as having no identified return type! Constructors can also just do nothing lol! As long as you have a constructor at least.
PHP Code:
methodmap MapMethod
{
public MapMethod( int index ) //this is the constructor!
{
return view_as<MapMethod>( index ); /*you must return the data as the methodmap. The data also cannot be an array
or the enum tag you're making the methodmap for or make the constructor do absolutely nothing.*/
}
}
Methodmaps can also have regular, normal functions be used inside them, like so!
PHP Code:
methodmap EntityWithHealth
{
public void SetHealth(int value) //normal function
{
SetEntProp(this, Prop_Send, "m_iHealth", value);
}
}
Adding properties/accessors to your methodmap can make it that much simpler to accessing data. Properties have getters and setters so you can easily set their data and utilize it as soon as possible!
properties do not have to have both getters and setters but it should definitely have getters.
PHP Code:
int iMoney = 0;
/*
remember that methodmaps are not classes/structs so you need to create globals.
The purpose of the methodmap is to be the only modifier of these global variables
so that the code is more structured and controlled.
*/
methodmap Bank
{
property int Money //property!
{
public get() { return iMoney; }
public set( int value ) { iMoney = value; } //property is an int, so the data must be set with an int!
}
}
Then there's inheritance! You can make other methodmaps get the same data and handling as your initial methodmap!
Here's a good example. The parent methodmap has the money property while the child mtm has toys! Since the child mtm inherits from the parent mtm, that means you can use the "Money" accessor from the child mtm!
PHP Code:
int iMoney;
int iToys;
methodmap Parent
{
property int Money //has money!
{
public get() { return iMoney; }
public set( int value ) { iMoney = value; }
}
}
methodmap Child < Parent
{
property int Toys //has toys AND money :D
{
public get() { return iToys; }
public set( int value ) { iToys = value; }
}
}
There's also stuff about inline methods but I've never used them but I just wanted to cover the beginner stuff.
The most important concept of methodmaps is the "this" name. The "this" name basically refers to whatever instance of the methodmap uses the available functions inside it. look at the final code below to see what I mean.
Here's the final product of what most realistic (custom) methodmaps would look like and how they are used!
PHP Code:
int iHealth[MAXPLAYERS+1];
int iAmmo[MAXPLAYERS+1];
float flSpeed[MAXPLAYERS+1];
methodmap Playur
{
public Playur(int playerindex) //constructor
{
return view_as<Playur>(playerindex); //make sure you do validity check on players
}
property int index
{
public get() { return view_as<int>(this); }
}
property int Health
{
public get() { return iHealth[this.index]; }
public set( int value ) { iHealth[this.index] = value; }
}
property int Ammo
{
public get() { return iAmmo[this.index]; }
public set( int value ) { iAmmo[this.index] = value; }
}
property float Speed
{
public get() { return flSpeed[this.index]; }
public set( float value ) { flSpeed[this.index] = value; }
}
public void GiveAmmo(int amount)
{
this.Ammo += amount;
}
public void RemoveAmmo(int amount)
{
this.Ammo -= amount;
}
}
public void OnClientPutInServer(int client)
{
Playur player = Playur(client);
if (player.Health < 1) player.Health = 100;
if (player.Ammo < 1) player.Ammo = 50;
if (player.Speed < 1.0) player.Speed = 300.0;
}
EDIT #1
another thing to introduce to the Methodmaps is the concept of "objectifying" them
Here's an example!
PHP Code:
methodmap MapMethod __nullable__
{
........
}
the methodmap is now nullable! Nullable methodmaps actually create objects compared to normal, non-nullable methodmaps!
with a nullable methodmap, you have to use "new" with its constructor!
like so!
PHP Code:
methodmap MapMethod __nullable__
{
public MapMethod() //constructor
{
//code here
}
}
MapMethod Data = new MapMethod();
Here's a better full example from one of my own plugins, the Arm Chair General plugin that allows spectators to be more interactive with red or blue team....
PHP Code:
enum {
IsGen = 0,
LeadingTeam
};
#define int(%1) view_as<int>(%1)
int General[MAX][2];
methodmap Commander
{
public Commander(int userid) //constructor: It's less of a headache to use userids
{
if ( IsValidClient( userid ) ) {
return view_as< Commander >( GetClientUserId( userid ) );
}
return view_as< Commander >(-1);
}
property int index
{
public get() { return GetClientOfUserId( int(this) ); }
}
property int bIsGeneral
{
public get() { return General[ this.index ][ IsGen ]; }
public set( int val ) { General[ this.index ][ IsGen ] = val; }
}
property int iLeadingTeam
{
public get() { return General[ this.index ][ LeadingTeam ]; }
public set( int val ) { General[ this.index ][ LeadingTeam ] = val; }
}
};
Creating a methodmap out of natives!
.inc file
PHP Code:
methodmap NativeMap
{
public native NativeMap();
property int MyIntProperty {
public native get();
public native set(const int val);
}
public native void MyMethodFunc();
}
implementation in the plugin that's exporting the native-based methodmap
PHP Code:
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
CreateNative("NativeMap.NativeMap", Native_NativeMapInstance);
CreateNative("NativeMap.MyIntProperty.get", Native_GetMyIntProperty);
CreateNative("NativeMap.MyIntProperty.set", Native_SetMyIntProperty);
CreateNative("NativeMap.MyMethodFunc", Native_MyMethodFunc);
return APLRes_Success;
}
public int Native_NativeMapInstance(Handle plugin, int numParams)
{
return GetNativeCell(1);
}
public int Native_GetMyIntProperty(Handle plugin, int numParams)
{
return Health[GetNativeCell(1)]; /* GetNativeCell(1) IS ALWAYS THE "this" parameter */
}
public int Native_SetMyIntProperty(Handle plugin, int numParams)
{
Health[GetNativeCell(1)] = GetNativeCell(2);
}
public int Native_MyMethodFunc(Handle plugin, int numParams)
{
CallBackFunc(GetNativeCell(1), GetNativeCell(2));
// Remember that GetNativeCell(1) is always the "this" parameter aka the first argument
}
__________________