tModLoader [Tutorial] Creating Simple UI: Custom Resource Bars

Subaro

Terrarian
Welcome,

in this tutorial, we want to create a custom health bar and custom mana bar. I will start with an empty project.

Project ID: CustomBars
Project Name: Custom Resource Bars
Seperator.png
1. Remove old health bar
Code:
public override void ModifyInterfaceLayers(List<MethodSequenceListItem> layers)
        {
            for (int i = 0; i < layers.Count; i++)
            {
                //Remove Resource bars
                if (layers[i].Name.Contains("Resource Bars"))
                {
                    layers.RemoveAt(i);
                }
            }
        }
Seperator.png
2. Create empty interface and register it
At first, we declare our new interface in the Mod class:
Code:
 public UserInterface customResources;

Now we need to create the interface on the Load() method:
Code:
public override void Load()
{
    if (!Main.dedServ)
    {
        customRessources = new UserInterface();
    }
}
Back to our ModifyInterfaceLayers(...) methode we need to register our interface that we created. We do that directly behind layers.RemoveAt(i):
Code:
//Add you own layer
layers.Insert(i, new MethodSequenceListItem(
"CustomBars: Custom Resource Bar",
delegate
{
    //At this point, your UI that we will create later will be updated. Leave it blank at the moment
    return true;
},
null)
Seperator.png
3. Create and register our UIState
Now we are ready to create our UIState. The UIState will be assigned to our interface. That will activate and recalculate the UI(and all the children) at the start.
So create a new folder called UI. Create a class that inheritance UIState and name it HealthManaBars. That class will provide only the health and mana bars. We removed the Resource Bars interface in step 1. The Resource Bars exist of the health bar, mana bar, and the buff bar. So if you finish the Tutorial you got your custom health/mana bars but no buff bar. Later I will add a custom buff bar to the Tutorial.
Now create the class HealthManaBars and implement the OnInitialize() method:
Code:
namespace CustomBars.UI
{
    internal class HealthManaBars: UIState
    {
        public override void OnInitialize()
        {
            //empty
        }
    }
}
Now we want to create a visible variable to easily control the current visibility of the UI:
Code:
public static bool visible = false;
We will add an empty default Terraria panel and position it at the top right of the game. We will go over the other UI elements later. Add to the OnInitialize():
Code:
UIPanel parent = new UIPanel();
parent.Height.Set(100f, 0f);
parent.Width.Set(300, 0f);
parent.Left.Set(Main.screenWidth - parent.Width.Pixels, 0f);
parent.Top.Set(0f, 0f);
parent.BackgroundColor = new Color(255, 255, 255, 255);

base.Append(parent);
Back to the Mod class create a HealthManaBars instance and register the UIState to the UserInterface:
Code:
public HealthManaBars healthManaBars;
.
.
.
public override void Load()
        {
            if (!Main.dedServ)
            {
                customRessources = new UserInterface();
                healthManaBars = new HealthManaBars();
                HealthManaBars.visible = true;
                customRessources.SetState(healthManaBars);

            }
        }
To See anything we need to update our UI. To do so go to the ModifyInterfaceLayers() and insert into the MethodSequenceListItem delegate:
Code:
if (HealthManaBars.visible)
{
    //Update CustomBars
    customResources.Update(Main._drawInterfaceGameTime);
    healthManaBars.Draw(Main.spriteBatch);
}
You can now run build your mod and you will see the first result:
whitepanel.PNG

Seperator.png
4. Create our own UIElement
Terraria has already the most UIElements you need to build your UI. The best is all of them are in terraria style. You can find all elements in your Terraria Reference under Terraria.GameContent.UI.Elements:
elements.PNG

We used the UIPanel earlier, but now we want to create our own UIElement. A flat panel without any borders.
So create a new class called UIFlatPanel that inheritance from UIElement. We need a color for the background and a texture. The texture is needed because everything will be drawn using a spriteBatch which require a texture.
Here the texture I use:
Blank.png

Download and put into your project (mine is at {ModID}\Textures\UI). Now we will create our UIElement class:
Code:
namespace CustomBars.UI
{
    class UIFlatPanel : UIElement
    {
        public Color backgroundColor = Color.Gray;
        private static Texture2D _backgroundTexture;

        public UIFlatPanel ()
        {
            if (_backgroundTexture == null)
                _backgroundTexture = ModLoader.GetTexture("CustomBars/Textures/UI/Blank");
        }
    }
}
Now we need to tell the UIElement how it should be drawn. We override the methode DrawSelf(..):
Code:
protected override void DrawSelf(SpriteBatch spriteBatch)
        {
            CalculatedStyle dimensions = GetDimensions();
            Point point1 = new Point((int)dimensions.X, (int)dimensions.Y);
            int width = (int)Math.Ceiling(dimensions.Width);
            int height = (int)Math.Ceiling(dimensions.Height);
            spriteBatch.Draw(_backgroundTexture, new Rectangle(point1.X, point1.Y, width, height), backgroundColor);
        }
We get the Dimension which is holding the information of the size and position of the element. We create the top left point called point1. Now we draw the _backgroundTexture as a Rectangle with the given size and color.
Now we got our own UIElement and are ready to test it out. Go to your HealthManaBars class and change the UIPanel to our new UIFlatPanel. Also, add another red one and blue one:
Code:
public override void OnInitialize()
{
    UIFlatPanel parent = new UIFlatPanel();
    parent.Height.Set(65f, 0f);
    parent.Width.Set(300f, 0f);
    parent.Left.Set(Main.screenWidth - parent.Width.Pixels, 0f);
    parent.Top.Set(0f, 0f);
    parent.backgroundColor = new Color(255, 255, 255, 255);

    UIFlatPanel hp = new UIFlatPanel();
    hp.Height.Set(25f, 0f);
    hp.Width.Set(280f, 0f);
    hp.Left.Set(10f, 0f);
    hp.Top.Set(5f, 0f);
    hp.backgroundColor = Color.Red;
    parent.Append(hp);

    UIFlatPanel mana = new UIFlatPanel();
    mana.Height.Set(25f, 0f);
    mana.Width.Set(280f, 0f);
    mana.Left.Set(10f, 0f);
    mana.Top.Set(35f, 0f);
    mana.backgroundColor = Color.Blue;
    parent.Append(mana);

    base.Append(parent);
}
It should look like this:
flatpanelblueandred.PNG


Seperator.png

5. Implement the Life/Mana Bar
So now we want to show the user the amount of life and mana as text. Also, implement its progress animation. To do so we create a new UIElement that contains two flat panels. One is the background and the other one is the current life/mana. I named the class ResourceBar. I also created an inner enum to set the current stat to display:
Code:
namespace CustomBars.UI
{
    internal enum ResourceBarMode
    {
        HP,
        MANA
    }
    class ResourceBar : UIElement
    {
        private ResourceBarMode stat;
        private float width;
        private float height;

        public ResourceBar(ResourceBarMode stat, int height, int width)
        {
            this.stat = stat;
            this.width = width;
            this.height = height;
        }

    }
}
Now create the OnInitialize() and add a gray FlatPanel as background and a colored as the current value and a UIText element. Determine the color of the current panel depending on the ResourceBarMode:
Code:
private UIFlatPanel currentBar;
private UIText text;
.
.
.
public override void OnInitialize()
{
    Height.Set(height, 0f); //Set Height of element
    Width.Set(width, 0f);   //Set Width of element

    UIFlatPanel barBackground = new UIFlatPanel(); //Create gray background
    barBackground.Left.Set(0f, 0f);
    barBackground.Top.Set(0f, 0f);
    barBackground.backgroundColor = Color.Gray;
    barBackground.Width.Set(width, 0f);
    barBackground.Height.Set(height, 0f);

    currentBar = new UIFlatPanel(); //Create current value panel 
    currentBar.SetPadding(0);
    currentBar.Left.Set(0f, 0f);
    currentBar.Top.Set(0f, 0f);
    currentBar.Width.Set(width, 0f);
    currentBar.Height.Set(height, 0f);

    //assign color to panel depending on stat
    switch (stat)
    {
        case ResourceBarMode.HP:
            currentBar.backgroundColor = new Color(164, 55, 65); //red
            break;

        case ResourceBarMode.MANA:
            currentBar.backgroundColor = new Color(46, 67, 114); //blue
            break;
        default:
            break;
    }

    text = new UIText("0|0"); //text to show current hp or mana
    text.Width.Set(width, 0f);
    text.Height.Set(height, 0f);
    text.Top.Set(height / 2 - text.MinHeight.Pixels / 2, 0f); //center the UIText

    barBackground.Append(currentBar);
    barBackground.Append(text);
    base.Append(barBackground);
}
Next we will implement the progress of the bar by overriding the draw method and determine how many percent of the current bar should be displayed:
Code:
public override void Draw(SpriteBatch spriteBatch)
{
    Player player = Main.player[Main.myPlayer];
    float quotient = 1f;
    //Calculate quotient
    switch (stat)
    {
        case ResourceBarMode.HP:
            quotient = (float)player.statLife / (float)player.statLifeMax;
            break;

        case ResourceBarMode.MANA:
            quotient = (float)player.statMana / (float)player.statManaMax;
            break;

        default:
            break;
    }
    currentBar.Width.Set(quotient * width, 0f);
    Recalculate(); // recalculate the position and size

    base.Draw(spriteBatch);
}
Now we need to override the Update(..) method to update the text:
Code:
public override void Update(GameTime gameTime)
{
    Player player = Main.player[Main.myPlayer]; //Get Player
    switch (stat)
    {
        case ResourceBarMode.HP:
            text.SetText("" + player.statLife + " | " + player.statLifeMax); //Set Life
            break;

        case ResourceBarMode.MANA:
            text.SetText("" + player.statMana + " | " + player.statManaMax); //Set Mana
            break;

        default:
            break;
    }
    base.Update(gameTime);
}
The ResourceBars are ready now so go back to the HealthManaBars class and change the hp and mana UIFlatPanels to ResourceBars. Also, remove the old white panel:
Code:
public override void OnInitialize()
{
    ResourceBar hp = new ResourceBar(ResourceBarMode.HP, 280, 25);
    hp.Left.Set(Main.screenWidth - hp.Width.Pixels - 10, 0f);
    hp.Top.Set(5f, 0f);
    base.Append(hp);

    ResourceBar mana = new ResourceBar(ResourceBarMode.MANA, 280, 25);
    mana.Left.Set(Main.screenWidth - hp.Width.Pixels - 10, 0f);
    mana.Top.Set(35f, 0f);
    base.Append(mana);
}
To be able to stay in the top right coner i override the DrawSelf method of HealthManaBars:
Code:
protected override void DrawSelf(SpriteBatch spriteBatch)
{
    panel.Left.Set(Main.screenWidth - panel.Width.Pixels, 0f);
    panel.Top.Set(0f, 0f);
    Recalculate();
}
Now it should stay at the top right even after resize.
Now we are ready and got two new bars. In the end, it should look like this:
first.PNG
second.PNG




Thank you for your patience and after you implemented the health bar you will see it´s very easy to create or replace a UI. In some days we will create a custom buff bar.

Seperator.png

Credits
Myself :)
the tModLoader Team & Co- creating tModloader, ExampleMod
Re-Logic - Creating that amazing game
 
I have a small issue, in removing the "Resource Bars" layer, you also remove the buff display. Is there any way to remove JUST the life/mana bar, or re-program in the buffs? I'm not to familiar with UI code.
 
If you have the official source on your hands you can search the code where they draw the buffs. You can copy change the code out of the source and put it into your mod. Then the buffs will be displayed as ever and you can add your own custom health/mana bars or any other UI Element.
 
Trying to create clickable UI and get two problems.
At first, UI don't response on any clicks/hovers until some random time passed or I Alt+Tab Terraia with UI opend. What can be a problem? I didn't create "parent" UIPanel and using "Vanilla: Inventory" layer.
Second, when clicks actually work, input son't blocked by UI, so any item in hand used simultaneously with OnClick effects. Didn't find any kind of "input blocks"
Also checked ExampleMod, but didn't find any missed calls or something...

class GemSocketsUI : UIState
{
public static bool visible;
public PathOfTerraria mod;

private UIText head;
private UIText info;
private UIGemSlot[] gemSlots = new UIGemSlot[6];

public GemSocketsUI(PathOfTerraria mod)
{
this.mod = mod;
visible = true;
}

public override void OnInitialize()
{
head = new UIText("Skill Gems");
head.Left.Set(50f, 0f);
head.Top.Set(273f, 0f);
Append(head);

for (int i = 0; i < 6; i++)
{
gemSlots[ i ] = new UIGemSlot(mod, i);
gemSlots[ i ].Left.Set(145f + (47f * i), 0f);
gemSlots[ i ].Top.Set(258f, 0f);
gemSlots[ i ].Width.Set(45f, 0f);
gemSlots[ i ].Height.Set(45f, 0f);
Append(gemSlots[ i ]);
}
}

public override void Draw(SpriteBatch spriteBatch)
{
head.TextColor = Colors.AlphaDarken(Color.Wheat);

base.Draw(spriteBatch);
}

private void slotClick(UIMouseEvent evt, UIElement listener)
{
Main.NewText("ID: " + listener.Id);
}


}

