### Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

### Messages - JWP

Pages: [1] 2 3 ... 8
1
##### Scripting and Reverse Engineering / Re: [FF8] Camera Research / reconstruction
« on: 2019-06-26 17:53:55 »
A lot of the camera animations are read using this, I'm not sure if it also applies to the field camera:
http://forums.qhimm.com/index.php?topic=15906.msg261844#msg261844
might help with some of the structure analysis.

2
##### Scripting and Reverse Engineering / Re: FF8 correct HP formula?
« on: 2019-05-10 16:50:00 »
Seems fine to me.
Code: [Select]
`default for Squall:_HP[0] = 44_HP[1] = 255_HP[2] = 179((magic_J_val * magic_count + stat_bonus + lvl * _HP[0] - (10 * lvl ^ 2) / _HP[1] + _HP[2]) * percent_mod) / 100;part1 = magic_J_val * magic_count + stat_bonus = 0part2 = lvl * _HP[0] = 8 * 44 = 352part3 = (10 * lvl ^ 2) / _HP[1] = (10 * 64)/255 = 640/255 = 2 (truncated because of integer arithmetic)percent_mod = 100((0 + 352 - 2 + 179)*100)/100 = 529`

3
##### Scripting and Reverse Engineering / Re: FF8 correct HP formula?
« on: 2019-05-10 08:34:31 »
I can tell you that the game uses integers and there's a little more info here: http://forums.qhimm.com/index.php?topic=16923.msg240609#msg240609

I can take another look when I get some time.

4
##### Scripting and Reverse Engineering / Re: [FF8] Ability data and Angel Wing mechanics
« on: 2019-05-08 20:03:22 »
Sure, here you go:
Code: [Select]
`0x483D67 - does the lookupfrom: 8D 0C C5 00 00 00 00 BA 20 00 00 00 2B C8 B3 40 8D 34 88 C1 E6 04 81 C6 00 F0 CF 01 33 FF 8D 8E 82to:   E8 B4 B2 00 00 25 FF 00 00 00 31 DB 31 C9 31 D2 8A 9A 88 3D 48 00 01 D9 42 39 C1 7E F3 B3 40 EB 700x483D88 - spell tablefrom:00 00 00 8A 01 84 C0 74 11 25FF 00 00 00 6B C0 3C 84 98 6E40 CF 01 74 01 47 83 C1 05 4A75 E3 85 FF 75 07 B8 FF 00 0000 EB 47 E8 68 B2 00 00 25 FF00 00 00 8B C8 81 to:00 00 0B 00 00 0B 00 00 0A 0600 06 06 30 30 10 20 20 12 0000 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 0000 00 00 00 06 00 00 00 06 0000 00 00 00 00 000x483DC0 - tests for angel wing and skips inventory check if truefrom: E1 1F 00 00 80 79 05 49 83 C9 E0 41 8D 54 8E 68 8A 44 11 1A 84 C0 74 10 25 FF 00 00 00 6B C0 3Cto:   05 82 F0 CF 01 8D 2C 52 8D 2C AA C1 E5 04 F6 85 1B 7B D2 01 02 0f 85 65 9A 00 00 E9 27 9A 00 000x48D802 - jumps to angel wing test from start of inventory checkfrom: 05 82 F0 CF 01to:   E9 B9 65 FF FF`
You'll likely run into an issue with the memory offset for the lookup table in the code being wrong (the "88 3D 48 00" bytes in the first section), I think the rest is relative, so you might be all right with the jumps.

5
##### FF8 Gameplay Releases / Re: [FF8PC - Steam] New Threat Mod (v0.3)
« on: 2019-05-02 18:19:45 »
I think it's using Level instead of stock; so to get the full stat boost from a junctioned spell the character needs to be lv.100.
Correct, normally the boost is (magic_amount * stat_boost)/100 but the patches just cause it to use level instead of the magic amount.

6
##### Scripting and Reverse Engineering / Re: [FF8] Ability data and Angel Wing mechanics
« on: 2019-03-18 14:33:43 »
As far as I'm aware, no. The most reliable source is: https://gamefaqs.gamespot.com/ps/197343-final-fantasy-viii/faqs/58936 as it looks like it was compiled from reverse engineering.
I'd probably give Rinoa a 1/256 chance of casting "The End" for entertainment .

