Jump to content

[Code] Customize Dropped Item Icons


Smallio_Pro

Recommended Posts

Version: 0.7.10

Originaly Written: 07/03/23

Last updated:

(Warning!! Always backup any files when working on the source code!)

Index

1. Introduction

2. Show Case

3. Declaring And Calling "GroundIcon"

4. Redesigning The Item Editor

5. The Final Stretch

6. Extra Notes

7. Ending Ramblings

 

 

Introduction

Since I am no longer using this engine anymore for my current project I thought I would help a few people out with show casing some of the features I finished before moving over. One feature being the ability to set what the items looks like when on the floor. Essentially you can select what your items look like when they are dropped and what they look like when they are in your inventory. Before reading further, this tutorial is for people who have a small knowledge of coding. Not a tone of knowledge, as long as you know what an if statement is and how to use Ctrl + F you shouldn't get lost but I recommend starting with this guide here: https://docs.freemmorpgmaker.com/en-US/developer/

 

Show Case

I had an issue where my items were bigger than my player sprites which made my game ugly. The Items looked good in the inventory so I didn't want to make them smaller in the UI. So I coded in a fix.

 

Before the fix:

 

Spoiler

d6f103a17346effe99477064da8237e3.png

 

After the fix:

Spoiler

012c7acee5d7ca5a255bd738650485d1.png

 

And in the editor you can see I can customize both icons individually:

Spoiler

021034f87693fcb87df86dd8a11ac4d5.png

 

Declaring And Calling "GroundIcon"

Now onto the fun part, coding. First you are going to want to make the variable your new database of icons will be stored in Then you want to change the code to draw that icon instead of the standard one. We will be calling this variable "GroundIcon"

 

Go to: Intersect.core > GameObjects >ItemBase.cs

Find:

Spoiler
public string Icon { get; set; } = "";

 

And add under that line:

Spoiler
 [NotMapped]
  public string GroundIcon { get; set; } = "";

 

 

That's the "GroundIcon" declared. now head over to Intersect.Client > Maps > Mapinstances.cs

Under "public void DrawItemsAndLights()" Find:

Spoiler
var itemTex = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Item, itemBase.Icon);

 

 

And replace it with:

Spoiler
var itemTex = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Item, itemBase.GroundIcon);

 

 

Redesigning The Item Editor

We have created our variable and also made it so any icons stored in that variable will show up on the map. Only issue is, "GroundIcon" is empty. We of course are going to assign it some values through the Item Editor. But first we need to redesign the form and code in the components.

 

Head over to Intersect.Editor > Forms > Editors > fmrItem.cs

Now you are going to want to rearrange some of the components in that form to make room for the ones you are going to create. Once you have created some room. Copy and paste the existing ComboBox and PictureBox: 

Spoiler

cd070e5dcdac78437d10f8640f9d373e.png

 

Now you are going to want to name your new components the following

ComboBox = cmbGround

PictureBox = picGround

 

For the last step of this section, double click on the new cmbGround and enter the following code:

Spoiler
private void cmbGround_SelectedIndexChanged(object sender, EventArgs e)
        {
            {
                mEditorItem.GroundIcon = cmbGround.SelectedIndex < 1 ? null : cmbGround.Text;
                picGround.BackgroundImage?.Dispose();
                picGround.BackgroundImage = null;
                if (cmbGround.SelectedIndex > 0)
                {
                    DrawGroundIcon();
                }
            }
        }

 

 

The Final Stretch

Our ComboBox has been set up to return a value when saving the editor. And we have called upon a function that will draw our icons in the PictureBox. Yet that function hasn't been written yet, our ComboBox is empty and your copy of Visual Studios is probably throwing out scary errors. Looks like it's time for the final stretch.

 

Lets write out that DrawGroundIcon() first.

find DrawIcon:

Spoiler
        private void DrawItemIcon()
        {
            var picItemBmp = new Bitmap(picItem.Width, picItem.Height);
            var gfx = Graphics.FromImage(picItemBmp);
            gfx.FillRectangle(Brushes.Black, new Rectangle(0, 0, picItem.Width, picItem.Height));
            if (cmbPic.SelectedIndex > 0)
            {
                var img = Image.FromFile("resources/items/" + cmbPic.Text);
                var imgAttributes = new ImageAttributes();

                // Microsoft, what the heck is this crap?
                imgAttributes.SetColorMatrix(
                    new ColorMatrix(
                        new float[][]
                        {
                            new float[] { (float)nudRgbaR.Value / 255,  0,  0,  0, 0},  // Modify 
the red space
                            new float[] {0, (float)nudRgbaG.Value / 255,  0,  0, 0},    // Modify the green space
                            new float[] {0,  0, (float)nudRgbaB.Value / 255,  0, 0},    // Modify the blue space
                            new float[] {0,  0,  0, (float)nudRgbaA.Value / 255, 0},    // Modify the alpha space
                            new float[] {0, 0, 0, 0, 1}                                 // We're not adding any non-linear changes. Value of 1 at the end is a dummy value!
                        }
                    )
                );

                gfx.DrawImage(
                    img, new Rectangle(0, 0, img.Width, img.Height),
                    0, 0, img.Width, img.Height, GraphicsUnit.Pixel, imgAttributes
                );

                img.Dispose();
                imgAttributes.Dispose();
            }

                gfx.Dispose();

            picItem.BackgroundImage = picItemBmp;
        }

 

 

Underneath that enter:

Spoiler
        /// <summary>
        /// Draw the Ground Icon to the form.
        /// </summary>
        private void DrawGroundIcon()
        {
            var picItemBmp = new Bitmap(picGround.Width, picGround.Height);
            var gfx = Graphics.FromImage(picItemBmp);
            gfx.FillRectangle(Brushes.Black, new Rectangle(0, 0, picGround.Width, picGround.Height));
            if (cmbGround.SelectedIndex > 0)
            {
                var img = Image.FromFile("resources/items/" + cmbGround.Text);
                var imgAttributes = new ImageAttributes();

                // Microsoft, what the heck is this crap?
                imgAttributes.SetColorMatrix(
                    new ColorMatrix(
                        new float[][]
                        {
                            new float[] { (float)nudRgbaR.Value / 255,  0,  0,  0, 0},  // Modify the red space
                            new float[] {0, (float)nudRgbaG.Value / 255,  0,  0, 0},    // Modify the green space
                            new float[] {0,  0, (float)nudRgbaB.Value / 255,  0, 0},    // Modify the blue space
                            new float[] {0,  0,  0, (float)nudRgbaA.Value / 255, 0},    // Modify the alpha space
                            new float[] {0, 0, 0, 0, 1}                                 // We're not adding any non-linear changes. Value of 1 at the end is a dummy value!
                        }
                    )
                );

                gfx.DrawImage(
                    img, new Rectangle(0, 0, img.Width, img.Height),
                    0, 0, img.Width, img.Height, GraphicsUnit.Pixel, imgAttributes
                );

                img.Dispose();
                imgAttributes.Dispose();
            }

            gfx.Dispose();

            picGround.BackgroundImage = picItemBmp;
        }

 

 

That will update the PicGround whenever cmbGround is updated. Now lets add some values to the ComboBox

Under "frmItem_Load", find:

Spoiler
        private void frmItem_Load(object sender, EventArgs e)
        {
            cmbPic.Items.Clear();
            cmbPic.Items.Add(Strings.General.None);

            var itemnames = GameContentManager.GetSmartSortedTextureNames(GameContentManager.TextureType.Item);
            cmbPic.Items.AddRange(itemnames);

 

 

Add Underneath that:

Spoiler
cmbGround.Items.Clear();
cmbGround.Items.Add(Strings.General.None);
cmbGround.Items.AddRange(itemnames);

 

 

Now our ComboBox has values and our PictureBox show our icons. But when editing multiple items, neither of them our going to update when a new item is selected. Lets sort that at.

Under UpdateEditor(), find:

Spoiler
cmbPic.SelectedIndex = cmbPic.FindString(TextUtils.NullToNone(mEditorItem.Icon));

 

 

Underneath that make room and add:

Spoiler
cmbGround.SelectedIndex = cmbGround.FindString(TextUtils.NullToNone(mEditorItem.GroundIcon));

 

 

Now finally find:

Spoiler
                picItem.BackgroundImage?.Dispose();
                picItem.BackgroundImage = null;
                if (cmbPic.SelectedIndex > 0)
                {
                    DrawItemIcon();
                }

 

 

And add underneath:

Spoiler
                picGround.BackgroundImage?.Dispose();
                picGround.BackgroundImage = null;
                if (cmbGround.SelectedIndex > 0)
                {
                    DrawGroundIcon();
                }

 

 

Congratulations! If everything was coded in correctly then you now can edit how items look when dropped!

 

Extra Notes

  • Right now the Ground Icon uses the same RGB shaders as the original icon. Changing this is really easy and only involves coping and pasting the original sliders and editing the DrawGroundIcon() function

 

Ending Ramblings

This tutorial was made for those who are just wetting their feet in the source coding half of the engine. I appreciate the fact that I didn't go into the nitty gritty details but I feel that this is more than enough information to understand what's going on here. That said I am always more than welcome to answer any questions. Being a reply or a dm. As for our seasoned programmers, I would love to hear any improvements I can do upon this code so I can edit this post with the best information I can provide.

 

Rather than create a patch everyone could download I thought it would be more helpful to explain the process instead. The documentation is few to zero on the coding end so if this helps 1 person out with understanding how this engines code is structured, even a little, then I would consider that a win. I would also like to show case more features I have worked into the engine in the future that are more and less advanced. All considering how this tutorial goes.

Link to comment
Share on other sites

  • 1 month later...
  • 1 month later...

Hi, sorry, I'm newbie, not understand this part:

 

Head over to Intersect.Editor > Forms > Editors > fmrItem.cs

Now you are going to want to rearrange some of the components in that form to make room for the ones you are going to create. Once you have created some room. Copy and paste the existing ComboBox and PictureBox: 

  Reveal hidden contents

 

Now you are going to want to name your new components the following

ComboBox = cmbGround

PictureBox = picGround

Link to comment
Share on other sites

4 hours ago, Arufonsu said:

 

in the code he changed, we have the possibility to put different icons between inventory and drop on the map, update us in the official please, this makes a huge difference in the construction of the game.

Link to comment
Share on other sites

1 hour ago, dougrz said:

we have the possibility to put different icons between inventory and drop on the map

If your intention is to overload the client with additional resources and utilize distinct icons for each individual item, resulting in double the time needed to set up items, then certainly, the OP's solution is the one you should choose.
 

 

1 hour ago, dougrz said:

update us in the official please, this makes a huge difference in the construction of the game

This change would cause issues with existing projects as it is too specific and would require everyone to either re-configure every item in their resource folder or redo another version for them all in order to have different icons for the ground. From my perspective, this would result in a significant waste of time and resources for something that could be handled more efficiently in terms of code and execution. The idea itself is not necessarily bad if the intention is to have a different art style for dropped items compared to the rest of the UI (which, in my opinion, is odd, but who knows), but personally, I am not a fan of overloading the client with additional resources and introducing extra steps that could delay everyone's development. Moreover, it could be even worse for existing projects, which may not align with this change. Implementing something like this would require extensive discussions and approval from the repository's author and maintainers as well.


 

On 3/7/2023 at 8:06 AM, Smallio_Pro said:

The Items looked good in the inventory so I didn't want to make them smaller in the UI

If this is what you guys are looking for, #1788 provides a cleaner, faster, and less complex approach that consumes fewer resources (icons/files, time/configuration). It allows you to easily resize dropped items within seconds without the need to reconfigure each item individually, saving time and resources for those with new and existing projects.

Regards ~

Link to comment
Share on other sites

This is a very neat feature by itself but I feel that what @Arufonsu linked would work better as it doesn't require extra renders.
However, this posts feature would be useful if you want to add rarity borders around inventory items while keeping them clean on the ground.

That could be an extra feature to be added at some point I guess.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...