class UIGemSlot : UIPanel
{
private int slotNumber;
private UIImage image;
private PathOfTerraria mod;

public UIGemSlot(PathOfTerraria _mod, int slotNum)
{
image = new UIImage(Main.itemTexture[0]);
mod = _mod;
slotNumber = slotNum;
}

public override void OnInitialize()
{
SetPadding(0f);
BackgroundColor = Color.Wheat.MultiplyRGBA(new Color(0.6f, 0.6f, 0.6f, 0.8f));
BorderColor = new Color(20, 20, 20, 180);

image.HAlign = UIAlign.Center;
image.VAlign = UIAlign.Center;
image.ImageScale = 0.75f;
Append(image);
}

public override void MouseDown(UIMouseEvent evt)
{
SetImage(Main.itemTexture[Main.mouseItem.type]);
}

private PoTPlayer Player()
{
return Main.LocalPlayer.GetModPlayer<PoTPlayer>(mod);
}

public void SetSlot(int slotNum)
{
slotNumber = slotNum;
}

public int GetSlot()
{
return slotNumber;
}

public void SetImage(Texture2D img)
{
image.SetImage(img);
Recalculate();
}

}

public override void ModifyInterfaceLayers(List<GameInterfaceLayer> layers)
{
int interfaceLayer = layers.FindIndex(layer => layer.Name.Equals("Vanilla: Inventory"));
if (interfaceLayer > -1)
{
layers.Insert(interfaceLayer, new LegacyGameInterfaceLayer("PathOfTerraria: Gem Sockets",
delegate
{
if (GemSocketsUI.visible && Main.playerInventory)
{
PoTUI.Update(Main._drawInterfaceGameTime);
gemSocketsUI.Draw(Main.spriteBatch);
}
return true;
},
InterfaceScaleType.UI));
}
}
 
