I was tinkering around with Lady Isabelle in our mod when we stumbled upon what seemed to be a real nuisance: basically, we noticed that minions summoned through srvDoFunc #49 (for reference, the Assassin's Shadow Master \ Shadow Warrior summoning spells) didn't seem to get boni from the AuraStatCalc and PassiveCalc fields.
Therefore, I investigated a bit how the whole function was handled and found out that while the AuraStats are correctly applied, they all read the value/calc you put in AuraStatCalc2 and PassiveStatCalc2. While it is unclear if this is just a typo by the devs or it's specifically intended to be so, it is very annoying for people that are into modmaking, so here's the fix for this odd behaviour. By applying this code you will render your srvDoFunc 49 minions able to get boni from the proper calc fields.
the code we're modifying is this:
Code: Select all
6FCF990E | 8D4D 54 | lea ecx,dword ptr ss:[ebp+54] |
6FCF9911 | 894C24 50 | mov dword ptr ss:[esp+50],ecx |
6FCF9915 | C74424 18 06000000 | mov dword ptr ss:[esp+18],6 | i = 6
6FCF991D | 8B5424 50 | mov edx,dword ptr ss:[esp+50] |
6FCF9921 | 66:8B02 | mov ax,word ptr ds:[edx] |
6FCF9924 | 66:85C0 | test ax,ax |
6FCF9927 | 7C 34 | jl d2game.6FCF995D |
6FCF9929 | 8B0D 6070D26F | mov ecx,dword ptr ds:[<&sgptDataTables>] |
6FCF992F | 0FBFC0 | movsx eax,ax |
6FCF9932 | 8B11 | mov edx,dword ptr ds:[ecx] |
6FCF9934 | 3B82 D40B0000 | cmp eax,dword ptr ds:[edx+BD4] |
6FCF993A | 7D 21 | jge d2game.6FCF995D |
6FCF993C | 8B4C24 4C | mov ecx,dword ptr ss:[esp+4C] | ecx = SkillID
6FCF9940 | 8B55 6C | mov edx,dword ptr ss:[ebp+6C] | edx = AuraStatCalc2
6FCF9943 | 53 | push ebx | sLvl
6FCF9944 | 51 | push ecx | nSkillID
6FCF9945 | 52 | push edx | nCalcField
6FCF9946 | 56 | push esi | ptCaster
6FCF9947 | E8 C6240200 | call <JMP.&Ordinal#11276> | GetCalc
Code: Select all
for (int i = 6; i > 0; i--)
{
// count starts from 0, so aurastatcalc[1] means AuraStatCalc2
int nValue = GetCalc(ptCaster, ptSkillTXT->aurastatcalc[1], Skill_ID, sLvl);
AssignStat(ptStatList, ptSkillTXT->aurastat[i], nValue, Skill_ID);
}
in c++, it would be like this:
Code: Select all
for (int i = 6; i > 0; i--)
{
// count starts from 0, so aurastatcalc[1] means AuraStatCalc2
int nValue = GetCalc(ptCaster, ptSkillTXT->aurastatcalc[6 - i], Skill_ID, sLvl); // notice aurastatcalc[6-i] that returns the correct calc field.
AssignStat(ptStatList, ptSkillTXT->aurastat[i], nValue , Skill_ID);
}
In order to do this, we first have to hijack the code to a custom space in our D2Game.dll
Code: Select all
6FCF993C | 8B4C24 4C mov ecx,dword ptr ss:[esp+4C]
6FCF9940 | 8B55 6C mov edx,dword ptr ss:[ebp+6C]
Code: Select all
6FCF993C | E9 78D30200 jmp d2game.6FD26CB9
6FCF9941 | 90 nop
6FCF9942 | 90 nop
then, in our custom space, we'll write:
Code: Select all
6FD26CAF | 8B4424 18 | mov eax,dword ptr ss:[esp+18] | // [ESP+18] = i
6FD26CB3 | B9 06000000 | mov ecx,6 | /*
6FD26CB8 | 29C1 | sub ecx,eax | i = (i - 6) *4
6FD26CBA | B8 04000000 | mov eax,4 |
6FD26CBF | F7E1 | mul ecx | */
6FD26CC1 | 8B5405 68 | mov edx,dword ptr ss:[ebp+eax+68] | EDX becomes SkillCalc Field = AuraStatCalc[0 + i]
6FD26CC5 | 8B4C24 4C | mov ecx,dword ptr ss:[esp+4C] | ECX becomes nSkillID again
6FD26CC9 | E9 752CFDFF | jmp d2game.6FCF9943 | jump back to the vanilla code
As for the passivestats: we will do the same
Code: Select all
6FCF99A4 | 8B4C24 4C mov ecx,dword ptr ss:[esp+4C]
6FCF99A8 | 8B95 A8000000 mov edx,dword ptr ss:[ebp+A8]
Code: Select all
6FCF99A4 | E9 25D30200 | jmp d2game.6FD26CCE
6FCF99A9 | 90 | nop
6FCF99AA | 90 | nop
6FCF99AB | 90 | nop
6FCF99AC | 90 | nop
6FCF99AD | 90 | nop
Code: Select all
6FD26CCE | 8B4424 18 | mov eax,dword ptr ss:[esp+18] | // [ESP+18] = i
6FD26CD2 | B9 05000000 | mov ecx,5 | /*
6FD26CD7 | 29C1 | sub ecx,eax | i = (i - 5) *4
6FD26CD9 | B8 04000000 | mov eax,4 |
6FD26CDE | F7E1 | mul ecx | */
6FD26CE0 | 8B9405 A4000000 | mov edx,dword ptr ss:[ebp+eax+A4]| EDX becomes SkillCalc Field = PassiveStatCalc[0 + i]
6FD26CE7 | 8B4C24 4C | mov ecx,dword ptr ss:[esp+4C] | ECX becomes nSkillID again
6FD26CEB | E9 BE2CFDFF | jmp d2game.6FCF99AE | jump back to the vanilla code
One last one: the boni you assign via aurastat or passivestat are not displayed on the client (think of resists, for example) but even if you don't literally see them, they are there, so don't worry about that.
Also, srvDoFunc 49 skips assigning boni to the minions if your skill level is lesser or equal to 1. In order to fix this you need to change the following code
Code: Select all
6FCF988C | 83FB 01 | cmp ebx,1 |
6FCF988F | 0F8E 70010000 | jle d2game.6FCF9A05 | if sLvl is lesser or equal to 1 , skip boni
Code: Select all
6FCF988C | 83FB 00 | cmp ebx,0 |
6FCF988F | 0F8E 70010000 | jle d2game.6FCF9A05 | if sLvl is lesser or equal to 0 , skip boni