Keitboor

Tutorial #1 - User selectable warp points

Recommended Posts

 

 

mta-sa-dm-tutorials.gif

 

Vidéo :

 

 

En construction

 

 

Turning on our script

 

MTA scripting is completely event based. Events are truly dynamic and you can actually implement your own within your scripts, but in this example we'll be using built in events, of which MTA has around 40. Events get "triggered" when all kinds of things happen in the game. We can tie our own functions to any event (by calling a function called addEventHandler). Each event can have any number of event handlers or none!

 

We'll create our first function called Script_onResourceLoad, that we will set up to be called when the server loads the resource that contains the map using the onResourceLoad event. We'll look at how MTA's 'resources' work exactly in a future post.

 

Then we will create a new global key that toggles our script off and on. We call bindKey to assign the I-key to the function "modeIO" we have yet to create.

Of course, we want this key for every player that is currently in our server, so we set up a small for-loop:

 

 

CODE
addEventHandler ( "onResourceLoad", getRootElement(), "Script_onResourceLoad" )

function Script_onResourceLoad ( resource )

 

if ( resource == getThisResource() ) then

-- for each player already in the server

for index, player in getElementsByType ( "player" ) do

 

-- binds the "i"-key to our function "modeIO"

bindKey ( player, "i", "down", "modeIO" )

end

 

end

end

 

Notice that we have now ended the function with the end keyword.

We're forgetting something though: the above function only gets called once (on map load), so any players that join afterwards will need the I-key available as well. We can use the onPlayerJoin event for this, which gets called for every player that joins:

 

 

CODE
addEventHandler ( "onPlayerJoin", getRootElement(), "Script_onPlayerJoin" )

function Script_onPlayerJoin ()

 

-- binds the "i"-key to our function "modeIO"

bindKey ( source, "i", "down", "modeIO" )

end

 

Our global key is needed, so any other binds we will use below will not interfere with any of the original controls and vice versa (such as the mouse buttons for fire and aim) when the script it turned on.

 

Getting our cursor to work

 

Specifying a warp point with keys can be hard to use (and to script). And ideally, we would want to use a mouse cursor. Fortunately, MTA has some nice mouse cursor functions available, including the showCursor which we will use now.

Let's create the "modeIO"-function we mentioned above:

 

 

CODE
function modeIO ( source, key, keyState ) -- function toggles the cursor

if isCursorShowing ( source ) then -- if cursor was already showing:

 

showCursor ( source, false ) -- hide it

else -- if it wasn't showing:

showCursor ( source, true ) -- show it

 

end

end

 

Now since we have three functions and a mouse cursor available, the easiest would be to assign every function to a different mouse button. That's exactly what we're going to do.

 

MTA has an event called onPlayerClick that allows scripters to get the xyz-coordinates at the exact world position of the cursor when the user clicks. This event is, of course, only possible when the cursor is visible.

Let's start our main function Script_onPlayerClick, which we bind to the onPlayerClick-event:

 

 

CODE
addEventHandler ( "onPlayerClick", getRootElement(), "Script_onPlayerClick" )

function Script_onPlayerClick ( key, keyState, element, x, y, z )

 

if keyState == "up" then

return -- ignore if the button was released

end

 

 

Creating our markers

 

Before we do this, you need a little understanding of how MTA's element hierachy works (identical to "entities" in other games).

 

MTA uses elements for everything. Markers, objects, vehicles, players etc - They're all elements. This is easy, because it means you don't have to check the elements's type each time before calling a function. For example: if you want to destroy or set the position of a marker, a vehicle or an object, just call destroyElement or setElementPosition.

 

We only want 2 markers (per player), a "teleport"-marker, and a "destination"-marker. This will keep the script easy, while still providing enough functionality. To allow 2 markers per player, we will store the ID of the marker we create for each player using setElementData.

 

If a user presses the left mouse button, we create a marker called "teleport" which is going to be our portal that will teleport us. If a user presses the right mouse button, we create a "destination"-marker that will be the portal's destination.

Let's implement the left and right mouse button functionality:

 

 

CODE
if key == "left" then -- on a left mousebutton

-- destroy his teleport point, if any

destroyElement ( getElementData ( source, "teleport" ) )

 

-- create a normal cylinder marker

local marker = createMarker ( x, y, z, "cylinder", 2, 0, 255, 0, 50 )

 

-- mark the cylinder as our "teleport" type

setElementData ( marker, "type", "teleport" )

-- link the creator (player) to the marker, and vice versa

 

setElementData ( source, "teleport", marker )

setElementData ( marker, "owner", source )

 

elseif key == "right" then -- on a right mousebutton

-- destroy his destination point, if any

destroyElement ( getElementData ( source, "destination" ) )

 

-- create a glowing corona

local marker = createMarker ( x, y, z+1, "corona", 1, 0, 255, 255, 50 )

 

-- mark the corona as our "destination" type

setElementData ( marker, "type", "destination" )

-- link the creator (player) to the marker, and vice versa

 

setElementData ( source, "destination", marker )

setElementData ( marker, "owner", source )

 

We use setElementData to store some data for the marker. Later on you will see that this is trivial to retrieve the owner and type of the marker.

 

setElementData and it's partner function getElementData both interact with the element data a function has. This data acts as a useful data store that stays attached to an element. You can put values into this store with a key using setElementData and access them later using getElementData.

Besides creating the markers, it is also useful to have a warp function so a player can teleport (and make markers) anywhere he wants.

 

 

CODE
elseif key == "middle" then -- on a middle mousebutton

-- teleport the player to whereever he clicked

setElementPosition ( source, x, y, z+1 )

 

end

 

If you're wondering what the source keyword is: it refers to the element that issued the event, in this case the player. The source keyword is available or all events, though in some cases is irrelevant.

 

Teleporting our player

 

The markers we just created have their own events. To let a script know a marker has been "hit" (touched) by a player, we can use the onMarkerHit event. The source keyword will be set to the marker that issued the event:

 

 

CODE
addEventHandler ( "onMarkerHit", getRootElement(), "Script_onMarkerHit" )

function Script_onMarkerHit ( player )

 

We now use the data we set in the Script_onPlayerClick function above, to see what kind of marker this is. This can be either "teleport" or "destination".

Of course, we only have actually do something if the player hits a "teleport" marker.

 

 

CODE
-- if the marker is a teleport point, proceed

if getElementData ( source, "type" ) == "teleport" then

 

-- get the owner linked to the "teleport" type marker

local owner = getElementData ( source, "owner" )

-- get the destination point linked to the owner

 

local destination = getElementData ( owner, "destination" )

-- if the destination point exists, proceed

if destination then

 

-- get the "destination" marker's position

local x, y, z = getElementPosition ( destination )

-- finally, warp the player there

setElementPosition ( player, x, y, z )

 

end

end

end

 

Cleaning up

 

Finally, we will do some cleaning up for each player. After all, we do not want any markers to stick around after a player has left the server.

Like the onPlayerJoin event, there is also a onPlayerQuit event that gets called whenever a player leaves:

 

 

CODE
addEventHandler ( "onPlayerQuit", getRootElement(), "Script_onPlayerQuit" )

function Script_onPlayerQuit ( reason )

 

--destroy his teleport point, if any

destroyElement ( getElementData ( source, "teleport" ) )

 

-- destroy his destination point, if any

destroyElement ( getElementData ( source, "destination" ) )

 

end

Partager ce message


Lien à poster
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant