Tulip 2021 Game Assistive Technology Intermediate Class (5)
-
- 046-C,C++ optimize macro call
- 047-C, C++ Analysis of Release of Souls and Resurrection of Angels
- 048-C, C++ Write code to test the soul release and resurrection code
- 049-C, C++ second repair and improvement of traversal code+
- 050-ce, xdbg analysis equipment durability analysis (current value, upper limit value)
- 051-ce, xdbg debugging analysis, repairing single equipment function and repairing all equipment
- 052-C, C++ writing code to traverse equipment durability
- 053-ce,xdbg analyzes equipment array
- 054-Write code to traverse the equipment array
046-C,C++ optimize macro call
Make macro calls support UTF-8 character encoding.
In the previous code, the string was not transcoded (transcoded to UTF-8), so we grabbed the string in UTF-8 format from the memory and used it. In this lesson, we will support Chinese Add to it.
We change the directory name of the self-written functional interface to 001-self-written API interface, then copy the AnsiToUtf8 function to the end of AsciiUnicodeUtf8.cpp, and add the function prototype to AsciiUnicodeUtf8.h.
Modify the macro test function:
Let’s write the call here like this temporarily and test it first.
We copy a copy of the macro execution function, put it in the game function interface.cpp, and add it to the TGAME class.
Entering the game test, there is no problem, but in the end our goal is to enter the macro command in the edit box and execute it successfully. So far, we have only succeeded in transcoding.
Since the AnsiToUtf8 function we just wrote only supports converting multi-byte character sets to UTF-8, not Unicode to UTF-8, we temporarily changed the character set of the project to use multi-byte character sets. Problems occurred after compilation. , let’s fix it:
We add an associated value variable to the edit box:
Give this edit box value variable an initial value:
047-C, C++ Analysis of Release of Souls and Resurrection of Angels
After we use xdbg to attach the wow game, when the character is dead (there are two ways to resurrect, one is angel resurrection, and the other is to find the body), we go to the wow module in xdbg and search for the current module and constant 6B0B50. Searching for places where this plaintext package is called, you will find more than 600 places. If you want to do offline assistance, you must analyze it all. Since we do not do offline assistance, we only need to analyze the parts we need:
Then, wherever we break without pressing the release soul button on the game interface, there are some heartbeat packages and other functions (steering, etc.). We cancel the breakpoints in those places, and then click to release the soul. The place where the button is broken is most likely the package that releases the soul.
Of course, it is also possible that we call a CALL higher than this CALL (we double-click to go to the return address 0085898A in the stack in the lower right corner of the picture above), or it may be disconnected, but we still need to verify whether it is, or it may be several layers above. (Analyze to see if you can find the skill string name).
Let’s go to ecx and take a look:
The selected part in the picture above is the content of our package. The value 5 may be the size of the package, and 23FCD350 is the buffer of the package. We have analyzed it before when analyzing skills:
After canceling the breakpoint, it was also broken in another place. Of course, it may not have much to do with releasing the soul:
The further to the back the breakpoint is, the less likely it is to be related to the release of the soul. The further to the front, the greater the possibility. We can also go in and take a look at the content of the following packages:
Take a look at what’s inside the package:
There are many broken places later, we will copy and record them all:
That is to say, after we click the release soul button, about 8 packages are sent. After we return to the game, we will see the Angel NPC in a dead state:
We use the right mouse button to click on the angel and break several places. We record and cancel these breakpoints one by one:
After we click the accept button in the picture above, we can see where the CALL of this plaintext package will be called:
After recording it, cancel the breakpoint, let the game run, and then break to other places:
Although it is said that the later the package is grouped, the less likely it is, but if it is the later package, it is still possible;
As shown in the picture above, There are about three packages related to the resurrection of angels, after clicking the accept button.
There are 4 packs when you right-click on the NPC, and there are about 7 packs for releasing the soul. But which one is the real release of the soul, which one is the real right-clicking on the NPC, and which one is the real command for the resurrection of the angel? We will write code to test in the next class (write a structure to assemble the package and call the corresponding CALL for testing). Of course, we will focus on analyzing the first package group now, because the possibility of subsequent package groups is very small. Generally, The probability of being the first is as high as 90%.
Let’s first look at the package analysis process of right-clicking an NPC:
The value at position +10 may be the size of the packet, position +4 is the packet buffer, and position +0 is the vftable of the package object. Let’s take a look at the contents of the package at position +4:
The combination of these two is a complete package object and the contents of the package. That is to say, when we right-click the NPC normally, we need to group the package.
This means which NPC (monster) you want to visit, you pass its GUID, and 13D should be the command to open the NPC. This is a fixed integer, used as a calling convention, I passed it It is a value of 13D, which means that you need to access, open, and right-click this NPC. This is probably what it means. This is a guess on our part.
Let’s take a look at the package and package contents when the angel was resurrected:
What is pushed on the stack is ecx. We see that the content of the packet has basically not changed. Only the address of the packet buffer at position +4 has changed. Let’s take a look at the content of the packet buffer:
You can see that the release soul command 15A in the packet buffer has not changed and is fixed.
Let's take a look at the package formed by clicking the accept button of the angel's resurrection:
What is pushed onto the stack is edx, and the contents of the package are:
Let's test to see if ID1 and ID2 are the player's own ID. Let's go to the CALL to get the player object and set a breakpoint:
The eax obtained after the CALL interrupts and returns is the character pointer. We found that the content of the +30 address is not the ID 5B015407, indicating that 5B015407 may belong to the angel NPC. Specifically, we can print the monster list in the next lesson. Just compare.
048-C, C++ Write code to test the soul release and resurrection code
In this lesson we will write code for testing.
In order to be more versatile, we modify the plaintext packet function:
Let's test it. If it fails, we need to analyze the following CALL packages. In special cases, it may require several packages to be used together, but generally only one package is used. Specifically, we Need to do testing.
The soul has been released successfully and has arrived at the angel's side. Now there are two steps to be done:
Visit the NPC package and click the accept button to resurrect the package.
We need to see if the ID filled in buf belongs to an angel. We can verify it by traversing the monster list.
The test failed and the NPC cannot be opened;
Let’s first package the angel’s resurrection and test to see if it can be resurrected without opening the NPC. If so, we will jump By opening the NPC function:
The test was successful when very close to the angel, and the second package was successful.
Let’s continue to analyze the function of right-clicking an NPC with the mouse:
We found that the test to open the NPC failed because the NPC's ID was incorrect, indicating that the angel's ID changes dynamically (it will change every time the game is reopened). In this case, we need to dynamically traverse to the angel's ID, and Take it out.
After our testing (clicking the open NPC button multiple times, the NPC dialog box interface never appears, and successful resurrection after clicking Resurrection, it means that the NPC dialog box interface is not displayed; the packet only has an effect, and there will be no interface). Currently, this The situation indicates that a higher-level CALL needs to be called.
If you call it with one click, it means that these three functions are called together:
After testing, we found that one-click resurrection is not possible, and the character needs to be moved near the angel NPC to be resurrected. Therefore, we need to traverse the monster list, obtain the coordinates of the angel, and then move to the angel for resurrection.
049-C, C++ second repair and improvement of traversal code+
There is a problem with our traversal monster code and the traversal is incomplete. Let’s improve it this time.
From the picture above, we can see that after the monster object's first node is judged to be an even number, after the object is obtained in line 179, the object is not judged to be an even number. The even number in the while condition is still The judgment result of the first node of the monster object.
Because we did not add such a judgment that the object is an even number before, it will cause the object address in the while loop to be an odd number, which will causeR4(对象+0x20)
to obtain the object and generate an exception, and the program will be terminated in advance. If it terminates, the traversal will be incomplete.
Let's streamline the code and make it more complete:
The traversal is incomplete. There is another problem with the previous code. We can see that when the 6th traversal is reached (i=5), the program exits.
We set the TopMost property of the form to true, and set Minimize to true to add a minimize button. Maximizing is generally not needed.
We added a few print output statements to assist debugging, and finally found that we did not reach the end of the traversal linked list printed by printf on line 235 (selecting that line in the figure below only starts traversing, and there is no i=37 to end the traversal linked list) , indicating that there is still a problem. Only when we reach line 237 does it mean that our traversal is successful. If we do not reach this line, it means that there must be a problem in the code.
There is probably a problem with the function of traversing the linked list.
We can see from the picture above that after i=36 is completed, an error occurred when i=37 started traversing the linked list. It can be determined that the error occurred in the function of traversing the linked list. At first glance, it may be in the function of printing monster object information. Problem:
But this time the test was successful, but the code is still unstable. We will improve it later.
050-ce, xdbg analysis equipment durability analysis (current value, upper limit value)
The current suspicion is that there is a problem in the function that prints monster object information on line 185:
We can start from the head of the function or start from the suspicious place to add exception handling. It is speculated that there is a problem in getting the name of the backpack object:
Pop up a window when it makes an error and make it stop:
We also add a large exception handling to it on the upper layer and include the entire function, because if the exception is not caused by the backpack name, it will be passed to this layer:
We can comment out the MessageBox in the exception handling in the above figure, so that it can still traverse subsequent nodes, but we will keep this information packet here for now:
For example, we can also move the starting block of __try back to the assignment of the utf8 object name (which means there is no problem with the previous part of the code at this time), so that we can narrow the scope step by step and finally determine the error. The location of the code.
Durability analysis
For this numerical type, we use CE to search the memory:
We can use the starting address of this object to specify a range for it, roughly what the range is (start and stop as shown in the figure below). Generally speaking, the durability is very close to the address of this object (equipment object). Of course This is not absolute either:
We found it immediately, but whether this value is our durability or not, we will know after we change it (use CE to modify the address value 24 to 11).
We can see that the durability has become 11, which means that this address must be durable.
At this time we use CE's debugger to find out what accessed this address:
After we point the mouse up (as shown in the picture above), several assembly instructions are displayed. From here, its first offset is +D8.
Display the disassembler to see the flow of the code and see what the previous offset (the offset related to eax) is:
We record the register environment in the picture above, and edi is equal to 2DD905C8, which happens to be the address of the apprentice robe.
Let’s use xdbg again to see the upper limit of equipment:
As shown in the memory window below, the equipment limit of 35 is next to the durability:
We modified the durability to 333 in CE, and you can see that the upper limit of the apprentice's robe's durability is 333.
051-ce, xdbg debugging analysis, repairing single equipment function and repairing all equipment
Repairing a single piece of equipment and repairing all equipment must be outsourced to the server group. Please refer to the knowledge points in Lesson 29:
You can see that there are more than 400 group package functions, and we only need a few group packages now.
Now let’s look at the function of repairing all equipment (on your body and in your backpack)
Go to the game and cancel all breakpoints that are not related to repairing:
We open the NPC at the blacksmith, cancel all broken items, and then click on the picture below to repair all items:
Copy and select part of the code in the picture above for record, because if you send a package to the server, if you repair all the equipment, the package format may only have one instruction. If you modify a single equipment, there may be a GUID of the equipment. What exactly is it? We still have to take a look to find out.
As shown in the figure above, go to the address represented by eax in the memory window:
That is, 3A9FB50 is a package object. We copy the contents of the package and record it:
Let’s take a look at the contents of the packet buffer at position +4 of the packet object:
You need to copy and record at least 21 bytes of the content in the above picture.
In fact, the part selected at +14 in the picture above is useless.
In theory, all the objects we repair here do not need the two item IDs F1300000 and 4E013851, so these two may be the IDs of players or NPCs:
At this point we can determine that the ID is the ID of the NPC selling equipment.
Repair a single piece of equipment
Cancel the breakpoint, continue running the game, and cancel all the breakpoints that have been broken;
Then click to repair a single equipment, and then click on the equipment with insufficient durability (apprentice robe ):
We found that the contents of the package buffer for repairing a single equipment, compared with repairing all equipment, have two more values 0x8277 and 0x40000000:
These two values are the item IDs of the apprentice robes.
Write code to package test and repair individual equipment
As long as you don’t change characters, servers, exit the game, or the game version is not updated, these IDs will generally not change; in addition, if you buy another apprentice robe, the ID of the new apprentice robe will definitely be different. Each copy has an independent GUID.
The first member of the plaintext packet object in the picture above is not what we analyze. Since we don’t know what it is used for, it doesn’t matter if it is wrong. Let’s test it first and see if it doesn’t work. If it doesn’t work, change it to the correct value noted later.
We first manually open the NPC (this step is indispensable). If we find that the durability of the equipment is full, we will go to fight monsters and get beaten up to let the durability drop some for testing.
Then run to the NPC and open his and your character information to test:
After the test, it was found that it was not successful. I closed the role panel and reopened it to refresh it. I found that it was still unsuccessful. This means that the content of the first member of the group package is effective and needs to be modified to the correct value and try again. In addition, we also changed the length of the package. If the modification is not correct, the test may fail due to packet length issues.
The discovery is still unsuccessful. We first traverse some monster equipment items to see if the GUID of the apprentice robe has changed. After traversing and searching, we found that the GUID has not changed, and the GUID of the NPC has not changed either, so it is possible Or there is something wrong with the analysis of our package.
Let’s add a piece of debugging information to the plaintext packet sending EX function to see if it is executed to this place:
Judging from the debugging information output, the plaintext packet EX function must have been called.
Maybe the package we analyzed was wrong, let’s re-analyze it:
Cancel irrelevant breakpoints until the game can run.
We found that there are many CALLs that use package object parameters before calling 6B0B50. It may be necessary to call these previous CALLs to initialize this object, and we see that the package object content in the memory window in the lower left corner also 0x100 and other data, let’s expand the scope of the packet object (to +24) and try again;
The content of the packet buffer should be 0x15 bytes, and the previous analysis of this piece should be correct. :
Let’s regroup this package and give it a try:
There is also a situation where the equipment has been repaired but has not been refreshed. If we exit the game for a while and then enter again, the data may be updated (the function of repairing all equipment is simpler, it does not have redundant parameters such as item IDs; Repairing individual ones is more complicated).
Let’s test it by killing monsters and then resurrecting the character (you can also directly use the command .die to die. After resurrection, the durability of the equipment will be reduced). Open the character panel and backpack, and you can see the equipment. The durability has all dropped, and now it is more convenient to test;
At this time, we can use our code to inject it and try it:
The repair was completed and the test was successful. It may indeed be related to the data (0x100) behind the package content that we did not add before:
But it may not matter. You can go down and test it yourself. For example, in the picture above, lines 39 and 40 are set to 0, and line 41 is still 0x100. Give it a try; you can also try it when the NPC is not opened; repair all equipment Go down and assemble the package yourself and give it a try.
052-C, C++ writing code to traverse equipment durability
Traverse the durability of equipment in the monster list. It is said to be a monster list. In fact, all equipment, backpacks, things on the ground, monsters, and NPCs are in this monster list, and the durability of all these objects is traversed.
We write code to traverse the equipment in all monster arrays and print its current durability and upper limit of durability.
We add an "equipment-related" directory, a "backpack-related" directory, and a "monster-related" directory to the project's game function test directory:
Add the "Equipment Array.cpp" source file and the "Equipment Array.h" header file, and then copy the codes of several functions related to traversing monsters:
Change the name of the function to get the latest object to traverse equipment, and delete the code that has nothing to do with traversing equipment. We only need a simple traversal:
Let’s modify the parameters for traversing the linked list:
The function of saving recent objects in the two figures above is no longer needed and should be deleted.
The selected part in the picture above is no longer needed and should be deleted.
Then continue to modify the traversal linked list function (the function written before is problematic):
Let’s see how to determine whether it is an equipment object:
As you can see from the picture above, all categories 3 are basically equipment. This is one place to judge;
Another place is the virtual function table vftable: a>
Both of these places can be used to judge equipment. We can currently consider judging from the classification, which is more accurate, because if it is really a game, as long as the game is updated a little bit, the address of this virtual function table will occur. If it changes, we have to re-analyze the virtual function table, but the classification will not change.
So here we have to read out the object classification first:
In our previous code, we wrote functions for obtaining object types. Copy their function prototypes to the "Equipment Array.h" header file to use:
Rename the previous function of printing monster information to printing equipment information, and modify the function:
If it is equipment, it definitely does not have the monster name (the offset is wrong). If it is the equipment name, take a look at how the previous code gets the name:
The name of the equipment object is also obtained through the "Get Backpack Object Name" interface (the name must be transcoded after being obtained).
Printing object information does not require coordinates and distance information, so delete it.
To obtain the durability, we specially write two functions:
Finally, we use the main line to call the traversal equipment function:
Let the printed equipment information be formatted and aligned:
The test found that the printed count was 0, the durability was incorrect, and the name was empty. It seemed that other objects were passed in and were not filtered. Let’s take a look at a randomly selected object in the picture above:
Check the code and find that it is because the classification is not judged. Just modify it as shown in the picture above (if(分类1==3) 打印装备信息(对象);
), so that if it is an NPC or monster, it will not be printed.
You can see that in addition to the equipment on the body, the equipment in the backpack is also traversed (if we repair it at the NPC, we may only need to repair the equipment on the body);
If If you only need to iterate over the equipment you are wearing, you will need to analyze this equipment array in the next lesson.
In addition, apprentice's boots, apprentice's shirt, and light throwing knives do not have durability. They are novice equipment and have no durability. Only equipment purchased or purchased by yourself has durability.
So how do we distinguish the two (body equipment and backpack)?
When we analyzed the backpack before, we knew that the backpack is actually an 8-byte array. Each grid of the backpack array stores the 8-byte GUID of the item; and we learned from the above You can also see in the picture that the equipment on the character information is also a grid. It should most likely be an array, similar to our backpack array. We will analyze this equipment array together in the next lesson.
053-ce,xdbg analyzes equipment array
The principle of equipment analysis is actually the same as that of our backpack analysis. During backpack analysis, we search for related addresses in CE by moving the first grid of the backpack. In fact, if you move an object in any grid, it will Can be used as a breakthrough point;
Similarly, you can also use the equipment in the character object panel that we open as a backpack. For example, we take the apprentice robe on the equipment as an example and move it into the backpack:
At this time, this position is vacant. This position is generally a fixed value, either negative 1 or 0. Generally, the probability of 0 is higher;
Then we move the apprentice robe up. To play the game, we need to write the object address to the chest space, or write the serial number or ID of the object here. After moving it up, it means that there must be something in the corresponding memory location. Write to this corresponding memory, as long as your game does not restart, then if you move something up, it will write the corresponding data to the location of the equipment;
If it is the same as the backpack array here If so, then what is written should be the ID of our equipment:
We first remove the apprentice robe, then this grid will be empty. Then, we search for 4 bytes of 0 in CE, and then we put this item on it, then it will be a non-0 value, which can also be said is greater than 0, because the numerical types set here in CE are calculated as unsigned numbers:
And we didn’t change it at this time, so we can search for the unchanged value (keep clicking to scan again to search many times, and you can move other equipment, but it will have no effect on the chest grid):
Then remove the apprentice robe again and search for the exact value 0 again. This way, the results will be much less. We can also remove other equipment. The chest position is still 0, but scanning again in this way can filter out a lot of things. , then equip the other removed equipment back, and then scan again, repeating several times.
Then we put the apprentice robe on it and search for values greater than 0. This can be searched repeatedly, and it has not changed. We can search for unchanged values, and when there are relatively few results, we can manually delete the repeated values in the results. Change the red content:
Then we click on the apprentice robe on the equipment, but we do not actually remove it (we have not moved the apprentice robe into the backpack yet):
So we still searched for unchanged values and filtered down to only 36 results. Then we put the apprentice robe back, but there was still no change. We moved it again and moved it to the backpack, and then deleted the unchanged content. Or you can directly search for the exact value 0 to filter out a lot of content, then put on other equipment, search for the exact value 0, or search for the unchanged value; then put the apprentice robe back on, search for values greater than 0, and take off the other items. Equip or move other equipment, and then search for unchanged values, or search for values greater than 0.
We can see that 0x8277 is the ID1 of the apprentice robe, and the address value 29BB7118+4=29BB711C is the address of ID2 of the apprentice robe. From this point of view, these two addresses are the addresses related to this item. They may be in the equipment array. The sex ratio is greater, and other possibilities are unlikely.
We give the address value ID1 the next access breakpoint:
We can see that the disassembly code in the above picture is indeed an array access method. Whether it is an array or not, we uninstall the CE debugger and use xdbg to attach the game to take a look. It is more convenient to use xdbg to view the memory. .
We go to the 7543D3 position in xdbg. We see here that we analyzed the backpack before. It has almost the same structure as the backpack object, except that they are located at different offsets. So what is the specific offset? We go to the memory window. Let’s take a look at the next hardware access breakpoint at 29BB7118:
Then move the mouse to the apprentice robe on the chest of the character panel in the game, xdbg breaks:
We see that the value of eax is 4 and ecx is 29BB70F8, then29BB70F8+4*8+4
The 8 in this formula should be the 8 bytes occupied by the item ID1 and ID2, then let’s do it again Take a look at the backpack lesson analyzed earlier:
We guess that the offset is not 172. It seems that 4 is added here. Let’s see if it is specific in xdbg:
We see that 29BB70F8 is definitely not a character object, but we don’t know whether [角色对象+8]
is equal to 29BB70F8.
And29BB70F8+4*8+4
the value of this formula is ID2, so the two addresses 7543D3 and 7543D6 are IDs, so we have to look forward to find the source of ecx.
We can see that this ecx comes from the upper layer CALL0062E214:
The two lines selected in the above picture are also key points, we copy and record them.
At present, its subscript value is 4. Let's replace it and take a look in the memory window. We find that it is indeed ID2, so now we have to take a look at what edi is.
You can see that the value of edi is the address of an object, but we don’t know whether this object is a player. We copy it and record it. We will find out later when we traverse the character object. If so, then the base address offset of our equipment is Yes.
During testing, if the program or game gets stuck (abnormal), we can just re-enter the game and re-test and verify.
Let’s take a look at the virtual function table address of the role object in CE:
Now we can be sure that this edi is our player's character object. Specifically, let's put this value into the formula in CE to see:
And we can see from the equipment information that the apprentice robe happens to be in the grid with the subscript 4, and the apprentice shirt is in the grid with the subscript 5.
We go to the formula in the memory window of xdbg2C4D9010+18F0+4
. The calculated 2C4DAE78 is the base address of the equipment array. We view it in 8 bytes:
We can see that the GUIDs here are not in the order of the grid of equipment information. There may be some in the backpack. Let's first traverse our equipment, directional files, traverse monsters, and then click the console to close the file handle. , check the debugging information, and then compare it with the GUID in the memory above:
Comparison shows that the subscripts in the equipment array in the memory are in a different order than the subscripts of the equipment grids we see in the game:
The order is a bit messy, but the equipment is all in the equipment array in the memory. Let's organize and analyze the rules.
It means that it has been our backpack since 8281. We move the hearthstone in the second grid in the backpack to the first grid:
You can see that 8281 has moved to the first 8-byte memory address, which means that the large section in front of the selected one in the picture above is equipped, and starting from the address where 8281 is located is the backpack.
We put the second-to-last equipment in the backpack, the light throwing knife, into the 2nd slot of the backpack:
Let's count the 23 spaces in front of 8287 in the first space of the backpack in the memory above. These 23 spaces are for equipment, and after 23 spaces is the backpack.
From the picture above, we can see that the base addresses of the equipment array and the backpack array are different, but from the memory window above, we can see that the two are next to each other, and in the game we open the character panel and count the equipment. I found that there are only 20 grids in total, and I don’t know what the extra 3 grids are used for.
Since the monster array also contains the backpack array, in the next lesson we only need to use the formula above[角色对象+18F0+4]+下标*8
to traverse the ID1 and ID2 of all equipment (subscript limited 0 to 22), so there will be no backpack items such as hearthstones.
054-Write code to traverse the equipment array
When we analyzed the monster array before, we knew that after taking out the ID, we can obtain the backpack object and the equipment object by calling the 4D4BB0 function. In fact, all objects can be obtained through ID1 and ID2:
Because each member of the equipment array stores ID1 and ID2, the equipment object is obtained by calling the 4D4BB0 function, and then the information of the equipment is printed out. However, this is not efficient, and when looping This CALL must be called every time, and this CALL must be traversed in a loop, which is not very efficient;
Here we will talk about a more efficient method, which is in the previous section On the basis of the lesson, we operate in reverse:
Because in the last lesson we traversed all objects, then took out the ID1 and ID2 of all objects, and then used this ID1 and ID2 to traverse and compare with the ID1 and ID2 in the equipment array. If we traverse all the objects and take out the ID, if It is in the first 20 cells, so it means that this is our equipment object. In this way, we can get all the equipment in the equipment information of the character panel without getting the equipment in the backpack. This is how we distinguish the two. is on, so we use the second, better method to solve it. We don’t need to call the CALL 4D4BB0. That means there are two ideas. We use the latter idea to implement it, because we already have the traversal The code of all objects is already there, we only need to change it to achieve it.
Let’s continue the code from the previous lesson and write:
Because what we traversed before was the entire backpack and equipment, which have been printed out, now we need to block out the part of the equipment in the backpack, and we need to add a judgment to it:
We only need to determine whether ID1 and ID2 exist in this equipment array. If they belong to our equipment array, then we will print it. If not, it means that it belongs to the backpack array. We distinguish the two, and we write A function will do.
First we need to get the pointer of the character object, and then calculate the base address of the equipment array through the formula:
In fact, this equipment array function does not need to pass in object parameters, just pass in ID1 and ID2 directly and compare it with the id1 and id2 we read through the formula here (because ID1 and ID2 are in the previous layer's printing equipment information function. read), if the object is passed in, you have to read and retrieve the ID1 and ID2 of the object.
If the printed information is 0, it must be in the backpack, and if it is 1, it is the equipment.
We compile and run and click the traverse equipment button:
We found that the printout included the contents of the backpack and gear.
After analysis, we found that it was because we added a 4 less to the base address of the equipment array. As shown in the above picture, it prints correctly after modification: