Author Topic: Change duration of status effects, also make haste time limited  (Read 5948 times)

Tenko Kuugen

  • Public Enemy
  • *
  • Posts: 1416
    • View Profile
    • Twitter
pretty much what the topic says.
any info appreciated.

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Just found this, but don't have it in front of me. :(

I can tell you that there re are 16 bytes involved. Among these are the values 10, 127, 127 in that order and they are for poison, barrier and mbarrier respectively. The last four bytes are all 0, and the byte after these is a 10.

Starting with this ten are another set of 16 bytes that indicate which status the timings are for. The first one is for stop because it is the tenth bit (starting at zeroth) in the status mask. The fast four bytes in this set are all 255.

Basically, search for 10, 127, 127 in that order in a hex editor and find the set that has four 00s followed by another set of 16 that starts with 0Ah and ends in FF FF FF FF. If you can't find it by the time I update this post with exact addresses tomorrow....then just...wait...until......I do that.........

cloudiar

  • *
  • Posts: 202
    • View Profile
Quote
Just found this, but don't have it in front of me. :(

I can tell you that there re are 16 bytes involved. Among these are the values 10, 127, 127 in that order and they are for poison, barrier and mbarrier respectively. The last four bytes are all 0, and the byte after these is a 10.

Starting with this ten are another set of 16 bytes that indicate which status the timings are for. The first one is for stop because it is the tenth bit (starting at zeroth) in the status mask. The fast four bytes in this set are all 255.

Basically, search for 10, 127, 127 in that order in a hex editor and find the set that has four 00s followed by another set of 16 that starts with 0Ah and ends in FF FF FF FF. If you can't find it by the time I update this post with exact addresses tomorrow....then just...wait...until......I do that.........


This really what I asked, but took care to ask about my (my English can kill you xD), on the issue, the original system on "haste" or "slow" is Practically cheat! Put temporary effect would be necessary.

If I try to give locations look tomorrow if I see, although I am not an expert like you.

I'll try to help if you give some information, I remind you that thanks to you we can make changes to the computer attributes.

It is another matter, but I want to mention it, also thanks to that talk with my friend, and in the future the community can have program editor "equip stats"!

Is not much, but we want to do something for the community  :roll:

PS: Sorry for english now YES xD
« Last Edit: 2012-10-16 04:09:40 by cloudiar »

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
This is a bad news/good news kind of post.

Bad news: I told you the wrong thing to look for.

