Advanced Topics
This page explains some advanced things you can do with scripts, this page should probably be changed later, depending how useful it is.
Custom element types
One of the most powerful areas of MTA scripting is custom element types. These types can be defined in map files and their functionality implemented by scripts. In this example, we're going to look at a custom flag element, such as you would use in a capture-the-flag game-mode, though this same method could be used for many different things.
First of all you need to decide what format you want the element to be defined in, we're going to use the following:
<flag id="redFlag" name="red team flag" posX="1210.0" posY="-2241.34" posZ="18.4332" />
Now you can define the flag element in the map file.
Next, you can write some code to handle your flag element. First of all, lets add an event that happens when you pick it up, called onFlagPickup. We should do this in an external script file, lets call this capture-the-flag.lua. At the top of the file (outside any functions), define the event:
addEvent ( "onFlagPickup", "player" );
Easy enough! We've added an event that will have a parameter called player. We'll use this to say which player picked up the flag. Next, we have a choice. Either we can add an event handler to the root of the map, and capture every flag pickup event, or we can add it to the individual flag. Its easiest if we use the root of the map, so lets do this here:
mapRoot = getRootElement ( ); addEventHandler ( "onFlagPickup", mapRoot, "flagPickup" );
This says that we want to direct all onFlagPickup events to our function called flagPickup, that we're about to define on the following line:
function flagPickup ( player ) flagName = getElementData ( source, "name" ); playerName = getPlayerName ( player ); serverChat ( playerName .. " picked up the flag " .. flagName ); end
The final part of the puzzle is to make it so that the event is triggered at the correct time. To do this, we'll need to create a timer that will be used to check if a player is trying to pick up the flag. Put the following code below your previous addEventHandler call:
setTimer ( "flagCheckPulse", 1000 );
This will make our soon-to-be-defined function flagCheckPulse be called every second. Now we'll define this function:
function flagCheckPulse ( ) playerCount = getPlayerCount(); flags = getElementsByType ( "flag" ); flagPositionX = getElementData ( flags[1], "posX" ); flagPositionY = getElementData ( flags[1], "posY" ); flagPositionZ = getElementData ( flags[1], "posZ" ); for i=0,playerCount - 1 do player = getElementByIndex ( "player", i ); posX,posY,posZ = getEntityPosition ( player ); distance = getDistanceBetweenPoints3D ( posX, posY, posZ, flagPositionX, flagPostionY, flagPositionZ ); if distance < 1 then triggerEvent ( "onFlagPickup", flags[1], player ); end end end
And thats it!
Note: Although this should work, its not tested. Some things could be improved if better support was provided by us, for example, theres no getPlayerByIndex, no getElementCount(type), an onPlayerPulse event would be useful. This currently only works for one flag, as theres I'm not sure how to find how many flags getElementByType ( "flag" ) returned.
Next: representing the flag in the world - spawning an object at the flags position.