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 - NFITC1

Pages: [1] 2 3 ... 115
That's knowledge that's probably lost to even Square. All source code has been lost and will likely not resurface again for years. Battle scripts weren't designed for artists, there's another set of scripts for those. I imagine it all came from a desire to make more complex AI after the previous FF's AI was so basic. They had a much bigger canvas to work on (so to speak) so all sorts of complicated AIs could be achieved.

FFVI had some very specific jump conditions. This is definitely a step-up in terms of customizations.

Does it actually say “bade code”? I wouldn’t put it past me back then. :P

Ahh, shoot! You’re right. I was thinking about the battle.lgp that contain the enemy model data. I’ve gotten less smart lately, apparently. :P

There's more debug info in the Japanese PSX edition. There is no scene.bin as that is unique to the PC edition, but the test enemies and formations were way different in the initial release. Every other edition after the first Japan release had their test enemies replaced with those pyramids.

As for 2018, this is only used in one of (all of?) the debug enemies and doesn't seem to be assigned anything.

What I'll say abou Grangalan Jr. Jr. is that PrC's AI disassembler isn't perfect. That's because the AI scripts themselves aren't perfect. Sometimes jumps will jump to jumps and other times jumps won't be reachable at all. This always throws off the disassemly. I think the Kalm wolf has some behavior like this, but it has a very simple script. Anyway, when this happens you'll have to diagnose the script by hand/sight.
TFergusson is incorrect and the script indicates a 3/4 chance of silver wheel. Take a look at the binary script:
Code: [Select]
60  04
60  00
71  000F
72  0020
72  000F
This is the relevant part at least. The code 71 will jump if the top two pops ARE NOT EQUAL. So the (Random Mod 4) will NOT trigger this if it is equal 0 and it will jump to 0020 at the next step. The confusing bit is the unreachable 72  000F that is located at 0x00C. This is confusing the disassembly and causing the weird output. This actually may be an artifact of the removed Stop Eye action.

NFI, how many formations are there that I need to be aware of that contains AI script?

Not as many as there should be. I can say that for certain. Most bosses that have "containers" like Rude's pyramids or Bottomswell's bubbles have them I think. Carry Armor might too. I only added editing them to PrC because I was told they exist. I never did much digging into them.