7
##### Scripting and Reverse Engineering / Re: [FF8] Ability data and Angel Wing mechanics
« on: 2019-03-17 22:41:13 »
Good idea but it didn't seem to work.
Selphie's slots uses attack type 0x10 instead of 0x02 (Magic), I tried changing the attack type and it cast the spell successfully but it soft locked after it finished .
You can change the numbers but just make sure they add up to 256 or there's a chance that the game could load an invalid spell.

Also you don't actually need that jump patch since the condition is never true anyway.

If you're curious, the patched code looks like this:

Code: [Select]
`00483D67 | E8 B4B20000              | call <ff8_en.battle_random_number>                              | eax = random number [0..255]00483D6C | 25 FF000000              | and eax,FF                                                      |00483D71 | 31DB                     | xor ebx,ebx                                                     | ebx = 000483D73 | 31C9                     | xor ecx,ecx                                                     | ecx = 0 - used to store running total00483D75 | 31D2                     | xor edx,edx                                                     | edx = 0 - used to store magic idlabel:00483D77 | 8A9A 883D4800            | mov bl,byte ptr ds:[edx+483D88]                                 | load byte from table to bl (ebx)00483D7D | 01D9                     | add ecx,ebx                                                     | add byte from table to running total00483D7F | 42                       | inc edx                                                         |00483D80 | 39C1                     | cmp ecx,eax                                                     |00483D82 | 7E F3                    | jle ff8_en.483D77                                               | jump to label if total <= random number00483D84 | B3 40                    | mov bl,40                                                       | bl is used later to test targeting00483D86 | EB 70                    | jmp ff8_en.483DF8                                               | jump past table to resume testing targeting stuff`
IMPORTANT NOTE: there might be a bug where the total doesn't get to 256 because it's adding to dl rather than (e)dx, I'll have to investigate it.
EDIT: I've fixed the patch in the previous post - the spell table also had to move
EDIT1: Proper test for angel wing has been added to skip the inventory check - see previous post.

8
##### Scripting and Reverse Engineering / Re: [FF8] Ability data and Angel Wing mechanics
« on: 2019-03-17 22:07:23 »
From your post, it looks like you want the following weightings:
Code: [Select]
`Firaga - 11Blizzaga - 11Thundaga - 10Water - 6Bio - 6Pain - 6Meltdown - 6Demi - 6Tornado - 32Quake - 32Flare - 48Holy - 48Meteor - 16Ultima - 18`
here is a patch that should do the trick:
Code: [Select]
`0x483D67 - does the lookupE8 B4 B2 00 00 25 FF 00 00 00 31 DB 31 C9 31 D2 8A 9A 88 3D 48 00 01 D9 42 39 C1 7E F3 B3 40 EB 700x483D88 - spell table00 00 0B 00 00 0B 00 00 0A 0600 06 06 30 30 10 20 20 12 0000 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 0000 00 00 00 06 00 00 00 06 0000 00 00 00 00 000x483DC0 - tests for angel wing and skips inventory check if true05 82 F0 CF 01 8D 2C 52 8D 2C AA C1 E5 04 F6 85 1B 7B D2 01 02 0f 85 65 9A 00 00 E9 27 9A 00 000x48D802 - jumps to angel wing test from start of inventory checkE9 B9 65 FF FF`
not 100% sure I got the table right but give it a shot.

9
##### Scripting and Reverse Engineering / Re: [FF8] Ability data and Angel Wing mechanics
« on: 2019-03-17 21:09:48 »
Hmm... so I've managed to get a patch table working as expected, the only problem is that if Rinoa doesn't have the spell in stock, she jumps forward and the spell name appears but nothing is cast.
There must be some sort of other check elsewhere .

EDIT:
found where it is and did a hacky patch but I'm not sure the best way to fix it.

10
##### Scripting and Reverse Engineering / Re: [FF8] Ability data and Angel Wing mechanics
« on: 2019-03-17 00:56:09 »
I'm not sure where these other places are getting the probabilities from but I see no indication of any magic specific weighting.
The function counts the number of valid magics and if it's not zero, it generates a random number between 0 and 31.
It then selects the magic in this slot, if there is no magic in this slot or the targeting isn't valid, it keeps selecting the next slot until it finds a valid one (and loops around).
This means that if you have a lot of empty magic slots at the end, the first slot ends up being more likely than the others.

It would be possible to create a table of weights for each of the magics but you would either have to make sure that the sum of the weights are <=256 or use a different way of generating random numbers than the one usually used in the battle module.

Easiest way would probably be to make the weights for the 56 spells listed here: https://github.com/alexfilth/doomtrain/wiki/Magic-data
total 256 since it would mean you wouldn't have to worry about evening the outcomes and I could probably whip a patch up if you came up with a table.

11
##### Scripting and Reverse Engineering / Re: [FF8] Ability data and Angel Wing mechanics
« on: 2019-03-16 15:33:23 »
The spell used under Angel Wing is decided in function 0x483D60.

12
##### FF8 Gameplay Releases / Re: [FF8PC - Steam] New Threat Mod (v0.3)
« on: 2019-03-16 10:28:17 »
If you want them based on level, the following patches should do the trick:

Code: [Select]
`#HP963CB = 8A 5C 24 14 90 90 90#Primary Stats966E5 = 8A 54 24 1C 90 90 90#Speed & Luck96788 = 8A 54 24 1C 90 90 90#Hit9688E = 8B 4C 24 04 31 C0 8A 81 B8 01 00 00#EVA9691C = 8B 4C 24 04 31 C0 8A 81 B8 01 00 00#Elemental Attack969CC = 8B 4C 24 04 31 C0 8A 81 B8 01 00 00#Elemental Defence96AA9 = 8B 44 24 04 31 C9 8A 88 B8 01 00 00#Status Attack96BBC = 8B 4C 24 04 31 C0 8A 81 B8 01 00 00#Status Defence96C98 = 8B 44 24 04 31 C9 8A 88 B8 01 00 00`

13
##### FF8 Tools / Re: [PSX/PC] Field editor - Deling (0.9.1b)
« on: 2019-03-04 10:07:38 »
The dialog for the characters in battle is in a different set of files (.dat files) and there isn't currently a tool to edit them as far as I'm aware.
I'm currently modifying Ifrit to be able to edit them along with the battle AI.

14
##### Scripting and Reverse Engineering / Re: ff8 monsters : .dat files analysis
« on: 2019-03-03 02:06:21 »
What I said seems to match up to the position data stuff, I haven't looked deep enough into it yet to comment about the other stuff.

15
##### Scripting and Reverse Engineering / Re: ff8 monsters : .dat files analysis
« on: 2019-03-03 00:47:50 »

What I've figured out so far is as follows:
The first byte is the number of frames as shown on the wiki.
The main function that reads the dat animation data looks to be at 0x00508F90.
There's a fixed array at 0xB8B9F0 of 4 bytes to help with uncompressing bits.
byte[] uncompress_helper = { 0x03, 0x06, 0x09, 0x10 }
There are 2 types of reads that are done on the animation data, bit reads and compressed bit reads.

there's a structure in memory used to parse the data that looks like:
BYTE* current_animation_byte;
int current_bit_position;
}

for bit reads, the following takes place:
int temp = *(current_position + 2) << 12 | *(current_position + 1) << 8 | *current_position //essentially reads 3 bytes in little-endian format
short value = (temp >> current_bit_position) & ~(0xFFFFFFFF << bitsToRead)
value = (value << (16 - bitsToRead)) >> bitsToRead //This looks odd but it's done as an arithmetic right shift to sign extend the bits

current_animation_byte += (bitsToRead + current_bit_position) / 8 // increases pointer by number of bytes read
current_bit_position = (bitsToRead + current_bit_position) % 8 // sets the position in the next byte to read from

For reading compressed bits, the following happens:
2 bits are read and this is used as an index with the fixed array above i.e.
0 -> 0x03
1 -> 0x06
2 -> 0x09
3 -> 0x10

Then this amount of bits are read and sign extended as above.
The function for compressed bit reads is at 0x00509320
The function for standard bit reads is at 0x005092A0
All offsets are for the English Steam version

