Need Party Exp formula

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

0
No votes
 
Total votes: 0

lolet
Posts: 95
Joined: Sat Sep 04, 2010 8:43 pm

Need Party Exp formula

Post by lolet » Sat Jun 04, 2011 8:33 pm

Okay, i've reworked whole party share exp function, but i cant disasm right formula of experience.Damn MMX funcs! Atm i have:

Code: Select all

	PartyExp hPartyExp;
	::memset(&hPartyExp,0,sizeof(hPartyExp));
	hPartyExp.pMonster = pMonster;
	D2GAME_ForEachInParty(pPlayer,pGame,(void (__fastcall*)(Game*,UnitAny*,void*))&ExpCallback,&hPartyExp);
	if(hPartyExp.nMembers > 0)
	{
		if(hPartyExp.LvlSum > 0)
		{
			if(hPartyExp.nMembers == 1)
			{
				int ExpGained = D2GAME_GetExpGained(PlayerExp,pPlayer,PlayerLvl,pGame,MonsterLvl);
				AddExp(pGame,pPlayer,ExpGained,PlayerLvl);	
			}
			else
			{
				double PExp = (double)(PlayerExp + 89 * PlayerExp * (hPartyExp.nMembers - 1)) / 256;
				PExp = PExp / hPartyExp.LvlSum;

				for(int i = 0; i<hPartyExp.nMembers; ++i)
				{
					int PLvl = hPartyExp.PartyLevels[i];
					UnitAny* pMember = hPartyExp.pPartyMembers[i];
					int ExpGained = D2GAME_GetExpGained(round(hPartyExp.PartyLevels[i] * PExp),pMember,PLvl,pGame,MonsterLvl);
					AddExp(pGame,pMember,ExpGained,PLvl);
				}
			}
		}
	}
I'm not sure at

Code: Select all

double PExp = (double)(PlayerExp + 89 * PlayerExp * (hPartyExp.nMembers - 1)) / 256;
After party up it calculates too low experience in my tests, i think i missed some argument in formula above. Anyone know the proper formula?

User avatar
Necrolis
Senior Admin
Throne
Posts: 9125
Joined: Sat Mar 25, 2006 1:22 pm
Location: The Land of the Dead
South Africa

Hand-picked

Re: Need Party Exp formula

Post by Necrolis » Sat Jun 04, 2011 11:05 pm

there is no MMX code in the calc (in fact D2 has NO MMX or any form of SIMD in it at all).

anyways, seeing as you don't give a version, this is from the 1.10 code:

The code in the calc is pretty retarded anyways, it loads a int values for the floating point calcs, which is an expensive op, anyways.

the whole calc boils down to (this uses floats btw, NOT doubles, and most of the operands are ints, which means the base was loaded as a float then multiplied or divided by integers):

Code: Select all

(((abs(((nPartyMembers - 1) * nExp) * 79) / 256) + nExp) / nTotalPartyLevel) * nCurrentPartyMemberLevel
the abs is unneeded unless you have negative exp gain, dunno why D2 even bothered with it...

version to make the casting clearer (all inputs are integers):

Code: Select all

float fBase = float((abs(((nPartyMembers - 1) * nExp) * 79) / 256) + nExp) / float(nTotalPartyLevel);
int nGain = int(fBase * float(nCurrentPartyMemberLevel));
Image
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal

lolet
Posts: 95
Joined: Sat Sep 04, 2010 8:43 pm

Re: Need Party Exp formula

Post by lolet » Mon Jun 06, 2011 1:27 am

Yes you're right about MMX, i wrote because i had seen a function calling IsProcessorFeaturePresent and i thought its checks if MMX is available but it checks PF_FLOATING_POINT_PRECISION_ERRATA.
Thanks a lot for reply, but are you sure it multiplies by 79? I work on 1.11b and there is

Code: Select all

PartyExp_6FC9DFD0+84                   imul    eax, esi
PartyExp_6FC9DFD0+87                   imul    eax, 59h
I don't think the code has changed since 1.10 :P

I have tested your formula and exp is still too low. When I exp in party I get 1/3 of exp which I would gain out of party (8 players, every char has 90 lvl). I don't know is it a big difference if you exp 1/8 in vanilla?

