[1.10f Tutorial] Make Minions with non-minions AI[Completed]

This forum is for discussions on how to edit what can not be edited through the txt files, needless to say this isn't about battle net hacking.

Moderators: Nefarius, Havvoric

Post Reply
User avatar
Ogodei
Senior Moderator
Champion of the Light
Posts: 420
Joined: Thu Mar 10, 2016 8:31 am
Italy

Hand-picked

[1.10f Tutorial] Make Minions with non-minions AI[Completed]

Post by Ogodei » Sun May 14, 2017 7:23 pm

Hello guys.
I noticed that some people asked about how to let every monster follow the player even without using a pet themed AI (NecroPet,DruidBear, and so on). As you may have noticed from my CE posts, I'm fond of summoner characters and therefore I decided to investigate and succeded in that.
Now, it is important to understand why some people would like to use pets with non-pets AIs, and the reason is this: although the Shadow Master's AI (if you apply my fix here viewtopic.php?f=8&t=62883) is able to perfectly replicate most of the enemy behaviors it cannot perform special actions such as Corrupt Archers running away from the enemy or the Imp's random teleport.

I'm going to explain you how to create a leash between a non-pet and a character (and here, I would really like to thank Necrolis for translating the code in C++ in a previous thread of mine and providing help with the player check described below).

We're going to work on the Bosses minion leash, which is the same used for the monsters revived by necromancers.

Here's the code for 1.10f, located in D2Game.dll

Code: Select all

6FCF0D10    8B4424 04       MOV EAX,DWORD PTR SS:[ESP+4]
6FCF0D14    53              PUSH EBX
6FCF0D15    55              PUSH EBP
6FCF0D16    56              PUSH ESI
6FCF0D17    8B28            MOV EBP,DWORD PTR DS:[EAX]
6FCF0D19    57              PUSH EDI
6FCF0D1A    8BFA            MOV EDI,EDX
6FCF0D1C    8BD9            MOV EBX,ECX
6FCF0D1E    8B75 0C         MOV ESI,DWORD PTR SS:[EBP+0C]
6FCF0D21    83FE FF         CMP ESI,-1
6FCF0D24  0F84 03010000   JE 6FCF0E2D
6FCF0D2A    85FF            TEST EDI,EDI
6FCF0D2C  0F84 F4000000   JE 6FCF0E26
6FCF0D32    8B47 04         MOV EAX,DWORD PTR DS:[EDI+4]
6FCF0D35    85C0            TEST EAX,EAX
6FCF0D37  0F8C E9000000   JL 6FCF0E26
6FCF0D3D    8B0D 6070D26F   MOV ECX,DWORD PTR DS:[<&D2Common.sgptDat
6FCF0D43    8B11            MOV EDX,DWORD PTR DS:[ECX]
6FCF0D45    3B82 800A0000   CMP EAX,DWORD PTR DS:[EDX+0A80]
6FCF0D4B  0F8D D5000000   JGE 6FCF0E26
6FCF0D51    8D0C40          LEA ECX,[EAX*2+EAX]
6FCF0D54    8D0CC9          LEA ECX,[ECX*8+ECX]
6FCF0D57    03C9            ADD ECX,ECX
6FCF0D59    2BC8            SUB ECX,EAX
6FCF0D5B    8B82 780A0000   MOV EAX,DWORD PTR DS:[EDX+0A78]
6FCF0D61    0FBF44C8 18     MOVSX EAX,WORD PTR DS:[ECX*8+EAX+18]
6FCF0D66    85C0            TEST EAX,EAX
6FCF0D68  0F8C B8000000   JL 6FCF0E26
6FCF0D6E    3B82 980A0000   CMP EAX,DWORD PTR DS:[EDX+0A98]
6FCF0D74  0F8D AC000000   JGE 6FCF0E26
6FCF0D7A    8D0CC0          LEA ECX,[EAX*8+EAX]
6FCF0D7D    8D0C48          LEA ECX,[ECX*2+EAX]
6FCF0D80    8D0488          LEA EAX,[ECX*4+EAX]
6FCF0D83    8B8A 900A0000   MOV ECX,DWORD PTR DS:[EDX+0A90]
6FCF0D89    8D0481          LEA EAX,[EAX*4+ECX]
6FCF0D8C    85C0            TEST EAX,EAX
6FCF0D8E  0F84 92000000   JE 6FCF0E26
6FCF0D94    33D2            XOR EDX,EDX
6FCF0D96    8A90 F0000000   MOV DL,BYTE PTR DS:[EAX+0F0]
6FCF0D9C    A1 A07BD26F     MOV EAX,DWORD PTR DS:[<&Fog.gdwBitMasks>
6FCF0DA1    2350 08         AND EDX,DWORD PTR DS:[EAX+8]
6FCF0DA4    895424 14       MOV DWORD PTR SS:[ESP+14],EDX
6FCF0DA8  74 7C           JE SHORT 6FCF0E26
6FCF0DAA    8B55 10         MOV EDX,DWORD PTR SS:[EBP+10]
6FCF0DAD    56              PUSH ESI
6FCF0DAE    8BCB            MOV ECX,EBX
6FCF0DB0    E8 4BADFCFF     CALL 6FCBBB00
6FCF0DB5    8BF0            MOV ESI,EAX
6FCF0DB7    85F6            TEST ESI,ESI
6FCF0DB9  74 6B           JE SHORT 6FCF0E26
6FCF0DBB    8BCE            MOV ECX,ESI
6FCF0DBD    E8 EECAFCFF     CALL 6FCBD8B0
6FCF0DC2    85C0            TEST EAX,EAX
6FCF0DC4  75 60           JNE SHORT 6FCF0E26
6FCF0DC6    8BD6            MOV EDX,ESI
6FCF0DC8    8BCF            MOV ECX,EDI
6FCF0DCA    E8 41040000     CALL 6FCF1210
6FCF0DCF    83F8 01         CMP EAX,1
6FCF0DD2  7F 25           JG SHORT 6FCF0DF9
6FCF0DD4    8B4D 10         MOV ECX,DWORD PTR SS:[EBP+10]
6FCF0DD7    85C9            TEST ECX,ECX
6FCF0DD9  75 1E           JNE SHORT 6FCF0DF9
6FCF0DDB    6A 01           PUSH 1
6FCF0DDD    6A 13           PUSH 13
6FCF0DDF    56              PUSH ESI
6FCF0DE0    8BD7            MOV EDX,EDI
6FCF0DE2    8BCB            MOV ECX,EBX
6FCF0DE4    E8 77F7FDFF     CALL 6FCD0560
6FCF0DE9    85C0            TEST EAX,EAX
6FCF0DEB  74 21           JE SHORT 6FCF0E0E
6FCF0DED    5F              POP EDI
6FCF0DEE    5E              POP ESI
6FCF0DEF    5D              POP EBP
6FCF0DF0    B8 01000000     MOV EAX,1
6FCF0DF5    5B              POP EBX
6FCF0DF6    C2 0400         RETN 4
6FCF0DF9    83F8 14         CMP EAX,14
6FCF0DFC  7E 2F           JLE SHORT 6FCF0E2D
6FCF0DFE    6A 28           PUSH 28
6FCF0E00    6A 00           PUSH 0
6FCF0E02    BA 07000000     MOV EDX,7
6FCF0E07    8BCF            MOV ECX,EDI
6FCF0E09    E8 A2F3FDFF     CALL 6FCD01B0
6FCF0E0E    6A 13           PUSH 13
6FCF0E10    56              PUSH ESI
6FCF0E11    8BD7            MOV EDX,EDI
6FCF0E13    8BCB            MOV ECX,EBX
6FCF0E15    E8 46FDFDFF     CALL 6FCD0B60
6FCF0E1A    B8 01000000     MOV EAX,1
6FCF0E1F    5F              POP EDI
6FCF0E20    5E              POP ESI
6FCF0E21    5D              POP EBP
6FCF0E22    5B              POP EBX
6FCF0E23    C2 0400         RETN 4
6FCF0E26    C745 0C FFFFFFF MOV DWORD PTR SS:[EBP+0C],-1
6FCF0E2D    5F              POP EDI
6FCF0E2E    5E              POP ESI
6FCF0E2F    5D              POP EBP
6FCF0E30    33C0            XOR EAX,EAX
6FCF0E32    5B              POP EBX
6FCF0E33    C2 0400         RETN 4
[Softcoded part]

A) Create a dummy state ID in states.txt
B) Create a dummy passive skill in Skills.txt that will provide our state.
C) In Monstats.txt , clone the rows of the monsters you want to have as pets and set their Align and InTown column to 1 (Align allows them to attack nearby foes, while InTown is the parameter which removes the collision for players, so that the minions won't block your path)
D) Create a skill that summons your pet(s)
D1) Assign the passive to your pets via sumskill columns (skills.txt)

[Hardcoded part]

E) in D2Game.dll start by nopping the code at address 6FCF0D1E and 6FCF0D21, and hijack to an empty space of the DLL (in my case, it's as follows):

Code: Select all

6FCF0D1E  E9 5C5E0300     JMP 6FD26B7F

F) Now, in our empty space, let's insert a check for a specific state ID.

Code: Select all

6FD26B7F   8B46 04                              MOV EAX,DWORD PTR DS:[ESI+4]
6FD26B82   68 F6000000                          PUSH XXX     ; XXX = custom state's ID in hex
6FD26B87   57                                   PUSH EDI
6FD26B88   E8 3B4BFFFF                          CALL <JMP.&D2Common.#10487>              ; Jump to d2common.#10487
6FD26B8D   85C0                                 TEST EAX,EAX
6FD26B8F    75 05                                JNE SHORT 6FD26B96
6FD26B91    8B75 0C                              MOV ESI,DWORD PTR SS:[EBP+0C]
6FD26B94    EB 05                                JMP SHORT 6FD26B9B
6FD26B96    BE 01000000                          MOV ESI,1
6FD26B9B    83FE FF                              CMP ESI,-1
6FD26B9E    0F84 89A2FCFF                        JE 6FCF0E2D <-- proceed with the vanilla code
6FD26BA4    E9 81A1FCFF                          JMP 6FCF0D2A <-- jump here if not a minion
With this modification we'll tell the game to check if monsters have our dummy ID. If they haven't, then their ownership is set to [EBP+0C], which can be either free [ESI = -1] or owned by a boss [ESI = 1]
Contrariwise, if they have our state, their ownership will be set to ESI=1, to indicate they're minions.