2180 might be another of those absconded memory addresses that had a function, but no implementation. I'm not sure why it's listed what it is in the wiki (I wrote it, I'm sure). I probably noticed it during a reversing session and just labeled it with the intention of revisiting it and just never did.

I found that 41E0 and 41F0 ARE indeed being set....

*investigation music intensifies!*
*investigation music abruptly ends*

Well that took, literally 10 seconds. 41E0 is Initial HP and 41F0 is Initial MP...but only for playable characters. It also doesn't seem to ever be used this way. Mandragora is literally the only enemy that uses it. Possibly it was a convenient dummy value for enemies and the AI programmer just thought "I'll use this value that is never used to communicate between enemies of the same type". While a great idea, it is sadly underused even as that.

2040 is still unset by the battle engine. It's a convenient global value marker, however, since it will not be automatically changed/unset during the battle except through scripting.

Then 4160 is current HP. I’m transposing numbers in my head... I don’t remember what 41E0 is.

It looks like neither 41E0 or 2040 are set by the battle engine.

For Mandragora's part, it look like it's using 41E0 to direct AI for all the Mandragoras in the battle. If one is attacked with either physical or magical damage, then the next attacking mandragora will counter with a specific action based on the type and then declare to the others "I've avenged us".

As for 2040. The only enemies that use it are Bottomswell, Carry Armor/Left Arm/Right Arm, Elfadunk, Roulette Cannon, SOLDIER:2nd, Turks:Rude. Roulette Cannon and SOLDIER:2nd can appear in the same formation so they might be able to shed some light as to what the intended function is.

I’ll have to double check some of this, but IIRC 41E0 is the actor’s MMP. Maybe the mandragora use it as a sort of shared pool? I dunno.

As for the 22 having split damage, it certainly does. That might be the magic calf for either most magic damage actions the player has (fire, ice, etc) or magic healing (cure, et al). Either way, there is a flag on actions that can set to bypass the split damage calculations. Most likely the ones TF has listed as 22 and non-split have this override enabled.

I’ll have to check on 2040, though. It doesn’t seem familiar.

2120 is elements in the last performed action. It doesn’t matter who the actor was.

Yeah. While it is an odd choice to check for some actions and exclude one, this is still essentially intended behavior. Soldier:3rd only has 40 MP so it can only do Ice2 or Bolt2 once without the player somehow interfering (giving an ether by mistake or something). Personally, I think most human enemies should be allowed to utilize items once or twice if the need arises. Say they can use an ether (rather, an action that imitates the ether item) if their AI selects something they don't have MP for. That makes them "waste" their turn on a utility action which makes the experience of fighting "intelligent" characters more believable. This is during the ShinRa HQ raid so you'd expect company guards would have access to such supplies. But I digress...

This is definitely one of those AIs that could be simplified.

It just affects damage done by actions that inflict the status

Once you enter Midgar, you never leave. those changes don't make sense. I'm guessing you meant this:
Code: [Select]
0x040 If ( (BattleAddr(&AllPlayers).BattleAddr(&FrontRow) == 0) )
0x040 {
0x04D LocalVar:PlayerRow <- 1
0x057 If ( (BattleAddr(&AllPlayers).BattleAddr(&FrontRow) == 1) )
0x057 {
0x064 LocalVar:PlayerRow <- 2
0x06E If ( (BattleAddr(&Self).BattleAddr(&FrontRow) == 0) )
THAT would make sense. :)
I just took a look at it and at first glance the vanilla script is totally stupid. Trying to AND a value that you just set to 0 will always result in 0. However, maybe they intended this. It appears that the intended function is if all playable characters are in the back row then prioritize the machine gun action.

There is a 1:4 chance of Tonfa in the event that the LocalVar:PlayerRow = 1
There is a 1:8 chance of Tonfa if LocalVar:PlayerRow = 2
However, since neither of those are possible, it defaults to a 1:6 chance of a Tonfa

This idea probably got scrapped since both Machine Gun and Tonfa are long range attacks and their damage output is not reduced due to target's row. Rather than remove the code that would allow for this chance behavior, it is simply mitigated by not allowing it to logically happen. Then, should the need arise in the future to change it back, it's a simple fix. A SIMPLER fix is to change the initial assignment at position 0x004 to be a 3. Then these values will be correctly AND'd and produce a non-zero result. The script is still stupid for other reasons (obvious copy-pasted code blocks) but it has more function again. If I wanted to take the time I could make a much cleaner code. I'm just not sure it's worth it on such a simple enemy. Although it might provide some good practice for other scripts... I might change my mind if I find myself bored later. Actually, it is CERTAINLY not worth it because the entire script is based around the possibility that Tonfa is a short range action. Since it's not there is no need for 90% of the script. It can be as simple as
Code: [Select]
If (Not (Random MOD 6))
   LocalVar:0080 <- 272 (Machine Gun)
} Else {
   LocalVar:0080 <- 273 (Tonfa)
TargetMask <- RandomBit( AllOpponentMask )
Perform(LocalVar:0080, EnemyAttack)
That is literally all it needs to be. This prioritizes Tonfa (since it's a more damaging action) at a 5:6 ratio.

I'm not going to say I'm lazy, but can you provide a link to where I discussed that. :P I'm not doubting that I said this, but I probably said other things around that and the context would make more sense to me and be able to explain it.

Ack! I was only looking at the AI. I know those flags pull into the 402X memory region, but I always forget to look in form data.

I didn't say multiple limbs, I said multiple parts. This includes Hell House as it essentially has two "parts". One being the thing you initially encounter and the other being the possessed thing after the initial house thing is defeated.

Eligor made me rage quit. I understand what it was doing, but he got WAY more of a detailed script than he needed. It's main script is longer and convoluted than Ruby Weapon's; And HE controls his tentacles!

You have the 4020, 4021, 4023 and 4024 addresses correct to my notes. I haven't tested 4022 very much. It's used in 59 different enemies (none of which are the Hojo samples. Not sure where you get that they are) and they are typically enemies that have multiple parts and are controlling certain parts. Some exceptions are enemies like Chocobos (which is why I think this flag is "not necessary to defeat to win").

I used to check Discord a lot. I haven't been on lately due to lack of time. I'll give it a check now though. I did get that PM, but I didn't have anything constructive to add. I'm almost daily checking this site though.

Oh this is the thread for me. :D

Regarding to the (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) conundrum. This, as you noticed, translates to if there are NO players in the back row. This has to do with the data type that is returned by the AllPlayers address. It's a 2X type variable meaning it returns a list (of 3 in this case) values with the state of each player. When that is masked by row, it changes those 3 values to each players' row values. In this case, if ANY of them are zero then the condition passes. That's just the nature of the 2X variable type and conditional checks. I wish there were a non-ugly way to indicate that in the AI editor.

Now to the 4022 variable, I believe this unsetting this value indicates the enemy does not need to be defeated in order for the battle to end. I think some set pieces set this in their init scripts. Check the helicopter in the Rufus battle and the truck and tiny bronco in the Palmer battle. Just going by memory here, but I'm pretty sure they unset the 4022 flag. A few bosses do as well IIRC. Check Mystery Ninja Custom 7 script and Diamond Weapon's Death script.

FF7 Tools / Re: FFVII Enemy Database & Calculator V1.0.0
« on: 2019-02-19 18:25:18 »
In all honesty NFI, I was trying to refrain from sending you a bucket load of updates on this thing; I was trying to wait till it was complete (complete-complete) before sending it your way, but the definition of "complete" kept changing and growing along with the spreadsheet lol.

Do you even code, bruh? There is no "complete" complete. :) Apart from "final/definitive" versions, which is a developer's way of throwing up their hands and saying "I'm sick of this code and don't ever want to touch it again!", there will always be something that can be added/corrected/optimized.

FF7 Tools / Re: FFVII Enemy Database & Calculator V1.0.0
« on: 2019-02-19 12:18:34 »
This thing is absolutely amazing for what it is and I know you spent lots of time on it. It's a great tool for enemy designers to balance their creations.

I know you sent me drafts several times and I'm sorry I didn't get a chance to really try to break it. It looks fantastic! I'm not great with Excel so I'm not qualified to tell you if anything's wrong or how to fix it. Sorry. :)

FF7 Tools / Re: Gauging interest in WM Walkmesh Editor
« on: 2019-02-13 20:11:28 »
Such a thing has long been foretold by many prophets, but fate has not yet blessed us with it.

This is a very common C gotcha (attempting to dereference podhd via &(podhd->line6) is undefined behavior if podhd is NULL. The check for NULL belongs before the attempt at dereferencing podhd and really any C programmer will know that. There's nothing wrong with the "second check" except that it's misplaced, and most good compiler's (gcc, for example) will optimize it away as the attempt to dereference podhd in the previous line will let the compiler know (mistakenly) that podhd cannot be NULL.

Simple solution, check for NULL before you dereference pointers. These sorts of things are more of a hassle when you're learning than later on when you've developed good habits w.r.t NULL handling (responsible for about 90% of C's "gotchas"). Being able to propogate constraints like this and letting the compiler (or instructing it with __builtin_unreachable) optimize away unnecessary works/checks is another factor that contributes to the performance advantage well written C code enjoys over most other compiled languages.

This is not unique to C. This is poor program planning and a violation of the Fail Fast programming convention which can result in runtime errors. Most, but not all, IDEs in more modern languages will detect this and some won't even let you compile. That's with pretty strict options as it will just throw a nullpointerexception (or that language's equivalent) which might be caught outside the method.

The actual solution is always check all your arguments' states before performing any logic on them. Almost all programming errors are the result of NOT performing these checks and handling bad states correctly. The others result from creating massively long methods that try to do too much so no human can keep track of what it's actually doing and it ends up contradicting itself or another method. These errors are universal to all programming.

Just want to throw another hat in the ring. I know Pascal was supposed to be "great", but I hate it. Still hate C more, of course.

Assembly is as close to machine code as you can get. Just because it uses aliases for codes that may or may not be multibyte instead of straight binary doesn't mean the two aren't practically interchangeable. They aren't the same thing, no, but the difference is only technical.

How old are we talking? DOS-era? Some of those use some data compression voodoo in the code that can't be modified without unpacking it.

Start with something REALLY simple, like Perl. It doesn't do much, but almost every OS (Operating System. ie; Windows, Mac OS, Linux, etc) has the ability to run Perl scripts. If nothing else this will get you used to seeing syntax and how code executes when little things change. Perl is executed in real-time as a script.

From there, look to Scratch. Not the most powerful language, but it's hard to mess up. This can be compiled into a stand-alone executable.

The next logical transition would be to java (since Scratch translates 1:1 with java IIRC). You'll run into a lot of road-blocks with java when trying to access system resources. This can also be compiled and nearly every OS can run it.

So the next level would be C#. It's a less explicit form of C++ that is similar enough to java to look familiar, yet have far more functionality. This is where OSs differ. Any program can be written in C#, but it will have to be compiled with a particular OS in mind.

If you aren't scared away from that, you can dive into assembly. Start with whatever your favorite OS runs. Then you can really learn how processors work.

At least, this was my experience with a more modern linguistic twist (I learned QBASIC instead of Perl, but they can do similar things). I spent years (and still do) on each of the languages I learned and I'm still learning neat tricks they each can do.

Hi NFITC, you mention a 1.5.0 version but I don't see any links to it anywhere.  Also, are you planning on releasing the source at all?

It’s still not ready, and yes. This update is super ambitious so I want to make sure it’s right. It’ll have multilingual support too. Source will soon follow, but it’s mostly garbage TBH.

General discussion / Re: Elemental Materia
« on: 2019-01-04 13:20:51 »
No. Either just applies the "attempt to cause status to enemy" flag which has a singular use per action. Multiple hits would cause multiple attempts, but in the case of sleep you'd just as likely cause it then the next hit will snap the target out of it.

Pages: [1] 2 3 ... 115