Miscellaneous Forums > Scripting and Reverse Engineering
[FF8] Monster stats and level formulas
JWP:
looking at the code:
--- Code: ---0048BD33 |. 8A57 1B MOV DL,BYTE PTR DS:[EDI+1B] //dl = d
0048BD36 |. 8886 CB7BD201 MOV BYTE PTR DS:[ESI+1D27BCB],AL //line not used in calculation
0048BD3C |. 33C0 XOR EAX,EAX //eax = 0
0048BD3E |. 33C9 XOR ECX,ECX //ecx = 0
0048BD40 |. 8D1492 LEA EDX,[EDX*4+EDX] //edx = d*5
0048BD43 |. 8A47 18 MOV AL,BYTE PTR DS:[EDI+18] al = a
0048BD46 |. 8A8E CC7BD201 MOV CL,BYTE PTR DS:[ESI+1D27BCC] //cl = lvl
0048BD4C |. 8D2C92 LEA EBP,[EDX*4+EDX] //ebp = d*25
0048BD4F |. 33D2 XOR EDX,EDX //edx = 0
0048BD51 |. 8A57 19 MOV DL,BYTE PTR DS:[EDI+19] //dl = b
0048BD54 |. 8D14AA LEA EDX,[EBP*4+EDX] //edx = 100*d + b
0048BD57 |. 8D2C92 LEA EBP,[EDX*4+EDX] //ebp = 500*d + 5*b
0048BD5A |. 33D2 XOR EDX,EDX //edx = 0
0048BD5C |. 8A57 1A MOV DL,BYTE PTR DS:[EDI+1A] //dl = c
0048BD5F |. 8D1492 LEA EDX,[EDX*4+EDX] //edx = c*5
0048BD62 |. 8D1492 LEA EDX,[EDX*4+EDX] //edx = c*25
0048BD65 |. 8D1490 LEA EDX,[EDX*4+EAX] //edx = c*100 + a
0048BD68 |. 0FAFC1 IMUL EAX,ECX //eax = a*lvl
0048BD6B |. 0FAFC1 IMUL EAX,ECX //eax = a*lvl*lvl
0048BD6E |. 0FAFD1 IMUL EDX,ECX //edx = (c*100 + a)*lvl
0048BD71 |. 8BC8 MOV ECX,EAX //ecx = a*lvl*lvl
0048BD73 |. B8 67666666 MOV EAX,66666667 //eax = 0x66666667
0048BD78 |. 8D2C6A LEA EBP,[EBP*2+EDX] //ebp = 1000*d + 10*b + (c*100 + a)*lvl
0048BD7B |. F7E9 IMUL ECX //edx:eax = (a*lvl*lvl)*0x66666667
0048BD7D |. C1FA 03 SAR EDX,3 //edx = floor((a*lvl*lvl)*0x66666667/2^35)
0048BD80 |. 8BC2 MOV EAX,EDX //eax = floor((a*lvl*lvl)*0x66666667/2^35)
0048BD82 |. 03D5 ADD EDX,EBP //edx = floor((a*lvl*lvl)*0x66666667/2^35) + 1000*d + 10*b + (c*100 + a)*lvl
0048BD84 |. C1E8 1F SHR EAX,1F //add 1 if the result was negative (this isn't going to happen, it's probably due to them putting the result in a signed int)
0048BD87 |. 03C2 ADD EAX,EDX
--- End code ---
Think this gives:
HP = floor(a*lvl*lvl/20) + 1000*d + 10*b + (c*100 + a)*lvl
or if you're using integers:
(a*lvl*lvl)/20 + 1000*d + 10*b + (c*100 + a)*lvl
This looks like it matches with what you have and also the formula I gave several years ago in this post: http://forums.qhimm.com/index.php?topic=6961.msg86799#msg86799
--- Quote ---BYTE HP[4]; //HP = (HP[0]*x*x)/20 + (HP[0] + 100*HP[2])*x + 10*HP[1] + 1000*HP[3], where x = monster lvl
--- End quote ---
You mentioned MAG twice in your post, did you mean VIT/SPR/SPD/EVA?
myst6re:
--- Quote from: JWP on 2016-04-17 23:52:49 ---You mentioned MAG twice in your post, did you mean VIT/SPR/SPD/EVA?
--- End quote ---
Yes, sorry for the confusion, and I fixed this on the wiki page yesterday.
So for the PC version, we're sure that is the right formula :) . It would be good to know if the PS version shares the same formulas.
JWP:
Ah nice :), I should probably see about getting a wiki account rather than just dumping info all over the forum :-P.
I'm curious as to what project you're using the formulas for :-P.
I'd guess that the original PS game was written in C/C++ and they copied functions like that for the PC version but I could be wrong.
I'm tempted to take a look at the PS version to see if some of the data structures in memory are similar and it might be easier to find information with snapshotting.
In addition to this, seeing the same routines in 2 different ASM implementations might help with reverse engineering.
PSX looks like it has a pretty good R3000 debugger to do that sort of thing.
While looking through the forums for FF8 posts (to see if there was anything I didn't know), I came across this old post: http://forums.qhimm.com/index.php?topic=3723.msg51764#msg51764
It seems that people have looked through the section of code before - although I think their interpretation is slightly off since there aren't enough brackets - divisions end up taking priority, which causes different results when using integer division:
--- Code: ---4*4/3 = 4 * floor(4/3) = 4
(4*4)/3 = floor(16/3) = 5
--- End code ---
Note the division order doesn't actually make a difference due to the nested division property mentioned below:
--- Code: ---floor(floor(x/y)/z) = floor(x/(y*z)) = floor(x/(z*y)) = floor(floor(x/z)/y)
--- End code ---
So many things just seem to get lost in time on this forum :(.
btw, I noticed that the STR/MAG formula can be simplified slightly due to this property:
https://en.wikipedia.org/wiki/Floor_and_ceiling_functions#Nested_divisions
it might be possible to simplify it further but I'm not too familiar with that sort of mathematics.
--- Code: ---floor((floor(level * a/10) + floor(level / b) - floor(level * level / d / 2) + c)/4)
--- End code ---
myst6re:
--- Quote from: JWP on 2016-04-19 10:23:49 ---I'm curious as to what project you're using the formulas for :-P.
--- End quote ---
A french website that will become the FF8 reference guide.
I removed nested floors, it works well :)
For now, Iron Giant is the only monster I know with errors, according to the Ultimania, maybe the error isn't on our side...
--- Code: ---Values : 30, 0, 6, 0
Level Ultimania Known formula
LV1 663 HP 631 HP
LV10 6900 HP 6450 HP
LV20 14400 HP 13200 HP
LV30 22500 HP 20250 HP
LV40 31200 HP 27600 HP
LV50 40500 HP 35250 HP
LV60 50400 HP 43200 HP
LV70 60900 HP 51450 HP
LV80 72000 HP 60000 HP
LV90 83700 HP 68850 HP
LV100 96000 HP 78000 HP
--- End code ---
There is nothing special about Iron Giant HPs on IA scripts.
JWP:
I forced a battle against a lvl 20 Iron Giant by using encounter code 248 (8420 when entering it) in the debug room and memory editing the level just after it loaded using a memory breakpoint.
It had 13200 HP so either it's an issue with the guide or the guide is based on a different version of the game.
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version