I also have another issue, I can draw the buffs, but the mousetext gets bugged. The default class for that stuff requires an instance of terraria or something, the error says.
 
I also have another issue, I can draw the buffs, but the mousetext gets bugged. The default class for that stuff requires an instance of terraria or something, the error says.

so there is a special class to show text when mouse is over something? i guess i somehow missed it and just created UIText :D
 
The guide is fine, but you forgot about one thing on the guide.
About adding on the beggining of the code:
Code:
using Terraria.UI;
using Terraria.GameContent.UI;
using Terraria.GameContent;
using Terraria.GameContent.UI.Elements;
using Terraria.GameContent.UI.States;
Without those, one will get stuck at step 3.
 
  • Like
Reactions: W1K
I want to make a mana like system, how would I go about using UI coding to do so? Without removing health and mana UI.
 
I am trying to follow this tutorial.
After fixing some of the errors my TModloader was returning I am stuck with a CS0246 at the end of step 3:
the type or namespace "MethodSequenceListItem" could not be found

Usually I managed to fix this error while coding by either referencing libraries or other subfolders - but I can't seem to find any info on the MethodSequenceListItem - topic

Any clue?
 
If you have the official source on your hands you can search the code where they draw the buffs. You can copy change the code out of the source and put it into your mod. Then the buffs will be displayed as ever and you can add your own custom health/mana bars or any other UI Element.
Welcome,

in this tutorial, we want to create a custom health bar and custom mana bar. I will start with an empty project.

Project ID: CustomBars
Project Name: Custom Resource Bars
1. Remove old health bar
Code:
public override void ModifyInterfaceLayers(List<MethodSequenceListItem> layers)
        {
            for (int i = 0; i < layers.Count; i++)
            {
                //Remove Resource bars
                if (layers[i].Name.Contains("Resource Bars"))
                {
                    layers.RemoveAt(i);
                }
            }
        }
2. Create empty interface and register it
At first, we declare our new interface in the Mod class:
Code:
 public UserInterface customResources;

Now we need to create the interface on the Load() method:
Code:
public override void Load()
{
    if (!Main.dedServ)
    {
        customRessources = new UserInterface();
    }
}
Back to our ModifyInterfaceLayers(...) methode we need to register our interface that we created. We do that directly behind layers.RemoveAt(i):
Code:
//Add you own layer
layers.Insert(i, new MethodSequenceListItem(
"CustomBars: Custom Resource Bar",
delegate
{
    //At this point, your UI that we will create later will be updated. Leave it blank at the moment
    return true;
},
null)
3. Create and register our UIState
Now we are ready to create our UIState. The UIState will be assigned to our interface. That will activate and recalculate the UI(and all the children) at the start.
So create a new folder called UI. Create a class that inheritance UIState and name it HealthManaBars. That class will provide only the health and mana bars. We removed the Resource Bars interface in step 1. The Resource Bars exist of the health bar, mana bar, and the buff bar. So if you finish the Tutorial you got your custom health/mana bars but no buff bar. Later I will add a custom buff bar to the Tutorial.
Now create the class HealthManaBars and implement the OnInitialize() method:
Code:
namespace CustomBars.UI
{
    internal class HealthManaBars: UIState
    {
        public override void OnInitialize()
        {
            //empty
        }
    }
}
Now we want to create a visible variable to easily control the current visibility of the UI:
Code:
public static bool visible = false;
We will add an empty default Terraria panel and position it at the top right of the game. We will go over the other UI elements later. Add to the OnInitialize():
Code:
UIPanel parent = new UIPanel();
parent.Height.Set(100f, 0f);
parent.Width.Set(300, 0f);
parent.Left.Set(Main.screenWidth - parent.Width.Pixels, 0f);
parent.Top.Set(0f, 0f);
parent.BackgroundColor = new Color(255, 255, 255, 255);

base.Append(parent);
Back to the Mod class create a HealthManaBars instance and register the UIState to the UserInterface:
Code:
public HealthManaBars healthManaBars;
.
.
.
public override void Load()
        {
            if (!Main.dedServ)
            {
                customRessources = new UserInterface();
                healthManaBars = new HealthManaBars();
                HealthManaBars.visible = true;
                customRessources.SetState(healthManaBars);

            }
        }
To See anything we need to update our UI. To do so go to the ModifyInterfaceLayers() and insert into the MethodSequenceListItem delegate:
Code:
if (HealthManaBars.visible)
{
    //Update CustomBars
    customResources.Update(Main._drawInterfaceGameTime);
    healthManaBars.Draw(Main.spriteBatch);
}
You can now run build your mod and you will see the first result:
View attachment 153852
4. Create our own UIElement
Terraria has already the most UIElements you need to build your UI. The best is all of them are in terraria style. You can find all elements in your Terraria Reference under Terraria.GameContent.UI.Elements:
View attachment 153854
We used the UIPanel earlier, but now we want to create our own UIElement. A flat panel without any borders.
So create a new class called UIFlatPanel that inheritance from UIElement. We need a color for the background and a texture. The texture is needed because everything will be drawn using a spriteBatch which require a texture.
Here the texture I use: View attachment 153855
Download and put into your project (mine is at {ModID}\Textures\UI). Now we will create our UIElement class:
Code:
namespace CustomBars.UI
{
    class UIFlatPanel : UIElement
    {
        public Color backgroundColor = Color.Gray;
        private static Texture2D _backgroundTexture;

        public UIFlatPanel ()
        {
            if (_backgroundTexture == null)
                _backgroundTexture = ModLoader.GetTexture("CustomBars/Textures/UI/Blank");
        }
    }
}
Now we need to tell the UIElement how it should be drawn. We override the methode DrawSelf(..):
Code:
protected override void DrawSelf(SpriteBatch spriteBatch)
        {
            CalculatedStyle dimensions = GetDimensions();
            Point point1 = new Point((int)dimensions.X, (int)dimensions.Y);
            int width = (int)Math.Ceiling(dimensions.Width);
            int height = (int)Math.Ceiling(dimensions.Height);
            spriteBatch.Draw(_backgroundTexture, new Rectangle(point1.X, point1.Y, width, height), backgroundColor);
        }
We get the Dimension which is holding the information of the size and position of the element. We create the top left point called point1. Now we draw the _backgroundTexture as a Rectangle with the given size and color.
Now we got our own UIElement and are ready to test it out. Go to your HealthManaBars class and change the UIPanel to our new UIFlatPanel. Also, add another red one and blue one:
Code:
public override void OnInitialize()
{
    UIFlatPanel parent = new UIFlatPanel();
    parent.Height.Set(65f, 0f);
    parent.Width.Set(300f, 0f);
    parent.Left.Set(Main.screenWidth - parent.Width.Pixels, 0f);
    parent.Top.Set(0f, 0f);
    parent.backgroundColor = new Color(255, 255, 255, 255);

    UIFlatPanel hp = new UIFlatPanel();
    hp.Height.Set(25f, 0f);
    hp.Width.Set(280f, 0f);
    hp.Left.Set(10f, 0f);
    hp.Top.Set(5f, 0f);
    hp.backgroundColor = Color.Red;
    parent.Append(hp);

    UIFlatPanel mana = new UIFlatPanel();
    mana.Height.Set(25f, 0f);
    mana.Width.Set(280f, 0f);
    mana.Left.Set(10f, 0f);
    mana.Top.Set(35f, 0f);
    mana.backgroundColor = Color.Blue;
    parent.Append(mana);

    base.Append(parent);
}
It should look like this:
View attachment 153858


5. Implement the Life/Mana Bar
So now we want to show the user the amount of life and mana as text. Also, implement its progress animation. To do so we create a new UIElement that contains two flat panels. One is the background and the other one is the current life/mana. I named the class ResourceBar. I also created an inner enum to set the current stat to display:
Code:
namespace CustomBars.UI
{
    internal enum ResourceBarMode
    {
        HP,
        MANA
    }
    class ResourceBar : UIElement
    {
        private ResourceBarMode stat;
        private float width;
        private float height;

        public ResourceBar(ResourceBarMode stat, int height, int width)
        {
            this.stat = stat;
            this.width = width;
            this.height = height;
        }

    }
}
Now create the OnInitialize() and add a gray FlatPanel as background and a colored as the current value and a UIText element. Determine the color of the current panel depending on the ResourceBarMode:
Code:
private UIFlatPanel currentBar;
private UIText text;
.
.
.
public override void OnInitialize()
{
    Height.Set(height, 0f); //Set Height of element
    Width.Set(width, 0f);   //Set Width of element

    UIFlatPanel barBackground = new UIFlatPanel(); //Create gray background
    barBackground.Left.Set(0f, 0f);
    barBackground.Top.Set(0f, 0f);
    barBackground.backgroundColor = Color.Gray;
    barBackground.Width.Set(width, 0f);
    barBackground.Height.Set(height, 0f);

    currentBar = new UIFlatPanel(); //Create current value panel
    currentBar.SetPadding(0);
    currentBar.Left.Set(0f, 0f);
    currentBar.Top.Set(0f, 0f);
    currentBar.Width.Set(width, 0f);
    currentBar.Height.Set(height, 0f);

    //assign color to panel depending on stat
    switch (stat)
    {
        case ResourceBarMode.HP:
            currentBar.backgroundColor = new Color(164, 55, 65); //red
            break;

        case ResourceBarMode.MANA:
            currentBar.backgroundColor = new Color(46, 67, 114); //blue
            break;
        default:
            break;
    }

    text = new UIText("0|0"); //text to show current hp or mana
    text.Width.Set(width, 0f);
    text.Height.Set(height, 0f);
    text.Top.Set(height / 2 - text.MinHeight.Pixels / 2, 0f); //center the UIText

    barBackground.Append(currentBar);
    barBackground.Append(text);
    base.Append(barBackground);
}
Next we will implement the progress of the bar by overriding the draw method and determine how many percent of the current bar should be displayed:
Code:
public override void Draw(SpriteBatch spriteBatch)
{
    Player player = Main.player[Main.myPlayer];
    float quotient = 1f;
    //Calculate quotient
    switch (stat)
    {
        case ResourceBarMode.HP:
            quotient = (float)player.statLife / (float)player.statLifeMax;
            break;

        case ResourceBarMode.MANA:
            quotient = (float)player.statMana / (float)player.statManaMax;
            break;

        default:
            break;
    }
    currentBar.Width.Set(quotient * width, 0f);
    Recalculate(); // recalculate the position and size

    base.Draw(spriteBatch);
}
Now we need to override the Update(..) method to update the text:
Code:
public override void Update(GameTime gameTime)
{
    Player player = Main.player[Main.myPlayer]; //Get Player
    switch (stat)
    {
        case ResourceBarMode.HP:
            text.SetText("" + player.statLife + " | " + player.statLifeMax); //Set Life
            break;

        case ResourceBarMode.MANA:
            text.SetText("" + player.statMana + " | " + player.statManaMax); //Set Mana
            break;

        default:
            break;
    }
    base.Update(gameTime);
}
The ResourceBars are ready now so go back to the HealthManaBars class and change the hp and mana UIFlatPanels to ResourceBars. Also, remove the old white panel:
Code:
public override void OnInitialize()
{
    ResourceBar hp = new ResourceBar(ResourceBarMode.HP, 280, 25);
    hp.Left.Set(Main.screenWidth - hp.Width.Pixels - 10, 0f);
    hp.Top.Set(5f, 0f);
    base.Append(hp);

    ResourceBar mana = new ResourceBar(ResourceBarMode.MANA, 280, 25);
    mana.Left.Set(Main.screenWidth - hp.Width.Pixels - 10, 0f);
    mana.Top.Set(35f, 0f);
    base.Append(mana);
}
To be able to stay in the top right coner i override the DrawSelf method of HealthManaBars:
Code:
protected override void DrawSelf(SpriteBatch spriteBatch)
{
    panel.Left.Set(Main.screenWidth - panel.Width.Pixels, 0f);
    panel.Top.Set(0f, 0f);
    Recalculate();
}
Now it should stay at the top right even after resize.
Now we are ready and got two new bars. In the end, it should look like this:
View attachment 153883 View attachment 153884



Thank you for your patience and after you implemented the health bar you will see it´s very easy to create or replace a UI. In some days we will create a custom buff bar.

Myself :)
the tModLoader Team & Co- creating tModloader, ExampleMod
Re-Logic - Creating that amazing game
Where Can I Find The Scource or the answer to why List<MethodSequenceListItem> is giving me errors?

Thank You!
 
Back
Top Bottom