• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
March 28, 2024, 10:56:36 am

News:

Use of ePSXe before 2.0 is highly discouraged. Mednafen, RetroArch, and Duckstation are recommended for playing/testing, pSX is recommended for debugging.


Dokurider's Custom AoEs

Started by Dokurider, April 21, 2014, 04:41:48 pm

nitwit

Effective AI would make vanilla absurdly difficult.  Great job!

Dokurider

April 10, 2017, 03:37:24 pm #61 Last Edit: April 10, 2017, 10:20:37 pm by Dokurider
Today I have some very basic AI fixes. I tested some of them, but they're such simplistic one line changes, they really shouldn't fail. Be sure to look at the descriptions of each hack because some of them will conflict if you aren't paying attention, but it should be pretty obvious which ones do.

I also recommend against implementing some of these hacks into your patch because they may end up making the AI overall worse rather than better. I only added them just so that people can mess around with it and at the end of the day, it's your call.

These changes are:


  • Correctly informs the AI that Throw Item range is 4 and not Move Range

  • Correctly informs the AI that Jump's CT is 50/SPD. I still have no idea what the original code was trying to do.

  • Correctly informs the AI about the existence of Weapon Elemental skills and that one can use them to heal themselves.

  • Correctly uses the correct flags for Short Charge and Non Charge (0x08 and 04 respectively, the original code was using 0x80 and 0x40, Monster Skill and Defend, a typo?) AND correctly calculates the new CT for short charge


  • AI will no longer wake up sleeping units with Jump.

  • AI will no longer add Protect/Shell/Wall/Reflect/Faith/Float while in critical

  • AI will now add Protect/Shell/Wall when at 50% HP. You may also use the hack that makes the AI use those status at any HP level (except critical), which is not recommended.

  • The AI will now use stat effecting skills 100% of the time. Previously, the AI would give itself a 50/50 chance of using stat skills. That being said, the AI has a very low priority on stat boosting skills to begin with, so usage rates will only increase slightly.

  • Optional hack: The AI will now use Reraise at any HP level. This is not a recommended hack.

  • Optional hack: The AI will now use Regen at any HP level. This is not a recommended hack.



EDIT: Oh and I threw in my AI Two Swords fix as well.

Xifanie

Someone is actually using my spreadsheet.
I... so happy...
  • Modding version: PSX
Love what you're seeing? https://supportus.ffhacktics.com/ 💜 it's really appreciated

Anything is possible as long as it is within the hardware's limits. (ie. disc space, RAM, Video RAM, processor, etc.)
<R999> My target market is not FFT mod players
<Raijinili> remember that? it was awful

Pride

  • Modding version: PSX
Check out my ASM thread. Who doesn't like hax?

Dokurider

Oh here's a late one I just made tonight, but it's too interesting to hold onto.

These hacks allow the AI to see it's own procs. Yes you heard that right. What's more, I have two versions for the community to use because I wasn't sure which method to use.

Version 1 makes the AI assume procs work 100% of the time.



001884d0: 3c038019 lui r3,0x8019
001884d4: 8c63f5fc lw r3,-0x0a04(r3)                      Load Simulation Byte
001884d8: 34020002 ori r2,r0,0x0002
001884dc: 10620008 beq r3,r2,0x00188500 Auto Succeed Proc Roll if Simulation = Display (Ignore results of roll)

Changed to:

001884d0: 3c038019 lui r3,0x8019
001884d4: 8c63f5fc lw r3,-0x0a04(r3)                      Load Simulation Byte
001884d8: 34020002 ori r2,r0,0x0002
001884dc: 10620008 bne r3,r0,0x00188500 Auto Succeed Proc Roll if Simulation = AI or Display (Ignore results of roll)



Version 2 makes the AI factor in proc rates. So in Vanilla, it will check it's own proc 0x0013% of the time.


001884c8: 0c061da4 jal 0x00187690 # Conditional Status Proc Roll (19%) Inner Routine
001884cc: 00000000 nop

Changed to:

001884c8: 0c061da4 jal 0x00187690 # Conditional Status Proc Roll (19%) Inner Routine
001884cc: 02000434 ori r4,r0,0x0002               r4 = Simulation Byte




00187690: 3c028019 lui r2,0x8019
00187694: 8c42f5fc lw r2,-0x0a04(r2)              Load Simulation Byte
00187698: 27bdffe8 addiu r29,r29,0xffe8
0018769c: 1440000d bne r2,r0,0x001876d4       Skip Proc Roll if Simulation = Display or AI

Changed to:

00187690: 3c028019 lui r2,0x8019
00187694: 8c42f5fc lw r2,-0x0a04(r2)              Load Simulation Byte
00187698: 27bdffe8 addiu r29,r29,0xffe8
0018769c: 0D004410 beq r2,r4,0x001876d4       Skip Proc Roll if Simulation = Display or AI



Both have their disadvantages and advantages and I will let the users decide which one they want to use.

I don't have video proof, but I can offer how I determined with certainty that these hacks work:

I set up a Thief with Punch Arts and Martial Arts with a modified Dagger that procs Wave Fist that is also flagged for all elements. I did same for all offensive Punch Arts except for Secret Fist. Secret Fist and Steal Heart I unflagged their Add Status property and flagged them for Target Ally use, ensuring they will never get used.

So versus a Woodsman, under normal circumstances, the AI will only ever consider using Attack on the the target. Indeed, this was the case, with the only setbacks coming from when the proc triggered and healed the tree.

When I activated Version 1, the AI refused to attack the target at all, finally seeing the proc and not wanting to attack at all. It spent the rest of the battle running away. When I deactivated the hack, the AI immediately resumed attacking the tree.

When I activated Version 2, the AI attacked the target, but sometimes it would randomly run away, as I predicted it would. When I increased the proc rate, this behavior intensified, constantly running away like the Version 1 hack, but occasionally attacking.


In either case, this hack leaves much to be desired. I would lean more towards Version 1, but I offer both. In the future, I would like to reduce the amount of damage/status priority that the procs cause by proc rate%. Something along those lines.

nitwit

April 14, 2017, 01:02:19 am #65 Last Edit: April 14, 2017, 07:52:24 am by nitwit
So the AI needs to take into account how much healing would be done and how often it could happen in order for it to act intelligently?  If the amount of healing over say 8 attacks is less than the damage you'd deal (both at a given proc rate), there's no reason not to attack.

Does the AI set attacks that have any possibility of healing as least priority?  Given that you won't often have a situation where the AI has so few options, it might be acceptable to have sub-optimal behavior.

Or the AI can be maximally conservative and never take that risk, in which case elemental defenses becomes a way of removing options for enemies or herding them towards PCs with vulnerability or weaknesses to their strongest abilities... it's something else to consider.  How could you exploit a maximally conservative AI?

Dokurider

Quote from: nitwit on April 14, 2017, 01:02:19 am
So the AI needs to take into account how much healing would be done and how often it could happen in order for it to act intelligently?  If the amount of healing over say 8 attacks is less than the damage you'd deal (both at a given proc rate), there's no reason not to attack.

Does the AI set attacks that have any possibility of healing as least priority?  Given that you won't often have a situation where the AI has so few options, it might be acceptable to have sub-optimal behavior.

Or the AI can be maximally conservative and never take that risk, in which case elemental defenses becomes a way of removing options for enemies or herding them towards PCs with vulnerability or weaknesses to their strongest abilities... it's something else to consider.  How could you exploit a maximally conservative AI?


I should have mentioned that the sheer amount of damage (healing) this proc did was absurd: 400+ damage vs 100 damage just with the weapon alone. So the only conclusion you should be drawing from this is how the AI reacts to being able to see their own procs.

I would really just recommend messing around with it yourselves. Even if I recorded a video, it's not an easy concept to understand or explain in a few sentences.

Dokurider

Today, I have a couple of new hacks and one update for everyone, but I don't have enough to detail how they work today.

The first and main feature hack now reverses the Critical AI's distance feature. Instead of moving away from allies healers, the AI will instead move closer to them. Yes, in fact, this was in the game this whole time, I just turned in one with one line of code. For a better explanation, check the hack description or wait until I post an in-depth explanation.

The second hack is actually an update. It's a much more efficient fix for the Stat Usage hack. It's still has little appreciable effect on actual usage unless paired with the next and last hack.

Lastly, this Low Priority Hack allows for abilities that have no real AI handling to be used by the AI in place of doing nothing. This mostly applies to Stat Boosting abilities, such as Accumulate. In Vanilla, the AI will only use Accumulate with this hack because it, Yell and Scream have the same priority, but Accumulate is the first added to the data bank, so it only uses Accumulate unless not learned.

Shoot me any questions, and I'll answer them a little later on in the week.

EDIT: Attached the correct file...

LohikaarmeX

Really amazing work here. I can see that the AI fixes gonna make the game more enjoyable.

But i got a question about the Cone AoE

Let's say that i want to make a skill, like a sword slash that goes all horizontal range (Not like Holy Explosion).

Something like this

P T T T P               P= Panel
     P                    T= Target
     P                    C= Caster
     P
     C



Can i make it with this hack?

Dokurider

The Cone AoE hack only makes Cone AoE.
I have no issues with you modifying it, in which case then yes, it can be (heavily) modified to become what you described.

Dokurider

May 09, 2017, 02:53:34 pm #70 Last Edit: May 09, 2017, 07:18:57 pm by Dokurider
Today I have some more AI Movement hacks.

The first hack changes the AI's primary tendency from move away from their targets during Post Action, to remaining close to the target.

The second hack changes the way the Post Movement Decision Routine processes panels. That way, both the Pre and Post Action Movement Routines are more likely to arrive at the same conclusion. This means that the AI is more likely to stay in place and less likely to move around unnecessarily.

Combine the two hacks and you have an AI that moves around less. I find the results surprisingly underwhelming. The AI just end up smashed together in the middle of the map. Then again, the end results are probably more impactful vs human players.

Dokurider

May 12, 2017, 10:40:12 am #71 Last Edit: May 13, 2017, 11:59:23 am by Dokurider


Okay lemme explain now.

The game has three modes of simulation. The first mode is the real one. What it uses to do actual damage and statuses to actual units. The second mode is the AI simulation, and the third is for the damage display billboard (before you make an attack). The two non real modes often manipulates anything that is based on chance to either auto succeed or auto fail. In the case of AI mode, the manipulation goes further than that, at least, when it comes to Reactions.

The AI mode denies access to even starting reactions to begin with, with one major exception, which I'll get to in a minute. Fortunately, this is a one line check and is easily disabled to allows the AI to see and take into account Reactions.

However, there is a few caveats. For one, which caught me offguard, is that the Reaction routine doesn't inherently check if the target is dead. What ends up happening, is that dead targets can react. I haven't observed them being able to damage their killers, but they can add Reraise to themselves at least, which is very annoying. So I had to replace the mode check with a dead check.

Why was this originally allowed, you ask? Because Dead units can and do react. How? Reflect. Reflect is coded as a reaction. It is the only reaction in the game that the AI is allowed to see and think about, and it is the only Reaction that dead units are allowed to perform. They allowed this so that Reflecting off of Dead units was possible.

Secondly, the AI is pretty strict about reactions. If it's a result that they can quantify, like Auto Potion, they will abide by it by sheer arithmetic. If they cannot deal enough damage to overcome Auto Potion, then they will not attack that target with damage at all, unless it's fatal damage. Which, for the most part, is good. However, the same principal applies to other Reactions like Counter. If they cannot outdeal the damage they will take back, they will not attack a Counter unit.

Even Dragon Spirit can make a target untargetable by anything that can't overcome the priority value that Reraise provides. Of course, once it's triggered, it's open season on the Dragon Spirit unit. And mind you, Priority Value is proportional to the target's HP, so the more HP the target has, the more damage a unit has to have to be allowed to attack a target. So you might end up with a nightmare scenario with a single unit that's considered untargetable by any single AI enemy unit in play.

And yes, the AI does take into consideration taking fatal damage. In fact, it'll avoid taking damage that would push it into critical or near critical.

