How to create a resource

From GT-MP
Jump to: navigation, search

How to create a resource

Every resource goes into its own folder inside the `resources` folder. Let's make our own resource!

1. Create a new folder called 'mines'.

2. Create a new text file called 'meta.xml' (Make sure you don't have file extensions hidden!) and fill it with the following:

<meta>
    <info name="Mines" description="Test resource to play around with mines" />

    <script src="mines.cs" type="server" lang="csharp" />
</meta>

On the second line we declare an `info` tag, this will contain basic information about our resource such as name, description, author, etc. On the fourth line we add our script file and this is where the magic will happen. The `type` is `server` since it will be running on the server, not the client, and `lang` is C#. You can also write in Visual Basic.NET, but we won't in this guide. (Use "vbasic" instead)

Main article: meta.xml

3. Create a new text file called 'mines.cs' and fill it with the following:

using System;
using GrandTheftMultiplayer.Server;
using GrandTheftMultiplayer.Server.API;
using GrandTheftMultiplayer.Server.Elements;
using GrandTheftMultiplayer.Server.Constant;
using GrandTheftMultiplayer.Server.Managers;
using GrandTheftMultiplayer.Shared;
using GrandTheftMultiplayer.Shared.Math;

public class MinesTest : Script
{
    public MinesTest()
    {
        
    }
}

This is a basic template for our scripts. All scripts must inherit the `Script` class and must reference GrandTheftMultiplayer.Server and GrandTheftMultiplayer.Shared

Let's fill it with some useful stuff. You can interact with GrandTheftMultiplayer using the `API` object. Let's make it write something to the server console when it starts:

We add an event handler called 'myResourceStart', and then attach it to API's `onResourceStart` event inside the constructor.

using System;
using GrandTheftMultiplayer.Server;
using GrandTheftMultiplayer.Server.API;
using GrandTheftMultiplayer.Server.Elements;
using GrandTheftMultiplayer.Server.Constant;
using GrandTheftMultiplayer.Server.Managers;
using GrandTheftMultiplayer.Shared;
using GrandTheftMultiplayer.Shared.Math;


public class MinesTest : Script
{
    public MinesTest()
    {
        API.onResourceStart += myResourceStart;
    }

    public void myResourceStart()
    {
        // This will be ran once all scripts are initialized!
        API.consoleOutput("Starting mines!");
    }
}

If you start the resource, you'll see "Starting mines!" pop up on your server console.

Now, we want it to do something useful. We want the resource to create a mine when the user types the command "/mine". Creating commands with GT-MP is very easy, and it doesnt need any input sanitation, since the server does it for you! All commands use the "[Command]" attribute, and take Client as the first parameter, indicating the player that sent the command.

using System;
using GrandTheftMultiplayer.Server;
using GrandTheftMultiplayer.Server.API;
using GrandTheftMultiplayer.Server.Elements;
using GrandTheftMultiplayer.Server.Constant;
using GrandTheftMultiplayer.Server.Managers;
using GrandTheftMultiplayer.Shared;
using GrandTheftMultiplayer.Shared.Math;

public class MinesTest : Script
{
    public MinesTest()
    {
        API.onResourceStart += myResourceStart;
    }

    public void myResourceStart()
    {
        API.consoleOutput("Starting mines!");
    }

    [Command("mine")]
    public void PlaceMine(Client sender)
    {
        // This is our command!
    }
}

Now let's make the command do something useful.

using System;
using GrandTheftMultiplayer.Server;
using GrandTheftMultiplayer.Server.API;
using GrandTheftMultiplayer.Server.Elements;
using GrandTheftMultiplayer.Server.Constant;
using GrandTheftMultiplayer.Server.Managers;
using GrandTheftMultiplayer.Shared;
using GrandTheftMultiplayer.Shared.Math;

public class MinesTest : Script
{
    public MinesTest()
    {
        API.onResourceStart += myResourceStart;
    }

    public void myResourceStart()
    {
        API.consoleOutput("Starting mines!");
    }

    [Command("mine")]
    public void PlaceMine(Client sender, float MineRange = 10f)
    {
        var pos = API.getEntityPosition(sender);
        var playerDimension = API.getEntityDimension(sender);

        var prop = API.createObject(API.getHashKey("prop_bomb_01"), pos - new Vector3(0, 0, 1f), new Vector3(), playerDimension);     
        var shape = API.createSphereColShape(pos, MineRange);
        shape.dimension = playerDimension;
    }
}

We can see how easily we can add arguments to our commands. The command takes a single optional parameter, the mine detonation range, which is defaulted to 10 meters. The player can input "/mine" to create a mine with a range of 10 meters, or "/mine 5" to create one with a range of 5 meters.

On the first line we get the player's position in the world and store it inside the "pos" variable. Then we do the same to player's dimension (virtual world) and store it in the "playerDimension" variable.

On the next two lines we create an object in the world (a bomb) on player's feet and inside the player's dimension. Next we create a sphere collision shape, which will detect any player/vehicle/object that enters or exits the shape. We also set it so it only detects entities inside player's dimension.


Now let's make it explode when someone enters it's range. As the player is already inside the collision sphere when placing the mine, first we have to arm it when player leaves the range, so it doesn't kill him instantly.

using System;
using GrandTheftMultiplayer.Server;
using GrandTheftMultiplayer.Server.API;
using GrandTheftMultiplayer.Server.Elements;
using GrandTheftMultiplayer.Server.Constant;
using GrandTheftMultiplayer.Server.Managers;
using GrandTheftMultiplayer.Shared;
using GrandTheftMultiplayer.Shared.Math;

public class MinesTest : Script
{
    public MinesTest()
    {
        API.onResourceStart += myResourceStart;
    }

    public void myResourceStart()
    {
        API.consoleOutput("Starting mines!");
    }

    [Command("mine")]
    public void PlaceMine(Client sender, float MineRange = 10f)
    {
        var pos = API.getEntityPosition(sender);
        var playerDimension = API.getEntityDimension(sender);

        var prop = API.createObject(API.getHashKey("prop_bomb_01"), pos - new Vector3(0, 0, 1f), new Vector3(), playerDimension);     
        var shape = API.createSphereColShape(pos, MineRange);
        shape.dimension = playerDimension;
        
        bool mineArmed = false;
        
		// Triggered when a player, vehicle or object enter the mine's range
        shape.onEntityEnterColShape += (s, ent) =>
        {
            if (!mineArmed) return;
			// Otherwise, create an explosion at mine's position, in player's dimension
            API.createOwnedExplosion(sender, ExplosionType.HiOctane, pos, 1f, playerDimension);
            API.deleteEntity(prop);
            API.deleteColShape(shape);
        };

		// Triggered when a player, vehicle or object exit the mine's range
        shape.onEntityExitColShape += (s, ent) =>
        {
            if (ent == sender.handle && !mineArmed)
            { // The player that placed the mine left it's range, let's arm the mine!
                mineArmed = true;
                API.sendNotificationToPlayer(sender, "Mine has been ~r~armed~w~!", true);
            }
        };
    }
}

We use lambda expressions to attach to our collision shape's events inside the command method. The mine wont explode until the player has left the mine range.

Now let's try it in game! Don't forget to add our new resource to your server's settings.xml file:

<resource src="mines" />

Connect to your server using Direct Connect and input "127.0.0.1" as the server, and type "/mine" to spawn a mine at your feet!