-
Notifications
You must be signed in to change notification settings - Fork 9
INTERACTION.md
amx allows developers to enrich their gamemodes and other scripts with Lua code, which is easier and more efficient to write than Pawn. To make this possible, a new Pawn function, lua was added to call Lua functions, and a Lua function called pawn correspondingly calls public Pawn functions.
A resource that uses the interaction functions will contain both one or more .amx files (<amx/>
in meta.xml) and serverside MTA scripts (<script/>
). Both Pawn and Lua scripts can only call other-language scripts that are in the same resource.
Before you can call a function with lua or pawn you need to define its prototype, which consists of the types of its arguments and return value. Each type corresponds to a single letter:
Letter | Type | Letter | Type | Letter | Type |
---|---|---|---|---|---|
b | boolean |
p | player |
m | menu |
i | integer |
v | vehicle |
g | gang zone |
f | floating point |
o | object |
a | 3D text label |
s | string |
u | pickup |
k | native marker |
c | color |
y | actor |
z | bot |
t | team |
x | textdraw |
Pawn functions are registered with amxRegisterPawnPrototypes:
native amxRegisterPawnPrototypes(const prototype[][]);
Lua functions are registered with amxRegisterLuaPrototypes:
bool amxRegisterLuaPrototypes(table prototypes)
Both functions associate a number of function names with their argument types and (optionally) return type.
To specify a return type, prepend the function name with the type letter followed by a colon (:), for example: f:testfn
. If you do not specify a return type (i.e. only specify the name, testfn
), "i" will be assumed.
See the syntax sections of the two registration functions for the precise syntax to use.
Use lua to call a Lua function from Pawn:
native lua(const fnName[], {Float,_}:...);
Use pawn to call a Pawn function from Lua:
variant pawn(string fnName, ...)
The functions have the same syntax: a string containing the name of the function, followed by the arguments to the function. amx takes care of any necessary argument and return value conversions: for example an .amx vehicle ID passed to lua will arrive in the Lua function as an MTA vehicle element, and vice versa (provided the correct prototype was registered for the Lua function).
It is possible to pass arguments by-reference from Pawn to Lua - however this is not possible in the opposite direction.
To make an argument be passed by reference, modifications in both the Lua function's prototype and body are necessary. In the prototype, prepend the type letter with a &
.
In the function's code, write _[argname]
instead of argname
for reading and writing the argument (argname
holds the memory address in the .amx of the argument).
Some limitations apply to cross-language calling.
- Only scalar values (numbers, players, vehicles...) and strings can be passed as arguments; Pawn arrays and Lua tables are not supported.
- Functions can only return scalar values (no strings or other arrays).
- As stated in the previous section, by-reference arguments can only be passed from Pawn to Lua, not from Lua to Pawn.
This example code demonstrates registering prototypes and calling other-language functions, with arguments passed by value and by reference.
#include <a_samp>
#include <a_amx>
main()
{
new prototypes[][] =
{
"p:testfn", { "p", "f", "s" },
""
};
amxRegisterPawnPrototypes(prototypes);
}
public testfn(playerid, Float:f, str[])
{
printf("pawn> testfn: %d %.1f %s", playerid, f, str);
return playerid;
}
public OnGameModeInit()
{
new
vehicleid = CreateVehicle(415, 0.0, 0.0, 3.0, -90.0, 0, 1, 5000),
vehicletype;
// vehicletype is passed by reference
new success = lua("getVehicleType", vehicleid, vehicletype, "Test text from Pawn");
if (success) printf("pawn> Vehicle type: %d", vehicletype);
SetGameModeText("Blank Script");
AddPlayerClass(0, 1958.3783, 1343.1572, 15.3746, 269.1425, 0, 0, 0, 0, 0, 0);
return 1;
}
public OnPlayerRequestClass(playerid, classid)
{
SetPlayerPos(playerid, 1958.3783, 1343.1572, 15.3746);
SetPlayerCameraPos(playerid, 1958.3783, 1343.1572, 15.3746);
SetPlayerCameraLookAt(playerid, 1958.3783, 1343.1572, 15.3746);
return 1;
}
function getVehicleType(vehicle, pVehicleType, str)
print('lua> ' .. str)
print('lua> ' .. _[pVehicleType])
local model = getElementModel(vehicle)
if model then
_[pVehicleType] = model
return true
else
return false
end
end
addEventHandler('onAMXStart', root,
function()
-- Note that we are calling pawn() from the onAMXStart event instead of in the main script body
-- Calling it from the main body would fail as the Pawn functions haven't yet been registered at that point
local player = pawn('testfn', getRandomPlayer(), 0.8, 'Test string from Lua')
if player then
print('lua> ' .. getClientName(player))
else
print('lua> No random player')
end
end
)
amxRegisterLuaPrototypes({
['b:getVehicleType'] = { 'v', '&i', 's' }
})
lua> Test text from Pawn
lua> 0
pawn> Vehicle type: 415
pawn> testfn: 1 0.8 Test string from Lua
lua> arc_