There are many more reaction interactions that this hack opens up. I will leave finding them up to the community. In the mean time, I will note that it's not perfect, but most of the issue lies with the AI's priority system, which needs an overhaul. Unlike most of the hacks I've published on the AI so far, this will not be a one line change. The priority system is the core of the AI. It is the base of which the AI functions off of. And it must be rewritten extensively. As a result, I will be saving that rewrite for last. Until then, I'll will be fixing and exploring other AI issues.

As always, try it out and let me know of any bugs. Thank you.

Dokurider

Confusion Hack and Status Effect Priority Value Workbook

I have two hacks for you guys today.

1. The first hack allows the AI to target Confused units. More specifically, Confused units are now considered Active Units, they are no longer treated the same way that Death Sentenced units are treated. However, there is an additional barrier to the AI's targeting of Confused units.

Recall that in the Reaction hack, the AI will not target Dragon Spirit units unless it can deal more damage than Reraise is valued to grant that target. The same principle applies here as well. The AI must deal over 50% damage to consider damaging a Confused unit. This can be very difficult for some team setups, so the next step would be to lower Confusion's Priority Value, which brings us to our next hack.

2. I had Raven create an Excel sheet that allows anyone to edit the Priority Values of all Status Effects. That way, you can lower Confusion's value to something more manageable so that the AI can reliably break Confusion on units. You can also increase Oil's priority value so that the AI will want to add and cure it often.

In summary, if you wish to use the Confusion hack, it's strongly advised to change Confusion's priority value as well.

RIP SSCC runs. Please forward your praises to Raven.

nitwit

Quote from: Dokurider on May 09, 2017, 02:53:34 pm
Today I have some more AI Movement hacks.

The first hack changes the AI's primary tendency from move away from their targets during Post Action, to remaining close to the target.

The second hack changes the way the Post Movement Decision Routine processes panels. That way, both the Pre and Post Action Movement Routines are more likely to arrive at the same conclusion. This means that the AI is more likely to stay in place and less likely to move around unnecessarily.

Combine the two hacks and you have an AI that moves around less. I find the results surprisingly underwhelming. The AI just end up smashed together in the middle of the map. Then again, the end results are probably more impactful vs human players.

Maybe you should attach different AI movement tendencies to different AI "roles" (similar to auto-battle)?

Also how does this mesh with the other AI hacks that increase the AI awareness of various things?  Second-order effects may not be visible with one hack alone, but with multiple ones you can make a truly ferocious AI.

Dokurider

June 25, 2017, 02:02:07 pm #74 Last Edit: June 27, 2017, 09:01:52 am by Dokurider
Quote from: nitwit on June 11, 2017, 10:38:31 pm
Maybe you should attach different AI movement tendencies to different AI "roles" (similar to auto-battle)?

That more or less how it already works. Critical/Cowardly and Default have different movement patterns. Protective and Aggressive have the same patterns as Default, but since they tunnel vision on one unit, they tend to move differently anyways.

QuoteAlso how does this mesh with the other AI hacks that increase the AI awareness of various things?  Second-order effects may not be visible with one hack alone, but with multiple ones you can make a truly ferocious AI.

Honestly, I haven't really tried them all out at once yet. That is my ultimate goal though.

Anyways...

Golem AI fixes

Here's how the AI currently handles Golem in Vanilla. Remember that Priority is a function of HP. Statuses are given a set Priority value for how much damage this effect is equivalent to (Protect/Shell are given +20% because they reduce damage by 20%).

  • Fetches current team Golem amount

  • Fetches the average HP of every unit that was in play. This value was determined at the very start of the battle and does not change at all. This value is capped at 255 HP/0xff.

  • Shifts current Golem by 7 (multiples by 128/0x80 for the unfamiliar)

  • Divides (curGolem * 128) by the team average

  • Adds this amount to the running priority total.

  • Repeat for every unit on that team


This formula only works until mid/late game, when even on the most fragile of units, HP values easily exceed 255 HP. What ends up happening is that Golem ends up with double or almost triple the priority its supposed to have, per unit. Even if Golem Priority was divided properly, Golem would still have an absurdly high priority compared to the average effect. It would be roughly priority valued at +100% per unit, which it is technically, but because the effect is shared amongst the team, it's more like +20% for the average 5 man party. It should not be valued at the same amount as a unit's actual HP, which I think was the intent and thus the core mistake in making the Golem handling routine.

