Adding Your Own Content; Part 3.1 (Custom Auto Combine function)
Intro
There are so many things you can do by modding. One of them is adding your own code to the game. This includes your own classes and methods that can add content to the game! You can use this fact to patch bugs or create bots (like auto combine) or even create things like aimbots or ESP for FPS games.In this Part 3.1, I will be covering how I created the custom Auto Combine function (The idea is to be able to add your own functions to any game).
In Part 3.2, I will be covering how to make a mod menu and I will be providing code you can copy paste and edit for your own use :)
For Part 3, you will need coding experience to understand what I am doing.
Add Your Own Method (My Thought Process)
I will teach you how you can add your own method and add to the game using DnSpy or any .NET dissemblers. So, as before, open up your dissembler and load up the Assembly-CSharp.dll of your game.
Decide what you want to do. In this case, I will be adding a custom auto combine since the one in game is too limiting for my taste.
Let's think of how we can do this. In my Post 2, as we were looking to see if we can hack the auto combine speed, we found a class called Panel_Items_Bag and we found out that it was responsible for the items combining. The class has the function that processes an item being dragged on top of another: OnDropItem().
Here, we see that the parameters passed is am object of DragObject.DraggingItem and an index.
By the name and how it's used in the function, I can tell right away that the first parameter is the item the user is dragging.
As for index, looking at the second if statement,
if (DragObject.draggingItem.index == index) { return; }
I can already tell that index is the location where the user dragged the item. So, the if statement is saying, if the user dragged the item and placed it back down at the same location, do nothing.
Then ultimately, we see how the stone combination works; it sends a packet of type SwapGameItem and a SwapGameItem object with data of the indexes of the items being combined.
Through this, we can tell many things:
1) Combination actually happens directly on the server.
2) Therefore, super combination chance can't be modded
3) Weather can't be modded to give you a boost on super combination chance
4) You can't mod what's combined.
5) Your bag with all your item is stored on the server, since all the packet needs are the indexes of the items.
However, we can take this information and create something that will virtually drag the items together, acting like the auto combination!
So all this function does is send a packet with the indexes of the items that are combined. (The other if statement about the Popup_CraftItems_Items can be ignored since there is no crafting system in the game yet; perhaps it's a future implementation.)
Now, we can make our own method that sends the exact same packet - all we need are the indexes of the items that we want to combine.
First, let's inject a new method into the class Panel_Items_Bag. Right click on it on the left panel,
Let's just name it AutoCombine and since we don't have to return anything, we'll leave the return type void.
Click Okay and now we got a method called AutoCombine() :D
Now, right click on the name and choose "Edit Method." A window called Edit Code will popup and this is where the fun starts :)
Let's rewrite the function as this since we don't need the extern keyword.
public void AutoCombine () {
//Your code here
}
Now, how do we make it do what we want? It's really simple to program the logic in this: we will look through our bag and see if we have any same types of stones. Think of it as basic sorting and comparing data. Then once we get a match, we will get their indexes (their position in the bag) and send a packet to the server as if we manually dragged an item on top of another of the same type.
Okay, so let's grab our bag:
Here, I notice the variable _cells of our bag class. This pops out to me because it makes sense that the bag is made of bunch of cells put together and the cells are what holds the items.
So _cells is a List of Panel_Items_Cell. We can loop through this list and see if the cells contain rocks, and if they do, we can see if any other cells have the same types of rocks.
In the Panel_Items_Cell class, we can see that it has a variable called index which we will need for the packet and methods/variables that make it obvious that these cells are the individual parts that make up the whole bag.
Okay and now to write the actual code:
The idea here is to loop through all the cells (this._cells), grab the items in the cell and compare it to other items in different cells. If they are the same, combine them and if not, ignore them.
We can use a nested for loop here to get started:
for( int i = 0; i < this._cells.Count -1; i++) {
//Grab the item in _cells;
for( int j = i + 1; j < this._cells.Count; j++) {
//Get next item
//compare item [i] and item [j]
//if same, send packet type SwapGameItem with i and j (they are the indexes)
//if different, continue;
}
}
That's basically it. Just as easy as that.
To do this, we can use this method already in the bag class:
So each cell in _cells, has an index as we saw earlier. This is the same as the index of the cell in the List _cells.
With this information, we can grab the item in our bag by calling GetItemBySlot() and passing on 'i' or 'j' as the index in our for loops.
Here is what I ended up with when I translated these thoughts into code.
Super simple code.
This part is where I compare the dataID's of the items to see if they are the same items. I reversed engineered the TItem class to see what variables it had. I just make sure the slot isn't empty and compare the data IDs.
Then I send the packet with the indexes of the items I just checked just like how the game does it back in OnDropItem().
Now that we have this method, we have to call it somewhere in the code. I'll just put it in the Update() function of the bag class since it is called continuously.
Let's do Edit Method on the Update function:
So what we need to do here is set a timer that will call our AutoCombine function. Super easy to do.
We will first add a variable called autoCombineDelay which will hold how many seconds has passed since we last called AutoCombine(). We make this variable in a higher scope than the Update function so that the same variable is used.
Now, we add time to it every time the Update function is called:
this.autoCombineDelay += Time.deltaTime;
In Unity, Time.deltaTime is "he time in seconds it took to complete the last frame" (from Unity documentation).
Then we check if this,autoCombineDelay is greater than whatever delay we want (basically how many seconds should it call the AutoCombine function).
if (this.autoCombineDelay >= 5f) {
this.autoCombineDelay = 0;
this.AutoCombine();
}
Just an easy timer :)
Now in the game, every 5 seconds, my auto combine method will be called, combining the same rocks together.
Decide what you want to do. In this case, I will be adding a custom auto combine since the one in game is too limiting for my taste.
Let's think of how we can do this. In my Post 2, as we were looking to see if we can hack the auto combine speed, we found a class called Panel_Items_Bag and we found out that it was responsible for the items combining. The class has the function that processes an item being dragged on top of another: OnDropItem().
Here, we see that the parameters passed is am object of DragObject.DraggingItem and an index.
By the name and how it's used in the function, I can tell right away that the first parameter is the item the user is dragging.
As for index, looking at the second if statement,
if (DragObject.draggingItem.index == index) { return; }
I can already tell that index is the location where the user dragged the item. So, the if statement is saying, if the user dragged the item and placed it back down at the same location, do nothing.
Then ultimately, we see how the stone combination works; it sends a packet of type SwapGameItem and a SwapGameItem object with data of the indexes of the items being combined.
Through this, we can tell many things:
1) Combination actually happens directly on the server.
2) Therefore, super combination chance can't be modded
3) Weather can't be modded to give you a boost on super combination chance
4) You can't mod what's combined.
5) Your bag with all your item is stored on the server, since all the packet needs are the indexes of the items.
However, we can take this information and create something that will virtually drag the items together, acting like the auto combination!
So all this function does is send a packet with the indexes of the items that are combined. (The other if statement about the Popup_CraftItems_Items can be ignored since there is no crafting system in the game yet; perhaps it's a future implementation.)
Now, we can make our own method that sends the exact same packet - all we need are the indexes of the items that we want to combine.
First, let's inject a new method into the class Panel_Items_Bag. Right click on it on the left panel,
Let's just name it AutoCombine and since we don't have to return anything, we'll leave the return type void.
Click Okay and now we got a method called AutoCombine() :D
Now, right click on the name and choose "Edit Method." A window called Edit Code will popup and this is where the fun starts :)
Let's rewrite the function as this since we don't need the extern keyword.
public void AutoCombine () {
//Your code here
}
Now, how do we make it do what we want? It's really simple to program the logic in this: we will look through our bag and see if we have any same types of stones. Think of it as basic sorting and comparing data. Then once we get a match, we will get their indexes (their position in the bag) and send a packet to the server as if we manually dragged an item on top of another of the same type.
Okay, so let's grab our bag:
Here, I notice the variable _cells of our bag class. This pops out to me because it makes sense that the bag is made of bunch of cells put together and the cells are what holds the items.
So _cells is a List of Panel_Items_Cell. We can loop through this list and see if the cells contain rocks, and if they do, we can see if any other cells have the same types of rocks.
In the Panel_Items_Cell class, we can see that it has a variable called index which we will need for the packet and methods/variables that make it obvious that these cells are the individual parts that make up the whole bag.
Okay and now to write the actual code:
The idea here is to loop through all the cells (this._cells), grab the items in the cell and compare it to other items in different cells. If they are the same, combine them and if not, ignore them.
We can use a nested for loop here to get started:
for( int i = 0; i < this._cells.Count -1; i++) {
//Grab the item in _cells;
for( int j = i + 1; j < this._cells.Count; j++) {
//Get next item
//compare item [i] and item [j]
//if same, send packet type SwapGameItem with i and j (they are the indexes)
//if different, continue;
}
}
That's basically it. Just as easy as that.
To do this, we can use this method already in the bag class:
So each cell in _cells, has an index as we saw earlier. This is the same as the index of the cell in the List _cells.
With this information, we can grab the item in our bag by calling GetItemBySlot() and passing on 'i' or 'j' as the index in our for loops.
Here is what I ended up with when I translated these thoughts into code.
Super simple code.
This part is where I compare the dataID's of the items to see if they are the same items. I reversed engineered the TItem class to see what variables it had. I just make sure the slot isn't empty and compare the data IDs.
Then I send the packet with the indexes of the items I just checked just like how the game does it back in OnDropItem().
Now that we have this method, we have to call it somewhere in the code. I'll just put it in the Update() function of the bag class since it is called continuously.
Let's do Edit Method on the Update function:
So what we need to do here is set a timer that will call our AutoCombine function. Super easy to do.
We will first add a variable called autoCombineDelay which will hold how many seconds has passed since we last called AutoCombine(). We make this variable in a higher scope than the Update function so that the same variable is used.
Now, we add time to it every time the Update function is called:
this.autoCombineDelay += Time.deltaTime;
In Unity, Time.deltaTime is "he time in seconds it took to complete the last frame" (from Unity documentation).
Then we check if this,autoCombineDelay is greater than whatever delay we want (basically how many seconds should it call the AutoCombine function).
if (this.autoCombineDelay >= 5f) {
this.autoCombineDelay = 0;
this.AutoCombine();
}
Just an easy timer :)
Now in the game, every 5 seconds, my auto combine method will be called, combining the same rocks together.
How Do I Use This In Other Games?
Well, I hope you didn't get lost while trying to follow my thought process about how I made my own auto combination.
The same process can be used for anything. Maybe you're modding a fps game and you want ESP. You can make a method that loops through players in the game and draw boxes around them so you can see where they are through walls. Maybe you're modding an rpg game and you want to make a bot that finds and kills monsters. You can loop through monsters in your map and write code that moves your character towards them and attack them.
What and how you do this are up to you and your programming skills.
In the next section, Part 3.2, I will be covering how to make your own mod menu. The process is very similar except you're adding a class instead of a method. It's basically the same thing. If you understood this article, then you probably already know how to make your own mod menu.
Comments
Post a Comment