Turned Poison into Disease through AI, but...

  • Thread starter Thread starter Armorvil
  • Start date Start date
Status
Not open for further replies.
Well, it depends how you calculate overkill - I'm not actually sure how FF X handles it...
That's the whole problem actually : the different overkill values aren't calculated or dependent on MaxHP; they're just set. Most of the time though, overkill values are almost equal to the enemy's HP, so one-shotting it will overkill it. The random monster Ahriman for instance, has 2800 HP and is overkilled when the finishing blow hits for at least 4200 damage. But another random monster has 5000 HP and is overkilled by an attack dealing at least 2400. And a Dark Aeon (=optional boss) has millions of HP and is overkilled with finishing blows dealing at least 99999 (yes, there are 5 digits). So, with these mechanics, there is no set rule that could work for all enemies...

This will be resolved when I get my computer, hard drive and internet connection sorted. I'll be getting a connection tomorrow and a replacement drive around (I believe) next Wednesday.
This is great to hear :)

One word about the kernel: whilst there's no on-disc size limit, KERNELs above 27,647 bytes *may* cause glitches. I haven't really investigated. That's still a 5kb increase, though.
Yeah, I read what Lasyan said about the ram. But as you said, I don't think it's an issue, since 5kb should be more than enough.

Feasible. There could be lots of ways of doing this, some more hacky than others. You could actually specify certain enemy IDs in the AI, but that would be bulky. You could make an enemy's prebattle script set a flag that turns on a different overkill script. You could make every 'strong' enemy turn on its bit in a targetmask held in a battlevar, then refer to that when working out which script to use. Or you could go for the simple method and make sure that only bosses have levels that are, say, multiples of twenty, and refer to this when choosing the right script.
Thanks for this insight. Still, as much as I'd love such a function to be implemented into FF7, I don't think I'd be able to write such a script without bothering you or NFITC1 for days... I'm quite satisfied with my mod's mechanics right now. If all goes well, I should be able to release it in July.
 
Last edited:
I don't mind writing AI scripts. I just can't do it in a timely manner at the moment thanks to my machine woes.
 
Cool :) (about your will to write AI scripts, NOT about your machine woes >_>)

Correct me if I'm wrong, but I think this overkill script should be written in the Death Counter section. It's quite simple actually, as it should be something like this (for the easy enemies, overkilled when the final blow is their maxHP x 100%) :

- Check for self + max HP
- Put this value in memory
- Check if last damage taken is equal or greater than the value we just stored in memory
- If not, jump to the end of the script
- If true, display message: "OVERKILLED {VAR:TargetName}{VAR:TargetLetter} !" (this should display the correct monster name, right ?)
- Check for AP
- Check for XP
- Check for Gil
- multiply those by 2 (I'd rather it be 1.5, but I don't think it's possible?)
- END

I *might* be able to write this, but my biggest problem would be with the bolded part. I don't know how to check for the strength of an attack.

Also, another idea that popped in my mind : since the Blind status doesn't work on enemies, I've been wondering whether one could add the Oil effect to it. Oil comes from Final Fantasy Tactics, and Fire elemental attacks deal more damage to the inflicted (or should deal more damage - it was glitched and didn't work in FFT...). Problem once again is, I don't know how to check for the presence of an element... ...I guess the script would look like this (what I'm gonna write will undoubtedly be unrefined and full of mistakes, but I don't have time to correct them ATM) :

- if target status=blind
- if attack = fire elemental
- if not, jump
- if true,  damage = damage x3
- end

The tissue could be put to good use as a way to remove the Oil status :)
 
Last edited:
Cool :) (about your will to write AI scripts, NOT about your machine woes >_>)

Correct me if I'm wrong, but I think this overkill script should be written in the Death Counter section. It's quite simple actually, as it should be something like this (for the easy enemies, overkilled when the final blow is their maxHP x 100%) :

