Implementing Fix Player Script - KimonoBoy/SHVDNTutorial-NucleiLite GitHub Wiki

Implementing Fix Player Script

Now that our menus are set-up and ready to be used, let's create the Fix Player Script inside our Player Menu - this script does the same as the one we created together earlier, except its now activated by the menu rather than a KeyPress

The Code

  1. Copy and Paste the below code
using System;
using System.Windows.Forms;
using GTA;
using LemonUI;
using LemonUI.Menus;

namespace NucleiLite
{
    public class Main : Script
    {
        ObjectPool menuPool = new ObjectPool();
        NativeMenu mainMenu = new NativeMenu("NucleiLite", "Main Menu");
        NativeMenu playerMenu = new NativeMenu("NucleiLite", "Player Menu");
        NativeMenu vehicleSpawnerMenu = new NativeMenu("NucleiLite", "Vehicle Spawner Menu");
        NativeMenu weaponsMenu = new NativeMenu("NucleiLite", "Weapons Menu");

        public Main()
        {
            mainMenu.AddSubMenu(playerMenu);
            mainMenu.AddSubMenu(vehicleSpawnerMenu);
            mainMenu.AddSubMenu(weaponsMenu);

            menuPool.Add(mainMenu);
            menuPool.Add(playerMenu);
            menuPool.Add(vehicleSpawnerMenu);
            menuPool.Add(weaponsMenu);

            NativeItem itemFixPlayer = new NativeItem("Fix Player", "Restores Player's Health and Armor");
            itemFixPlayer.Activated += (sender, args) =>
            {
                Game.Player.Character.Health = Game.Player.Character.MaxHealth;
                Game.Player.Character.Armor = Game.Player.MaxArmor;
                Notification.Show("Health and Armor Restored!");
            };
            playerMenu.Add(itemFixPlayer);

            KeyDown += OnKeyDown;
            Tick += OnTick;
        }

        private void OnTick(object sender, EventArgs e)
        {
            menuPool.Process();
        }

        private void OnKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F5)
            {
                mainMenu.Visible = !mainMenu.Visible;
            }
        }
    }
}
  1. Build and Reload(), open your Menu F5 and Select Player Menu and then select Fix Player and you should see the following

image

  1. Press the Enter key to activate the script

image

Code Breakdown - Simplified

A few new things are going on here, and they might seem confusing, but let's give it a try

            NativeItem itemFixPlayer = new NativeItem("Fix Player", "Restores Player's Health and Armor");
            itemFixPlayer.Activated += (sender, args) =>
            {
                Game.Player.Character.Health = Game.Player.Character.MaxHealth;
                Game.Player.Character.Armor = Game.Player.MaxArmor;
                Notification.Show("Health and Armor Restored!");
            };
            playerMenu.Add(itemFixPlayer);
NativeItem itemFixPlayer = new NativeItem("Fix Player", "Restores Player's Health and Armor");

The above code is based on the following constructor from the NativeItem class

public NativeItem(string title, string description)

A NativeItem is created this item can be activated to perform a specific task we'll elaborate on that below


itemFixPlayer.Activated += (sender, args) => { }

We call the itemFixPlayer defined just above - the itemFixPlayer has an event called Activated, this event is triggered when the user activates the item (typically by pressing Enter)

The (sender, args) => { } is called an anonymous method where the (sender, args) is the arguments/parameters/inputs passed in and the => { } defines the task to be performed, where everything inside the { } will be performed, in our case it looks like the following

            itemFixPlayer.Activated += (sender, args) =>
            {
                Game.Player.Character.Health = Game.Player.Character.MaxHealth;
                Game.Player.Character.Armor = Game.Player.MaxArmor;
                Notification.Show("Health and Armor Restored!");
            };

So when the itemFixPlayer is activated (Enter pressed while the item is Selected) the code within the { } is performed - Setting Health to MaxHealth and Setting Armor to MaxArmor and finally a message is displayed to the user, informing them about their Health and Armor being restored

The above code would be the equivalent to the following

        private void FixPlayer(object sender, EventArgs e)
        {
            Game.Player.Character.Health = Game.Player.Character.MaxHealth;
            Game.Player.Character.Armor = Game.Player.MaxArmor;
            Notification.Show("Health and Armor Restored!");
        }

Creating the event-method and then assigning the .activated to that method instead, like so

itemFixPlayer.Activated += FixPlayer;

So for now, the anonymous method might seem overwhelming, but you'll see in our Spawn Vehicle Script why this is way easier than defining named Methods


playerMenu.Add(itemFixPlayer);

Finally, we add the new NativeItem to it's associated menu which is the playerMenu in our case

Code Breakdown - Advanced

Let's dive a bit more into what an anonymous method is, and why it's a powerful tool, consider our code

using System;
using System.Windows.Forms;
using GTA;
using LemonUI;
using LemonUI.Menus;

namespace NucleiLite
{
    public class Main : Script
    {
        ObjectPool menuPool = new ObjectPool();
        NativeMenu mainMenu = new NativeMenu("NucleiLite", "Main Menu");
        NativeMenu playerMenu = new NativeMenu("NucleiLite", "Player Menu");
        NativeMenu vehicleSpawnerMenu = new NativeMenu("NucleiLite", "Vehicle Spawner Menu");
        NativeMenu weaponsMenu = new NativeMenu("NucleiLite", "Weapons Menu");