User avatar
Necrolis
Senior Admin
Throne
Posts: 9125
Joined: Sat Mar 25, 2006 1:22 pm
Location: The Land of the Dead
South Africa

Hand-picked

Re: Need Party Exp formula

Post by Necrolis » Mon Jun 06, 2011 8:20 am

lolet" wrote:Yes you're right about MMX, i wrote because i had seen a function calling IsProcessorFeaturePresent and i thought its checks if MMX is available but it checks PF_FLOATING_POINT_PRECISION_ERRATA.
Thanks a lot for reply, but are you sure it multiplies by 79? I work on 1.11b and there is

Code: Select all

PartyExp_6FC9DFD0+84                   imul    eax, esi
PartyExp_6FC9DFD0+87                   imul    eax, 59h
I don't think the code has changed since 1.10 :P
yip, you'd be right, forgot about an extra multiplier early on:

Code: Select all

6FCC2E1A                                                             |.  0FAFCE                                                IMUL ECX,ESI                                    ;  nExp * (nPlayers - 1)
6FCC2E1D                                                             |.  8D0489                                                LEA EAX,DWORD PTR DS:[ECX+ECX*4]                ;  (nExp * (nPlayers - 1)) * 5
6FCC2E20                                                             |.  8D04C0                                                LEA EAX,DWORD PTR DS:[EAX+EAX*8]                ;  ((nExp * nPlayers) - 1) * 45
6FCC2E23                                                             |.  03C0                                                  ADD EAX,EAX                                     ;  ((nExp * nPlayers) - 1) * 90
6FCC2E25                                                             |.  2BC1                                                  SUB EAX,ECX                                     ;  ((nExp * nPlayers) - 1) * 89
I have tested your formula and exp is still too low. When I exp in party I get 1/3 of exp which I would gain out of party (8 players, every char has 90 lvl). I don't know is it a big difference if you exp 1/8 in vanilla?
you sure its cause your not messing up the percentage boni increases or something in D2GAME_GetExpGained? though IMO, just replaced D2's formula, its terrible, changed it to something way more simple.

Code: Select all

/* 
	Date: Tue Dec 08 08:26:20 2009
	Author: Necrolis
	Function: EXPERIENCE_CalculateDecay
	Address:
	Comments:
*/

int __fastcall EXPERIENCE_CalculateDecay(int nAttackerLevel, int nDefenderLevel)
{
	if(nAttackerLevel == nDefenderLevel || nAttackerLevel == 1)
		return 100;

	int nDifferance = nAttackerLevel - nDefenderLevel;
	if(nDifferance < EXPERIENCE_DECAY_START)
		return 100;

	return (nDifferance > 100 / EXPERIENCE_DECAY_AMOUNT) ? 0 : 100 - (nDifferance * EXPERIENCE_DECAY_AMOUNT);	
}

/* 
	Date: Thu May 28 10:42:34 2009
	Author: Necrolis
	Function: EXPERIENCE_Calculate
	Address: D2Game.0x6FCC2EC0
	Comments: Highly Different
*/

DWORD __fastcall EXPERIENCE_Calculate(D2GameStrc* pGame, D2UnitStrc* pAttacker, int nAttackerLevel, int nDefenderLevel, DWORD dwExp)
{
	if(pGame == NULL || pAttacker == NULL || nAttackerLevel < 1 || nDefenderLevel < 1 || dwExp == 0)
		return EXPERIENCE_MIN_GAIN;

	if(nAttackerLevel >= PLAYERS_GetMaxLevel(pAttacker))
		return EXPERIENCE_MIN_GAIN;

	int nRatio = PLAYERS_GetExperienceRatio(pAttacker,nAttackerLevel);
	dwExp = INLINE_ApplyPercent(dwExp,100,EXPERIENCE_CalculateDecay(nAttackerLevel,nDefenderLevel));
	return EXPERIENCE_Normalize((dwExp * nRatio) / 1024);
}
though ATM I give party members the full share of the exp that the killer gains, only adjusted for their level vs the defender level, gonna probably add a distance based decay to it when I revise it some time in the future
Image
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal

lolet
Posts: 95
Joined: Sat Sep 04, 2010 8:43 pm

Re: Need Party Exp formula

Post by lolet » Mon Jun 06, 2011 4:34 pm

Okay i found the error. This whole formula is {filtered}. I changed

Code: Select all