- Check for self + max HP
- Put this value in memory
- Check if last damage taken is equal to the value we just stored in memory
- If not, jump to the end of the script
- If true, display message: "OVERKILLED {VAR:TargetName}{VAR:TargetLetter} !" (this should display the correct monster name, right ?) This works for Battle Texts, but I don't know if it works inside scripts like that. The way you reference Character names (Barret, Cloud) inside the AI text is different.
- Check for AP
- Check for XP
- Check for Gil
- multiply those by 2 (I'd rather it be 1.5, but I don't think it's possible?) Multiply by 3, divide by 2. Boom, 1.5
- END

I *might* be able to write this, but my biggest problem would be with the bolded part. I don't know how to check for the strength of an attack. I believe there's a Var:4XXX battle address for this. I don't recall what it is though as my notes for that section are incomplete I know that there are a lot of values in there that aren't used in AI, but the battle engine itself might handle.

Also, another idea that popped in my mind : since the Blind status doesn't work on enemies, I've been wondering whether one could add the Oil effect to it. Oil comes from Final Fantasy Tactics, and Fire elemental attacks deal more damage to the inflicted (or should deal more damage - it was glitched and didn't work in FFT...). Problem once again is, I don't know how to check for the presence of an element... See previous comment ...I guess the script would look like this (what I'm gonna write will undoubtedly be unrefined and full of mistakes, but I don't have time to correct them ATM) :

- if target status=blind
- if attack = fire elemental
- if not, jump
- if true,  damage = damage x3
- end

The tissue could be put to good use as a way to remove the Oil status :)
 
Correct me if I'm wrong, but I think this overkill script should be written in the Death Counter section. It's quite simple actually, as it should be something like this (for the easy enemies, overkilled when the final blow is their maxHP x 100%) :

- Check for self + max HP
- Put this value in memory
- Check if last damage taken is equal or greater than the value we just stored in memory
- If not, jump to the end of the script
- If true, display message: "OVERKILLED {VAR:TargetName}{VAR:TargetLetter} !" (this should display the correct monster name, right ?)
- Check for AP
- Check for XP
- Check for Gil
- multiply those by 2 (I'd rather it be 1.5, but I don't think it's possible?)
- END

I *might* be able to write this, but my biggest problem would be with the bolded part. I don't know how to check for the strength of an attack.
Hmm. I don't know if you can find that info out. You can find out the amount of HP lost since last turn, but that's not the same thing. I'll have to investigate...

Also, another idea that popped in my mind : since the Blind status doesn't work on enemies, I've been wondering whether one could add the Oil effect to it. Oil comes from Final Fantasy Tactics, and Fire elemental attacks deal more damage to the inflicted (or should deal more damage - it was glitched and didn't work in FFT...). Problem once again is, I don't know how to check for the presence of an element... ...I guess the script would look like this (what I'm gonna write will undoubtedly be unrefined and full of mistakes, but I don't have time to correct them ATM) :

- if target status=blind
- if attack = fire elemental
- if not, jump
- if true,  damage = damage x3
- end

The tissue could be put to good use as a way to remove the Oil status :)
You can't really do it that way, because you can't query the element of the last attack. You can query its ID, however, so you can write

Code: [Select]
Code:
counter preturn {is oil active? skip if notif id of last attack == that of fire 1, fire 2 or fire 3, thenstore current level in battle varand set level as 1/2 current}counter general {[implement oil however you feel]if battle var with level has anything in itset level to battle varset battle var to zero}
Some limitations with this, however:

1. You aren't quite multiplying damage taken. You can add and remove HP in an AI script, but it doesn't display. Changing level means your character takes a lot more damage from fire attacks, but it won't always be 150% damage.

2. You have to specify the IDs of the spells which have fire element. If you have lots of fire spells, specifying them individually could be space-consuming. It might be quicker to specify groups of spells, eg 'does spell have an ID which is > 0x29 but < 0x3A', then putting all fire spells within that range. This won't, however, help you combine Oil with Weapon Elemental - Fire, or any fire-based weapons you implement yourself.

The only other alternative is to find a way of setting a weakFire flag via AI. I can't really help at the moment because my machine is out of commission, but to find the weakFire flag, you would need to

- take Akari's memory map of the NTSC PSX build's battle engine
- run an emulator and compare memory maps for monsters with weakFire and without
- use a process of elimination to see where the weakFire might be stored
- look at the addresses in the memory map the AI can, uh, address, and see if some of the unknown addresses tally with the location of your weakFire variable
- set weakFire on when the target was Blind
 
This works for Battle Texts, but I don't know if it works inside scripts like that. The way you reference Character names (Barret, Cloud) inside the AI text is different.
Ah yes. Cloud is {EA0000h} in the AI text, and Barret is {EA0001h}, etc... Actually, it looks a lot like the FF7-text format, but all my different tests didn't net me any results regarding monster names. If this script becomes manageable in the future, I guess a simple "OVERKILL" message will do...

Multiply by 3, divide by 2. Boom, 1.5
lol, basic maths. I should have realized one can do more than one operation ^^;

I believe there's a Var:4XXX battle address for this. I don't recall what it is though as my notes for that section are incomplete I know that there are a lot of values in there that aren't used in AI, but the battle engine itself might handle.
Ah, this gives me hope - though I don't hold my breath.

Hmm. I don't know if you can find that info out. You can find out the amount of HP lost since last turn, but that's not the same thing. I'll have to investigate...
If those investigations will require you to in-game test each one of the 4xxx battles addresses not referenced into wallmarket.dat, I wish you good luck. Looking at them, there are 4041-4047, 4049, 4051-4057, 4059, 4061-4067, 4069, 4071-4077, 4079, 4081-4087, 4089 (I start to see a pattern :P), 4091-4097, ... (not gonna list them all, actually O_O). We're talking about hundreds - maybe thousands of battle addresses ! I may be crazy like that, but even I couldn't test them all - and I suggest you don't either, if you value your sanity. Still, perhaps many of those can already be ruled out ?

And about Oil : wouldn't it be possible to increase the level and/or the magic stat of the caster, instead ?... ...After all, levels can go up to 255 - might as well put this to good use.

And it's too bad about elemental weapons :( I asked in another thread if the AI could check for the presence of a piece of equipment, but I guess this means it can't.

The only other alternative is to find a way of setting a weakFire flag via AI. I can't really help at the moment because my machine is out of commission, but to find the weakFire flag, you would need to

- take Akari's memory map of the NTSC PSX build's battle engine
- run an emulator and compare memory maps for monsters with weakFire and without
- use a process of elimination to see where the weakFire might be stored
- look at the addresses in the memory map the AI can, uh, address, and see if some of the unknown addresses tally with the location of your weakFire variable
- set weakFire on when the target was Blind
Yeah, but weakFire is just a basic x2 damage. So, oiling an already fire-weak monster wouldn't reap any more benefits.

EDIT:

About Overkill, how about this :

In General Counter :

Code: [Select]
Code:
If HP < MaxHPIf target:self is NOT deadSet {VAR:E0} to 1
In Death Counter :

Code: [Select]
Code:
If {VAR:E0} is 0If attack ID is NOT 18 (=Death)If attack ID is NOT 3D (=Odin)Display message: "OVERKILLED!!"Set Exp to 2xSet Gil to 2x
What do you think ? Alternatively, I thought about using the in-game timer, and if you finished a battle quickly enough, you'd get added bonuses. FFVI can check a timer in its AI (some enemies can call backup, after a while), but I'm not sure FFVII can. And, third idea : couldn't we simply make use of the "Greatest elemental damage" battle address ? Since almost all attacks are elemental thanks to the physical elements, if one put, in the Death Counter script :

Code: [Select]
Code:
- Check for self + max HP- Put this value in memory- Check if the greatest elemental damage taken is equal or greater than the value we just stored in memory- If not, jump to the end of the script- If true, display message: "OVERKILL!"- Check for AP- Check for XP- Check for Gil- multiply those by 3- divide them by 2...
Wouldn't it work ?
 
Last edited:
Ah, this gives me hope - though I don't hold my breath.
Good idea. There's likely nothing like that, but you never know. :)

If those investigations will require you to in-game test each one of the 4xxx battles addresses not referenced into wallmarket.dat, I wish you good luck. Looking at them, there are 4041-4047, 4049, 4051-4057, 4059, 4061-4067, 4069, 4071-4077, 4079, 4081-4087, 4089 (I start to see a pattern :P), 4091-4097, ... (not gonna list them all, actually O_O). We're talking about hundreds - maybe thousands of battle addresses ! I may be crazy like that, but even I couldn't test them all - and I suggest you don't either, if you value your sanity. Still, perhaps many of those can already be ruled out ?
No, that's not how they work. Think of those addresses as pointers to BITS, not bytes. Every 8 is a different byte, and we're talking in Hexadecimal. So between 4008 and 4010 there are 8 values (4009, 400A, 400B, etc). My notes say that the highest 4XXX value is 42E0 which contains the total experience gained in that battle (technically, it goes to as far as 433F before it leaks into another actor's data, but it doesn't look like 4300 and beyond are used). Almost every value in between is used for something.
 
Can these addresses leak into another actor's data? Which data exactly (it might well be data I want to manipulate)?

I need to get to know that memory map better. I'd like to see how data for different actors is positioned.

I wonder which function assigns pointers to 'relative' addresses like 0x4001 etc. I also wonder if we might hijack it.
 
No, that's not how they work. Think of those addresses as pointers to BITS, not bytes. Every 8 is a different byte, and we're talking in Hexadecimal. So between 4008 and 4010 there are 8 values (4009, 400A, 400B, etc).
Why do you feel the need to tell me that, because I know this and- */me re-reads his previous post* ...OK, wow, I took the addresses as if they were decimals, I must have been really tired  ;D

So, what do you guys think about the three ideas I posted when I edited my previous post ? I'm especially interested in the GreatestElementalDamage battle address (VAR:4058).
 
Last edited:
As far as I can tell, 4058 is only modified when a 96 command is executed. I believe it's blank otherwise. You'll have to read my notes in WM's or PrC's readme for more details.
 
Can these addresses leak into another actor's data? Which data exactly (it might well be data I want to manipulate)?
Addresses can leak into other actors' data I don't see any restrictions in the AI code to cap the address it will access. Here are some of the findings that I've made. Each 4XXX structure is 104 bytes in memory. Normally, these will go up to 0x433F then another actor's data will start. Actor 0 (I believe this is the top slot of player characters) would be the only one to access everyone else's data. Starting at 0x4340, Actor (X) would be able to access Actor (X+1)'s active statuses. Adding another 340h to that and Actor (X) can access Actor (X+2)'s data, etc. Technically, I believe there are 10 actors (three playable characters, up to six enemies, and one "battle actor" that would contain formation-based scripts). For Actor (0) to access Actor (9)'s data, it would start at 0x5D40 and should be no greater than 0x607F. This applies to ANY 4XXX Battle variable. This doesn't apply to 2XXX addresses, because they are technically temporary to which ever character's turn it is.

So it IS possible for actor 9 to perform some DRASTIC memory leaks. I don't really know what's beyond the battle addresses, but Actor 9 can access quite a bit of it. Just shy of 6K outside of it as a matter of fact.

I need to get to know that memory map better. I'd like to see how data for different actors is positioned.
So follow this if you want to access other actors' data. Just add these amounts to the address of what you want to access:

Code: [Select]
Code:
Actor (X)   Actor (X+1)   Actor (X+2)   Actor (X+3)   Actor (X+4)   Actor (X+5)   Actor (X+6)   Actor (X+7)   Actor (X+8)   Actor (X+9)        0           340           680           9C0           D00          1040          1380          16C0          1A00          1D40
I'm not certain about which actor is which, but I think it goes: PartyCharTop, PartyCharMid, PartyCharBottom, Battle, Enemy0, Enemy1, Enemy2, Enemy3, Enemy4, Enemy5

I wonder which function assigns pointers to 'relative' addresses like 0x4001 etc. I also wonder if we might hijack it.
There aren't really any pointers. It's all pretty hard-coded static address lookups in every location it gets read from/written to. You can't really hijack it because they're all referenced all over the place. I suppose you could hijack lookups to those addresses though, but that's a lot of hooks.
 
I've been looking into this tonight. As far as I can tell, I just can't get a Counter:PreTurn script "Make Self.NullRestore = 1" or "Make Party.NullRestore = 1" to stop healing. I'm not holding any counter materia, so I'm developing a suspicion that the element control flags don't work outside the initialization scripts.

Will continue researching this.
 
*bump*

I finally got around to trying this out - I've uploaded a Youtube video here:

In this case, I created a pre-attack script on one character:

Code: [Select]
Code:
12 206010 42A98002 206000 4003809073
Then I just linked my characters to the other's scripts and was on my way.

For some reason, trying to make the script set allActors.nullRestore = allActors.poison (using the address 20E0 rather than 20E0 in the script above) didn't work well - inflicting / curing poison on one character would apply / remove nullRestore on everyone. I'm not sure why this is - though I'd appreciate some pointers.

In any case, I just made my script set self.nullRestore = self.poison, and it worked fine for the player characters. Any ideas how I can make it work OK on enemies without having to give them all a similar script? Maybe if I take an activeMask and iterate through all the formation numbers?
 
Status
Not open for further replies.
Back
Top