16
##### Scripting and Reverse Engineering / Re: [FF8] .x battle fields
« on: 2019-02-18 13:49:56 »
The structure that the camera animation is loaded into looks like:
Code: [Select]
`struct CameraStruct { BYTE unkbyte000; //000 BYTE unkbyte001; //001 keyframe count? WORD control_word; //002 WORD unkword004; //004 WORD unkword006; //006 WORD unkword008; //008 WORD unkword00A; //00A WORD unkword00C; //00C WORD unkword00E; //00E total frame count/time? BYTE unk[20] //010 short unkword024[32]; //024 - start frames for each key frame? short unkword064[32]; //064 short unkword0A4[32]; //0A4 short unkword0E4[32]; //0E4 BYTE unkbyte124[32]; //124 short unkword144[32]; //144 short unkword184[32]; //184 short unkword1C4[32]; //1C4 BYTE unkbyte204[32]; //204 BYTE unkbyte224[128]; //224 BYTE unkbyte2A4[128]; //2A4 BYTE unkbyte324[128]; //324 BYTE unkbyte3A4[128]; //3A4 BYTE unkbyte424[128]; //424 BYTE unkbyte4A4[128]; //4A4};`and the function that parses the animation into it looks something like:
Code: [Select]
`short* parse_camera(short* camera_data, CameraStruct* cam) { short* local2C; BYTE keyframecount; WORD totalframecount; short* local1C; short* local18; short* local14; short* local10; short* current_position = camera_data; if (*current_position == 0xFFFF) { return NULL; } cam->control_word = *current_position; current_position++; totalframecount = 0; keyframecount = 0; switch ((cam->control_word >> 6) & 3) { case 1: cam->unkword004 = 0x200; cam->unkword006 = 0x200; break; case 2: cam->unkword004 = *current_position; cam->unkword006 = *current_position; current_position++; break; case 3: cam->unkword004 = *current_position++; cam->unkword006 = *current_position++; break; } switch ((cam->control_word >> 8) & 3) { case 0: cam->unkword008 = ff8vars.unkword1D977A2; cam->unkword00A = ff8vars.unkword1D977A2; break; case 1: cam->unkword008 = 0; cam->unkword00A = 0; break; case 2: cam->unkword008 = *current_position; cam->unkword00A = *current_position; current_position++; break; case 3: cam->unkword008 = *current_position++; cam->unkword00A = *current_position++; break; } switch (cam->control_word & 1) { case 0: if (*current_position >= 0) { do { cam->unkword024[keyframecount] = totalframecount; totalframecount += *current_position++ * 16; cam->unkbyte124[keyframecount] = *current_position++; cam->unkword064[keyframecount] = *current_position++; cam->unkword0A4[keyframecount] = *current_position++; cam->unkword0E4[keyframecount] = *current_position++; cam->unkbyte204[keyframecount] = *current_position++; cam->unkword144[keyframecount] = *current_position++; cam->unkword184[keyframecount] = *current_position++; cam->unkword1C4[keyframecount] = *current_position++; keyframecount++; } while (*current_position >= 0); if (keyframecount > 2) { ff8funcs.Sub50D010(cam->unkword024, cam->unkword064, cam->unkword0A4, cam->unkword0E4, keyframecount, cam->unkbyte224, cam->unkbyte2A4, cam->unkbyte324); ff8funcs.Sub50D010(cam->unkword024, cam->unkword144, cam->unkword184, cam->unkword1C4, keyframecount, cam->unkbyte3A4, cam->unkbyte424, cam->unkbyte4A4); } } break; case 1: if (*current_position >= 0) { local14 = current_position + 5; local10 = current_position + 6; local2C = current_position + 7; local18 = current_position + 1; local1C = current_position + 2; short* ebx = current_position + 3; do { cam->unkword024[keyframecount] = totalframecount; totalframecount += *current_position++ * 16; ff8funcs.Sub503AE0(++local18, ++local1C, ++ebx, *(BYTE*)current_position, &cam->unkword064[keyframecount], &cam->unkword0A4[keyframecount], &cam->unkword0E4[keyframecount]); ff8funcs.Sub503AE0(++local14, ++local10, ++local2C, *(BYTE*)(current_position + 4), &cam->unkword144[keyframecount], &cam->unkword184[keyframecount], &cam->unkword1C4[keyframecount]); cam->unkbyte204[keyframecount] = 0xFB; cam->unkbyte124[keyframecount] = 0xFB; local1C += 8; local18 += 8; current_position += 8; local2C += 8; ebx += 8; local10 += 8; local14 += 8; keyframecount++; } while (*current_position >= 0); if (keyframecount > 2) { ff8funcs.Sub50D010(cam->unkword024, cam->unkword064, cam->unkword0A4, cam->unkword0E4, keyframecount, cam->unkbyte224, cam->unkbyte2A4, cam->unkbyte324); ff8funcs.Sub50D010(cam->unkword024, cam->unkword144, cam->unkword184, cam->unkword1C4, keyframecount, cam->unkbyte3A4, cam->unkbyte424, cam->unkbyte4A4); } } break; } if ((cam->control_word & 0x3E) == 0x1E) { ff8funcs.Sub503300(); } cam->unkbyte001 = keyframecount; cam->unkword00E = totalframecount; cam->unkword00C = 0; return current_position + 1;}`
The size of the animation depends a lot on the control word and the amount of keyframes.
I haven't verified the code completely but it should be roughly correct with some possible minor errors.