        public Main()
        {
            mainMenu.AddSubMenu(playerMenu);
            mainMenu.AddSubMenu(vehicleSpawnerMenu);
            mainMenu.AddSubMenu(weaponsMenu);

            menuPool.Add(mainMenu);
            menuPool.Add(playerMenu);
            menuPool.Add(vehicleSpawnerMenu);
            menuPool.Add(weaponsMenu);

            NativeItem itemFixPlayer = new NativeItem("Fix Player", "Restores Player's Health and Armor");
            itemFixPlayer.Activated += (sender, args) =>
            {
                Game.Player.Character.Health = Game.Player.Character.MaxHealth;
                Game.Player.Character.Armor = Game.Player.MaxArmor;
                Notification.Show("Health and Armor Restored!");
            };
            playerMenu.Add(itemFixPlayer);

            KeyDown += OnKeyDown;
            Tick += OnTick;
        }

        private void OnTick(object sender, EventArgs e)
        {
            menuPool.Process();
        }

        private void OnKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F5)
            {
                mainMenu.Visible = !mainMenu.Visible;
            }
        }
    }
}

Let's break down the new changes

    NativeItem itemFixPlayer = new NativeItem("Fix Player", "Restores Player's Health and Armor");
    itemFixPlayer.Activated += (sender, args) =>
    {
        Game.Player.Character.Health = Game.Player.Character.MaxHealth;
        Game.Player.Character.Armor = Game.Player.MaxArmor;
        Notification.Show("Health and Armor Restored!");
    };
    playerMenu.Add(itemFixPlayer);

This adds a new item to the playerMenu submenu that will restore the player's health and armor when activated. Here's what it does in more detail

NativeItem itemFixPlayer = new NativeItem("Fix Player", "Restores Player's Health and Armor");

This line creates a new instance of the NativeItem class, which represents an item in a LemonUI Menu. This instance is named itemFixPlayer.

The NativeItem constructor we're using takes two parameters:

public NativeItem(string title, string description)

string title: Representing the text that will be displayed for the *item in the menu. (In our case Fix Player)

string description: Representing an optional description of the item that will be displayed in a tooltip at the bottom of the menu when the item is highlighted. (In our case Restores Player's Health and Armor)

There are overloaded constructors defined in the NativeItem class - an overloaded constructor is another constructor that creates the same item but with different parameters (input). If we go to the Documentation of the NativeItem, you'll notice there are three different constructors

public NativeItem(string title)
            : this(title, string.Empty, string.Empty)
        {
        }

This only takes a Title and leaves the Description and the AltTitle blank

public NativeItem(string title, string description)
            : this(title, description, string.Empty)
        {
        }

This is the one we're currently using. This takes a Title and a Description and leaves the AltTitle blank

        public NativeItem(string title, string description, string altTitle)
        {
            //IL_0001: Unknown result type (might be due to invalid IL or missing references)
            //IL_0006: Unknown result type (might be due to invalid IL or missing references)
            //IL_000c: Unknown result type (might be due to invalid IL or missing references)
            //IL_0011: Unknown result type (might be due to invalid IL or missing references)
            //IL_0029: Unknown result type (might be due to invalid IL or missing references)
            //IL_002e: Unknown result type (might be due to invalid IL or missing references)
            //IL_0044: Unknown result type (might be due to invalid IL or missing references)
            //IL_0061: Unknown result type (might be due to invalid IL or missing references)
            this.title = new ScaledText(PointF.Empty, title, 0.345f);
            Description = description;
            this.altTitle = new ScaledText(PointF.Empty, altTitle, 0.345f);
        }

This takes a Title, a Description and an AltTitle (Title to the right of the Menu)

You can learn more about Overloaded Methods and Constructors at Constructor Overloading - pretty much the same concept goes for Methods


itemFixPlayer.Activated += (sender, args) =>
{
    Game.Player.Character.Health = Game.Player.Character.MaxHealth;
    Game.Player.Character.Armor = Game.Player.MaxArmor;
    Notification.Show("Health and Armor Restored!");
};

After creating the itemFixPlayer instance, we use that variable and add an event handler for the item's Activated event using the += operator. The Activated event is raised when the user selects the item and hits Enter in the menu.

The event handler is defined using a lambda expression, which is a concise way of defining an anonymous method. The lambda expression takes two parameters (inputs), sender and args, the sender represents the object that raised the event and the args parameter represents any additional information or data related to the event that is being raised.

You can learn more about Lambda Expressions at Lambda Expressions and more about Anonymous Methods at Anonymous Methods

Inside the code-block { } the task to restore the Player's Health and Armor is defined

{
    Game.Player.Character.Health = Game.Player.Character.MaxHealth;
    Game.Player.Character.Armor = Game.Player.MaxArmor;
    Notification.Show("Health and Armor Restored!");
};

playerMenu.Add(itemFixPlayer);

Finally, we add the new NativeItem to it's associated menu which is the playerMenu in our case

Conclusion

We've implemented the Fix Player Script we've created earlier into our Menu - we can now Restore Health and Armor simply by selecting the item from our Menu

Previous - Introduction to LemonUI
Next - Implementing Invincible Script