However, that's not the worst part. The absolutely worst part, is that any damage done to Golem, to even a single unit, is interpreted as happening to every unit on that team.
It works like this because it actually is effecting every unit on the team. You deal damage to Golem, you reduce that amount for the entire team. From the AI's standpoint, you are dealing damage to the entire team.
So what happens when the AI sees it can deal damage to an already overvalued effect and it also effects every enemy unit on the field with a single no cost action? Why, the AI is going to attempt to damage Golem every single time. The way the game has it handled, the AI sees damaging Golem as more valuable than dealing actual damage. This effect is strong, it even overpowers the AI's desire to finish off critical units. Small wonder why Golem breaks the AI so hard.




I have two fixes for you guys today.

The first fix simply blanks this entire routine outright. You can use this fix if you are dissatisfied with the second actual fix or you are not using Golem in your patch at all.

The second fix is an actual, if rudimentary, fix. It now handles Golem like thus:

  • Fetches current Golem amount

  • Divides Golem amount by 8 (shifts down by 3). 999 HP produces 0x7c, which is at least somewhat in line with normal priority values.

  • Divides that amount by 5, the number of units on an average player team.

  • Adds that amount to the running Priority total

  • Repeat for every unit on that team, which if there are only 5 units, ends up being about the current shifted down Golem amount.


Of course the obvious problem with this fix is that if you have more than 5 units on a team, the golem amount is still going to high. Not as absurdly high as it was, but still high. One can argue that is a good thing, because an 11 man team with Golem on top of it is a dire threat.
However, the idea of fixing Golem is to encourage the AI to use other attacks to bypass Golem instead of dropping everything to try to remove Golem. Making it too high of value was what was causing the problem in the first place.

So yes, I'm not satisfied with my current fix. The idea fix would be making Golem Priority = (curGolemHP * 40) / (Team Total HP). Team Total HP is just that, the sum of every unit's max HP on a team. For an example, assuming curGolem is 999, and every unit's HP is also 999 with 11 units, you would end up with +5% priority per unit. This seems rather small, but remember that because the AI sees that it effects every unit on the field, that effect adds up. Furthermore, the AI also understands that it is not dealing actual damage when it is hitting Golem.

Having Golem being seen as a small amount that nevertheless prevents certain attacks from dealing real damage achieves our desired goal: discourages, but still allows for Golem breaking, but for the most part, encourages bypassing Golem.

Because adding up the Team's Total HP every time I want to calculate Golem is a serious drain on the CPU cycle, leading to very long "thinking" times. Golem handling is in one of the most frequently used routines of the entire AI process. This routine, which already goes through every unit on the field, is used to process the effect of every action on every possible unit. It seriously adds up.

So the only sane way of using a Team Total HP is to create the value beforehand and then reference it as needed. The only issue is that I don't have a real space to do this aside from Kanji Space. The Average Unit HP (of all units, not just that team btw), is set once and then never changes and even then, it's caps out at 255 HP because it is a single byte and only has a single byte of space allotted to it. I don't know what, if anything, uses the spaces before and after.

I always strive to avoid using Kanji Space, so I can't implement this solution right now until I'm know I can use those spaces.


So yeah, it's not the perfect solution, but it's a start. It should, at the very least, make it so that the enemy AI doesn't go nuts when Golem hits the field anymore and has a reasonable response. This destroys yet another way the player frequently cheesed the AI. I strongly recommend this hack for PvE patches.

Here is a video of this hack in action:

nitwit

If you never use Golem and remove it from the game (and you want to optimize) how much code could you cut out of the game?  And your list isn't correctly formatted.

Dokurider

Quote from: nitwit on June 27, 2017, 03:52:25 am
If you never use Golem and remove it from the game (and you want to optimize) how much code could you cut out of the game?  And your list isn't correctly formatted.