17
##### Gameplay Modding / Re: [FFVIII-PCSteam] Enemy AI?
« on: 2018-08-10 17:11:27 »
There's a beta version of Ifrit that has been modified to make it possible to view/edit AI but note that it is pretty buggy at present.
see here

18
##### Gameplay Modding / Re: [FFVIII-PCSteam] Ifrit: Some questions about the program
« on: 2018-07-19 18:09:49 »
Heh, I really need to get around to fixing it but the whole AI section really needs a rewrite =/.

19
##### Gameplay Modding / Re: [FFVIII-PCSteam] Doomtrain: GF Abilities
« on: 2018-07-13 15:35:08 »
I believe the names are also in kernel.bin but you need a different tool to edit them:
Carbuncle

20
##### Gameplay Modding / Re: [FFVIII-PCSteam] Doomtrain: GF Abilities
« on: 2018-07-12 18:26:34 »
Already learned abilities are stored in the save data and there is a file in partial save game format that is initially loaded when you start a new game (init.out), you would need to edit this file to change it for new games (see this thread) and your current save if is for an existing game (using Hyne for example).
Shuffling the abilities up (so the 2 last ones are blank instead) may fix the odd black skill problem but that's just a guess.

21
##### Scripting and Reverse Engineering / Re: FF8 - Adding New Enemies
« on: 2018-07-01 12:30:04 »
It could also be to do with the constant array of files embedded in the exe:
http://wiki.ffrtt.ru/index.php/FF8/Engine_const/BattleFiles

22
##### Gameplay Modding / Re: Simple Mod idea for Final Fantasy VIII, would it be easy to make?
« on: 2018-04-21 09:28:32 »
Should be easy enough to do if you know how to work with ff8.

The following patches in memory would do it for the English Steam version for stats other than hit or eva:

Code: [Select]
`Address: 0x004966E5From:    8A 14 4D F9 E0 CF 01 To:      8A 54 24 1C 90 90 90`
Code: [Select]
`Address: 0x00496788From:    8A 14 4D F9 E0 CF 01To:      8A 54 24 1C 90 90 90`
Code: [Select]
`Address: 0x004963CBFrom:    8A 1C 45 F9 E0 CF 01To:      8A 5C 24 14 90 90 90`
The way this works is that the following functions:
Code: [Select]
`0x496310: GetCharacterHP (int lvl, int char_id)0x496440: GetCharacterStat (int lvl, int char_id, int stat)`
are called with the character level as a parameter and it's easy to pull this off the stack when it tries to get the value for the junctioned magic amount.

Hit and Eva are calculated in the following functions:
Code: [Select]
`0x4967C0: GetCharacterHit (int char_id)0x4968A0: GetCharacterEva (int char_id, int unk1)`
it's probably possible to change these too but it's more work than I'm willing to do.

23
##### Gameplay Modding / Re: FF VIII How to MOD?
« on: 2017-10-29 19:29:45 »
I updated the file without changing the filename or version numbers.

24
##### Gameplay Modding / Re: FF VIII How to MOD?
« on: 2017-10-29 18:28:24 »
Are you using the fixed version of Ifrit above?

25
##### Gameplay Modding / Re: FF VIII How to MOD?
« on: 2017-10-23 21:43:12 »
that particular error was because it was gfStolen, rather than gfstolen.

Pages: [1] 2 3 ... 8