G) Next, NOP from 6FCF0DAA to 6FCF0DAE and hijack, again, to an empty space. In my case, it's

Code: Select all

6FCF0DAA  E9 0A5E0300     JMP 6FD26BB9

and then, in our empty space, we will introduce a check for the minions: they will identify the player who owns them. If no player owns this minion, then the game will assign them to the proper Boss.

Code: Select all

6FD26BB1    8B4D 2C                              MOV ECX,DWORD PTR SS:[EBP+2C]
6FD26BB4    83FE 08                              CMP ESI,8
6FD26BB7    7F 0F                                JG SHORT 6FD26BC8
6FD26BB9    BA 00000000                          MOV EDX,0
6FD26BBE    89CE                                 MOV ESI,ECX
6FD26BC0    56                                   PUSH ESI
6FD26BC1    89D9                                 MOV ECX,EBX
6FD26BC3    E9 E7A1FCFF                          JMP 6FCF0DAF
6FD26BC8    8B55 10                              MOV EDX,DWORD PTR SS:[EBP+10]
6FD26BCB    89CE                                 MOV ESI,ECX
6FD26BCD    56                                   PUSH ESI
6FD26BCE    89D9                                 MOV ECX,EBX
6FD26BD0    E9 DAA1FCFF                          JMP 6FCF0DAF
6FD26BD5    90                                   NOP
Here's the result. You may see that the monsters are following me "abnormally", but that's the result of other code edits of mine in order to make them better at keeping the pace with the summoner.

Here's the result :)



*note* : You may notice that sometimes SuperUniques and Random Bosses minions will stop following them, but that's not due to this edit. It's rather a flaw of D2 vanilla code.
I tested it, and it persists even in vanilla 1.14d ^^'

ocarinas
Posts: 50
Joined: Sun Apr 10, 2016 4:36 am

Re: [1.10f Tutorial] Make Minions with non-minions AI[Completed]

Post by ocarinas » Mon Oct 08, 2018 9:45 am

Sorry for necroing the thread.
Just wanna ask if this works with hireling?
I haven't started modding yet so I can't test, just wanna make sure first.

And thanks for many cool CE you've shared. They will help me greatly in what I want to achieve.

Edit: Oh that was fast! Thanks for the advice.
Last edited by ocarinas on Mon Oct 08, 2018 10:27 am, edited 1 time in total.

User avatar
Ogodei
Senior Moderator
Champion of the Light
Posts: 420
Joined: Thu Mar 10, 2016 8:31 am
Italy

Hand-picked

Re: [1.10f Tutorial] Make Minions with non-minions AI[Completed]

Post by Ogodei » Mon Oct 08, 2018 10:28 am

You're welcome :)

Long time since I did it, but I only tested with normally summoned monsters. However, since the code should refer to the owner's GUID, you can try with mercs, too, but I'd advise you not to use Hireable nor other pet specific AI's.

EDIT: tested, and it doesn't work. This leash is specific to normal monsters, sorry ^^ '

ocarinas
Posts: 50
Joined: Sun Apr 10, 2016 4:36 am

Re: [1.10f Tutorial] Make Minions with non-minions AI[Completed]

Post by ocarinas » Mon Oct 08, 2018 10:42 am

Oh what a shame, I guess Shadow Master is the only choice for me then.

And thanks for testing for me.

User avatar
Ogodei
Senior Moderator
Champion of the Light
Posts: 420
Joined: Thu Mar 10, 2016 8:31 am
Italy

Hand-picked

Re: [1.10f Tutorial] Make Minions with non-minions AI[Completed]

Post by Ogodei » Wed Oct 10, 2018 3:35 pm

Np :)

Anyway, using Shadow Master isn't a big deal if you "fix its AI". Actually it could be even better for special pets like mercenaries - instead of monster AI's I mean - because you get extreme flexibility in matter of skills and combat behavior.


EDIT ! [10/10/2018]:

ocarinas,
Sorry but I discovered I had altered some settings. I reverted the code back to this tutorial's form and I have to correct myself. it works even for Hireables. I hope that helps you ^^ '

ocarinas
Posts: 50
Joined: Sun Apr 10, 2016 4:36 am

Re: [1.10f Tutorial] Make Minions with non-minions AI[Completed]

Post by ocarinas » Thu Oct 11, 2018 2:28 am

Hey thanks for reporting to me. Best news I've heard in awhile. :)

Post Reply

Return to “Code Editing”