Good news: (you're going to like this) The timings for different statuses are located at 0x7B74F0 (0x3B60F0), one byte each, and the statuses they affect are right below them.

Better news: There's room for FOUR MORE and the game WILL RUN THEM!!! It requires three edits for each stat you want to update. So let me give you some technical details on how this works:

First of all, we know there are 12 statuses that are timed in some way.
Stop, Paralyze, Death-Sentence, Slow-Numb, Barrier, MBarrier, Poison, Sleep, Regen, Dual Drain, Shield, and Peerless.
Most of these are temporary as in when they run out they just turn off. There are three exceptions to this: Death-Sentence, Slow-Numb, and Poison.

Death-Sentence:
When its time runs out it causes the omnipresent battle-driver (like an invisible referee from FFTA) to perform the previously-believed-to-be-unused magic 36h from the KERNEL.BIN on the character whose time is up. I used to think this was a debug attack used for testing death animations, but it's actually essential. It looks like "Death", but it can't miss. Since it's a queued action it will wait until the end of the current action/animation before killing the player. So if you're adding Death Force just as the timer reaches 0 then the character won't die.

Slow-Numb:
When the counter is 0 and if the Actor has Slow-Numb status, it removes S-N and adds Petrify. There's no actual action taking place here so it can happen any time even in the middle of an attack where the actor is targeted.

Poison:
This is treated differently than the others. Poison is never actually removed. Instead, its timer counts down and, upon reaching 0, queues the poison attack (built in to the exe) and refills the timer back to 10 (the byte at 0x434DD2/0x0341D2 sets the new timer value). This will continue until the character is either healed or dead.

All others:
Well, you know how they work. Their timers will slowly whittle down for each character before reaching 0 and the status will be removed. It can happen in the middle of an action. So things like Barrier or Regen may turn off at the moment before damage calculation or in the middle of a multi-hit attack.

Now the fun part:
First of all there are three parts to this: The handler, the timer, and the status bit. All three of these are connected to make these work.
As mentioned earlier, the timers are located at 0x7B74F0 (0x3B60F0). When inflicted with said status, they get put into memory for each actor at (0x9A8B10 + 0x10 + 44h * ActorID). These are order-specific and there are 16 bytes for durations, one per status. This might be signed.
The status bits are right below the times at 0x7B7500 (0x3B6100) and use the index of the status they are going to affect. It is in the order I mentioned above. The order of these bytes also determine the order of the value of the timers listed above. Stop has a timer of 30, Paralyze has a timer of 20, and so on.
Now the handlers are located at 0x7C2A58 (0x3C1458) and are stored as DWords to the function that handles them. They're all the same except the ones specifically mentioned above. These are also in the same order as the status bits, but don't alter D.Sentence, SlowNumb, or Poison without moving their handlers around with them.

Now for the really exciting news that I've been building up to. These statuses can be made permanent or more limited based on how you manipulate these three things! Also, there's room for four additional statuses that can be made limited! I agree with cloudiar that Haste and Slow are over-powered because they're permanent. Berserk is a little unfair for being permanent too. In any case, its up to your discretion on what you want to edit. I'll make a tl;dr chart below for easy access to what you need to edit to suit your needs:


Code: [Select]
Status:     Timer Off:  Bit Off:    Handler Off:
Stop        0x7B74F0    0x7B7500    0x7C2A58
Paralyze    0x7B74F1    0x7B7501    0x7C2A5C
D.Sentence  0x7B74F2    0x7B7502    0x7C2A60
SlowNumb    0x7B74F3    0x7B7503    0x7C2A64
Barrier     0x7B74F4    0x7B7504    0x7C2A68
MBarrier    0x7B74F5    0x7B7505    0x7C2A6C
Poison      0x7B74F6    0x7B7506    0x7C2A70
Sleep       0x7B74F7    0x7B7507    0x7C2A74
Regen       0x7B74F8    0x7B7508    0x7C2A78
Drain       0x7B74F9    0x7B7509    0x7C2A7C
Shield      0x7B74FA    0x7B750A    0x7C2A80
Peerless    0x7B74FB    0x7B750B    0x7C2A84
Unused      0x7B74FC    0x7B750C    0x7C2A88
Unused      0x7B74FD    0x7B750D    0x7C2A8C
Unused      0x7B74FE    0x7B750E    0x7C2A90
Unused      0x7B74FF    0x7B750F    0x7C2A94
The handler value for timed statuses is 00434D0A, but since this is in little-endian you'll need to store that backwards like 0A 4D 43 00.

Let's run a few examples:
We now want Haste and Berserk to be limited. So we'll take two of the unused ones and add timings to it as well as indicate which status it will change and the handler that will disable it when the timer runs out:

Code: [Select]
0x7B74FC 0 -> 40h   0x7B750C FFh -> 08   0x7C2A88 00434DE9h -> 00434D0Ah
0x7B74FD 0 -> 40h   0x7B750D FFh -> 17   0x7C2A8C 00434DE9h -> 00434D0Ah

Also, let's make Stop NOT run out.
Code: [Select]
0x7B74F0 1Eh -> ??   0x7B7500 0Ah -> ??   0x7C2A58 00434D0Ah -> 00434DE9hChanging the timer or the status bit won't make a difference, but just to be safe, don't make the status bit higher than 1Fh. The important thing here is to remove the handler for when the timer runs out. There's also the problem that of all playable characters are Stopped that the battle is essentially lost. In FFIX this will end the battle if all are stopped without the enemies having to whittle their HP down to 0. In this case the player will have to wait.

Barrier and MBarrier last too long too:
Code: [Select]
0x7B74F4 7Fh -> 40h
0x7B74F5 7Fh -> 40h
That will halve the time they run.

Sorry the tables are all in virtual addresses, but you can convert them to disk addresses by subtracting 400C00h from each of them.

Tenko Kuugen

  • Public Enemy
  • *
  • Posts: 1416
    • View Profile
    • Twitter
table in .exe addresses coming up
edit: Uh, can it be the converting is a little off? I find the address of 3C1E88 ( which is 7C2A88 minus 400C00 ) at 3C1488 instead. So it looks like the subtraction is 401600? Am I overlooking something simple here?

Okay, for handler offsets I get 401600 as subtraction
for the bit offset, I get 401400
for the timer offset I get also 401400 apparently

sample:
7B74F0 - 401400 = 3B60F0
At 3B60F0 I find this: 1E 14 3C 1E 7F 7F 0A 64 7F 7F 40 40 00 00 00 00 ( fits perfectly with all the status durations. Is this in ticks? I noticed when increasing the battle speed manually or via hext and fps manipulation that these timers run faster too, so it's gotta be ticks? Do we have an actual seconds number for this?

At 7B7500 - 401400 = 3B6100 I find
0A 19 15 0D 10 11 03 02 0F 1B 14 18 FF FF FF FF ( perfect fit again. Matches with http://wiki.qhimm.com/FF7/Battle/Status_Effects )

and finally at 7C2A58 - 401600 = 3C1458 I find
0A 4D 43 00 0A 4D 43 00 46 4D 43 00 5F 4D 43 00 etc ( matches up with your examples )

I have no explanation for this but unless this is something specific to my exe I'll update your tables with the .exe addresses
« Last Edit: 2012-10-16 17:15:52 by Tenko Kuugen »

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Kinda, but not really.

Yes, the offsets seem to be 401600 from that part. For the actual code in the exe, the offset is 400C00. I made the mistake of thinking that offset carried over into static memory. Somewhere between code and the static memory there's a dll injection that my debugger accounted for that separates the offsets a little. I'm not sure where that takes place, though. Looks like you're correct that they're offset by 401600. I just wasn't paying too much attention to how much offset they were when I wrote 400C00.

Tenko Kuugen

  • Public Enemy
  • *
  • Posts: 1416
    • View Profile
    • Twitter
made an edit above. There is either something really wrong or I dunno lol

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
No, you're right. Probably another injection I'm not seeing. I'm not going through all the bytes between point A and point B, but you've got the starting addresses right according to my debugger.

Tenko Kuugen

  • Public Enemy
  • *
  • Posts: 1416
    • View Profile
    • Twitter
That makes me a happy Kuugen

I understand the bits and the timers but could you explain a little more en detail what the parts at the handlers do?
Like, Death sentence has 46 4D 43 00 instead of 0A 4D 43 00
What would potentially happen if one played around with these values?
as I see it, E9 sets a permanent status until removed by an action
0A calls the timer and sets a time-limited status, right?
what does 46 do? ( death sentence )
5F is (slownumb )
B0 is poison

I'm interested in this since theres the possiiblity of making one status inflict another ( ala slow numb ) or set a timer for a heal ( delayed heal or status ( regen ) ala slownumb )

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
All the bytes in those dwords are addresses to different functions that handle the different statuses. There's nothing special about those values except that's where those handlers start. Don't play around with those values. There aren't other handlers.