float fBase = float((abs(((nPartyMembers - 1) * nExp) * 79) / 256) + nExp) / float(nTotalPartyLevel);
to
float fBase = float((abs((nPartyMembers - 1) * nExp) + nExp) / float(nTotalPartyLevel);
and it finally works like i wanted to. Just look at diagram
Image

User avatar
misiek1294
Junior Member
Paladin
Posts: 168
Joined: Mon Dec 29, 2014 3:58 pm
Poland

Re: Need Party Exp formula

Post by misiek1294 » Sat Oct 14, 2017 8:30 pm

Hey !
Someone can share me info about PartyExp struct ?
Thanks !

User avatar
kidpaddle94
Forum Legend
Principality
Posts: 2057
Joined: Thu Aug 13, 2009 2:54 pm
Location: localhost
Canada

Re: Need Party Exp formula

Post by kidpaddle94 » Sat Oct 14, 2017 11:27 pm

misiek1294" wrote:Hey !
Someone can share me info about PartyExp struct ?
Thanks !
lolet sent me the definition of this struct some time ago in another context, here it is:

Code: Select all

struct PartyExp
{
   Unit* pMonster;
   Unit* pPartyMembers[8];
   int nPartyLevels[8];
   int nMembers;
   int nLvlSum;
};

User avatar
misiek1294
Junior Member
Paladin
Posts: 168
Joined: Mon Dec 29, 2014 3:58 pm
Poland

Re: Need Party Exp formula

Post by misiek1294 » Sun Oct 15, 2017 8:36 am

Thanks alot Kidpaddle94 You are save me alot of the time :D !

User avatar
thaison
Junior Member
Paladin
Posts: 108
Joined: Fri Apr 03, 2015 11:59 am
Location: Viet Nam
Vietnam

Re: Need Party Exp formula

Post by thaison » Tue Oct 24, 2017 1:10 am

Hey!
who can give me little information about this function.
Thanks!

Code: Select all

D2GAME_GetExpGained

User avatar
Necrolis
Senior Admin
Throne
Posts: 9125
Joined: Sat Mar 25, 2006 1:22 pm
Location: The Land of the Dead
South Africa

Hand-picked

Re: Need Party Exp formula

Post by Necrolis » Tue Oct 24, 2017 10:29 am

Its the same function lolet and I posted assembly listings of:

Code: Select all

/* 
	Date: Thu May 28 10:42:34 2009
	Author: Necrolis
	Function: EXPERIENCE_Calculate
	Address: D2Game.0x6FCC2EC0
	Comments: Highly Different
*/

DWORD __fastcall EXPERIENCE_Calculate(D2GameStrc* pGame, D2UnitStrc* pAttacker, int nAttackerLevel, int nDefenderLevel, DWORD dwExp)
Image
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal

User avatar
misiek1294
Junior Member
Paladin
Posts: 168
Joined: Mon Dec 29, 2014 3:58 pm
Poland

Re: Need Party Exp formula

Post by misiek1294 » Tue Oct 24, 2017 3:12 pm

Hey ,
Necrolis maybe You can share some more info about Your exp functions?
I think your way to exp share will be much more clear then oryginal :D

Code: Select all

 
PLAYERS_GetExperienceRatio,
   INLINE_ApplyPercent,
EXPERIENCE_Normalize,
EXPERIENCE_DECAY_START,
  EXPERIENCE_DECAY_AMOUNT 
 
Thanks!

User avatar
Necrolis
Senior Admin
Throne
Posts: 9125
Joined: Sat Mar 25, 2006 1:22 pm
Location: The Land of the Dead
South Africa

Hand-picked

Re: Need Party Exp formula

Post by Necrolis » Tue Oct 24, 2017 5:11 pm

Sure, but its rather simple.
EXPERIENCE_Normalize just bounds the gain between a min and max value.
PLAYERS_GetExperienceRatio just gets the exp ratio from experience.txt
INLINE_ApplyPercent just increases/decreases a value by a percentage.
And the constants:

Code: Select all

#define EXPERIENCE_MAX_GAIN 0x7FFFFF
#define EXPERIENCE_MIN_GAIN 1
#define EXPERIENCE_DECAY_START 6
#define EXPERIENCE_DECAY_AMOUNT 10
Image
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal

Return to “Code Editing”