Oh thanks for the catch.
It might make the AI think cycle go a touch faster, I'm not sure at all. I think after I take a look at how the Song/Dance/Math AI works. I'll probably start optimizing the AI.

Dokurider

July 18, 2017, 03:41:16 pm #77 Last Edit: July 18, 2017, 04:36:34 pm by Dokurider
Hey guys, I have some updated and new code for you guys today. But first,


Stat Abilities vs the Wait Command

The AI assigns a Priority Value to not taking an action or Waiting. That value is the accumulation of every unit's current HP, MP, statuses, and whatever else. This value is the initial threshold that every ability has to beat in order to even be considered for usage by the AI. Abilities that are have worse or equal values will not be considered. Being equal to the Wait command is the problem for Stat Abilities.

As I've explained before, the AI does not have coding to handle Stat Abilities when it comes to assigning them Priority. Therefore, it has equal value to simply waiting and is not considered for usage by the AI, with one major exception.

The stat abilities of Songs and Dance are used with a rare consistency when it comes to the AI. This is owed to the combination of being Ignore Range, bypassing a great deal of usage checks and and special code that adds priority to stat spells outside of the normal priority routine.

This code is accessed in very specific ways, the most common being charging a spell, either planning to or currently doing so.

0019de10: 92620000 lbu r2,0x0000(r19)        Load Ability's AI Behavior Flags
0019de14: 00000000 nop
0019de18: 30420008 andi r2,r2,0x0008
0019de1c: 10400003 beq r2,r0,0x0019de2c        Branch if Ability doesn't have Stat Changes
0019de20: 34170001 ori r23,r0,0x0001        r23 = Target Priority - 1
0019de24: 341e0003 ori r30,r0,0x0003        r30 = Target Priority + 3
0019de28: 34170004 ori r23,r0,0x0004        r23 = Target Priority - 4


What is in r23 doesn't ultimately matter because it's locked behind impossible conditions and even if it wasn't, it would still only have an effect on a handful of skills in the game. From both looking at the code and in my testing, this routine is called three times, so for calculating Priority, multiply desired result by three.


Without that code, the Stat Performances would not be used at all. It was a fast way to make sure the AI used every Song and Dance ability. However, this came with a downside seen when the unit gets it's turn and very visible once you push the user into higher speeds. The AI will cancel it's own song/dance once it gets it's turn. Once the AI starts to get faster than the CT of it's Song/Dance, it will constantly restart the song/dance, preventing them from ever actually casting the spell. This does not effect normal spells, or even non-stat songs/dances. Wiznaibus and Life Song will work just fine, no matter what speed you are.

First, let me explain how the AI normally resumes spells. The AI gets it's turn, gets the value for Wait and then the value for whatever spell it was already casting. It will see that the effect that just waiting (and letting the spell go off) vs restarting the spell casting has the same value. And since the AI will only use abilities that are better priority wise, it will not restart the spell, and choose to wait, letting the spell go off. This is all well and good until you get to Stat Abilities with a CT. The Wait Command doesn't go into the routine that gives the Stat Abilities it's priority because it technically doesn't follow any of the requirements to get in. But restarting the Stat Ability does. So therefore, the Wait Command is lesser than just restarting the Stat Ability, so it gets restarted.

In order to fix this behavior, the code that gives Priority to Stat abilities must be present in the main Priority routine in order to be counted. This is what my hack I give to you today does. Not only does it fix the Song/Dance Restart bug, but it also naturally gives the AI an incentive to use other non CT Stat Abilities like Accumulate and Yell. I even added an extra Golem fix to bypass the Golem Calculation if there is no Golem present, for slightly faster decision making.

This both the Stat Ability AI fix and the same Golem fix I published above with one additional change.

The only issue that remains with Stat Song/Dance is that the AI will instead switch from stat skill to stat skill. The Priority code I gave them does not give any distinguish beyond "are they stat abilities?" Therefore, the AI will see them all as equal and given that the Stat Abilities are also dictated by randomness, will freely switch between abilities if it interrupts it's own song/dance. But it will definitely not restart it's own performance if it happens to land on the spell it was already using.

Strongly recommended hack for all patches.