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 - Terence Fergusson

Pages: [1] 2 3 4 5 6 7
1
I was speaking more in generalities since I haven't looked at any of this in detail (and can't at the moment). I did forget about the "never miss" weakness too, but I don't think that's ever used for elemental damages, is it? Just statuses, right? Actually, when I wrote this I was only half awake so I wasn't really paying attention to what I was writing. :)

Um, other way around.  'Auto Hit' is never used for status chances.  No weaknesses/immunities/resistances, even to 'status' elements, affect status chances.  Auto Hit affects the PAt or MAt of the ability itself, allowing it to connect in the first place before it even worries about whether statuses are hitting.  Weakness/Resistances can affect PAt and MAt as well, but only if the ability has a Power of 0 (and is thus not intended to cause damage anyways).

Where does "Never miss" fall into that?

It really doesn't, seeing how it doesn't affect damage at all.  Unless otherwise specified, the game remembers all the weaknesses, absorbs or immunities it hit... it just doesn't care to remember *which* elements were weaknesses, absorbs and immunities, or how many of each there were.  So Auto Hit gets checked for during the hit chance calculation (along with a bunch of other things that can cause auto hit, like Death or Immunity (the latter so it can properly throw away the status inflictions and print up a big fat 0 damage).


I think these are handled like elements because of the "Never miss" effect Terence reminded me of. If the action is supposed to do "sleep" then it will always hit and always inflict. Change that modifier to double-damage and it will do just that.

Nope.  Nothing in the game has an Auto-Hit weakness to a status ability, in the first place.  Even if they did, they'd just cause the attacks to always hit (Lucky Evade could dodge physical auto hits, but enemies don't get Lucky Evades), but the infliction would still have its original chance.  There's only three enemies in the game with an Auto-Hit weakness, and they're all 'weak' to Punch.

Instead, enemies are either Weak to or Absorb these 'status elements'.  Weakness just doubles the damage if the ability does damage in addition to inflicting the status.  If it doesn't do damage, it doubles the hit rate of the ability (but not the status infliction chance).  Absorb will just toggle the Restorative bit, allowing the enemy to heal from any damage the ability inflicts and swap status infliction with status removal and vice-versa.

Honestly, most of this is all in the Battle Mechanics Guide (though I guess I don't make it clear enough that weaknesses/resistances/etc don't have any effect on status infliction chances).  Pretty much everything in Section 3.2 Status and Elemental Resistance is dealt with during the first routine I mentioned that collates all the resistances together so that everything else that comes after can just ask whether the ability was Absorbed, Resisted, etc and not worry about *which* elements are used anymore.

2
I bet it would be, but it'd take some creative re-writing. What the game does is it takes that elemental modifier on an enemy and plays with the damage in a function depending on the value. To add more values you'd have to recreate the table it currently uses then add your own:

Far, *far* more complicated than that.  First, there's 8 levels of resistance: you forgot Auto Hit weakness (as opposed to Death Weakness and Double Damage Weakness).  Secondly, the system's split into at least two parts: the setup that collects element *and* status resistances into a single dword that's set, which is then called by everything that cares about it (which is a lot, though most just care about Death Weakness and Restorative).  That's widespread code changes required to allow for more element differences (especially given that the setup routine uses 16 dwords worth of stack space to collate all the element and status resistances before combining them).  Changing this would not be trivial.

Based on the way the damage is calculated it will (I believe) take all the elemental modifiers the attack is based upon and calculate damage that way. Kujata is a good example to use.

It does take all elemental resistances, but it doesn't use all of them.  The only three that can interact are Absorb, Double Damage Weakness and Half Damage.  Death, Full Recovery and Immunity override all of the above (and they have a priority which goes Death > Full Recovery > Immunity, so there's no clashes there either).

* No-one yet knows which variable(s) store dragon force data. We could try and find out, though.

I'm pretty sure this isn't stored in the range of the AI's memory addresses. Dragon Force itself is just a status that "prevents you" from stacking the bonuses it gives.

Dragon Force is not a status: it just does the same thing as Hero Drinks, except to different stats with a different value.  So it can stack with itself just as well as any other StatMod-modifying routine can.  And those modifiers are stored in 'Object Block #1' (which has other fun stuff like whether the character has had its item stolen, or how much time is left on various status effects), and is impossible for scripting to reference.

3
General Discussion / Re: Invincible Ultimate Weapon Glitch
« on: 2010-07-22 04:19:08 »
Here's my theory (someone feel free to back me up on this). Initiating a battle with Ultima Weapon(s) runs a specific field script that looks at GlobalVar:007B. If that value ANDed with 4 is 4 then the GlobalVars listed above are set appropriately to give him 20000 HP. However, when run from the Debug room, this script isn't active. Therefore, it doesn't reset his HP from 0 and the battle will load his initial HP to 0 and continue ad infinitum.
Not quite.  Check the Enemy AI for the Mideel version of Ultimate Weapon, which is the very first time you're *meant* to fight him.  That's the one that actually sets the Global Variable for Ultimate Weapon's HP correctly.  Later battles with Ultimate Weapon expect the Global Variable to have been set, and so just overwrite the current HP with that value.  So if you skip the Mideel battle, future battles with Ultimate Weapon are going to start him with 0 HP.  Since, as you state, Death requires a change in HP to 0, the Counter:Death script won't run (which is the requirement to set UW to have 20000 HP for the final battle).  Instead, the Counter:General script runs, and that doesn't care how low UW's HP is, so his HP will still be 0 for the final battle.

2. Why is he (trying to) using Ultima Beam every round? He's only supposed to use that once every five rounds.
Um, not in the final battle he isn't.  His AI is simply a 50% chance of Ultima Beam or Thunderball for that battle, with the requisite counter attack of Shadow Flare when he dies.

4
FF7 Tools / Re: Welder: A little AI Template Project
« on: 2010-06-16 01:40:53 »
This is very new information to me. And, I think, to other board members - more than once, I've heard people warn each other not to let different creatures use the same LocalVar numbers. I suppose the assumption was that 'Local' referred to a battle-only namespace, as opposed to global vars.

Well, my very first post on the subject of AI scripting all those years ago did show where each set of variables were mapped to: such that 0000-1FFF and 4000+ were mapped to blocks that were unique to each object, but any call to 4000 would retrieve *all* blocks rather than just the object's own block.

Which brings up another thing I've noticed in this thread which is ill-advised: don't use LocalVar 0400 or higher.  Only 128 bytes are given to each enemy, so anything higher than that will start overwriting other data.

So it's bytecode, huh? Do portions of the AI scripting code have 1:1 relations to the binary they eventually yield? Is it bytecode in the sense of 'generalized, partially abstracted ASM'? That surprises me, actually. Especially considering how complex things like calling for targets would be on the machine level.

Just because something is bytecode doesn't mean it's machine code.  It's just a form of code that can be quickly read by an interpreter (in that the operands are all single bytes).  Game designers don't program enemies, rooms or other scripts in bytecode: they use some higher level custom language (usually designed specifically for the game), which they then compile down into an easier format for the game to read.  The resulting code doesn't take up very much memory and is relatively fast to run compared to translating human readable code in real-time (which would be both slower and take up more space).

I don't have access to the code right now, but IIRC, Ultima Weapon uses a very verbose method of storing its HP in a GlobalVar.

It's only verbose because AccessGlobalVar can only read and write Bytes.  So storing what requires at least 3 bytes is going to require a bit of maths.  There's obviously going to be some compiler artifacts around in the code, which is why a lot of the enemy scripts can be rewritten to be more efficient in bytecode, but some of it is just working around the limitations of the system.

5
FF7 Tools / Re: Welder: A little AI Template Project
« on: 2010-06-13 23:25:01 »
The issue seems to be that 'Leaders' aren't changing data in LocalVars as part of their Counter:Death scripts.

No, the real problem is that LocalVars are *specific to the object that uses them*.  You can't change Object 1's LocalVar:0000, and expect to read the changed value out of Object 2's LocalVar:0000.  They're two completely different variables.

Look at Warning Board's script for examples of how to use the Battle Player Block to use the specially set aside variables in the Battle Player Block to change the behavior of other enemies ([41A0], [41C0], [41E0] and [4200] at least are set aside for this).

Also look at Manhole's script on how to use *Battle* Variables for storing information ([2180]/[2190]/[21A0] at least are set aside for this), which any enemy in battle can use.


6
Troubleshooting / Re: FF7-PC Item Creation
« on: 2010-05-27 02:20:07 »
How much info do we actually have on the attack anim format? There must presumably be 'checkpoints' for launching into other animations, but how are they implemented?

The last I saw on it was in this thread on Action Opcodes posted by Akari.  It's certainly not my field, at any rate, but there's enough progress there for someone who's already looked into it to maybe suggest an answer.

7
Troubleshooting / Re: FF7-PC Item Creation
« on: 2010-05-27 00:54:11 »
I assume he means one or the other, rather than both. At any rate

His very first post on the thread specifies he wants both HP and MP.

Also, it doesn't matter how you name the second spell, it won't get named.

And yet, if you give the 18 01 ability to Potion, it will cast Cure2, but name it Hi-Potion.

NFITC1, I'm not sure what you're asking - as a rule, the one animation gets completed, before the next proceeds. Excepting the limits, the effect usually just resembles W-Magic / W-Item / etc., with two discrete and separate visual effects.

He's referring to the fact that the only abilities that canonically used this ability were those that can apparently already handle the job without printing the attack name or animation twice.  Finding out *why* would be an important step in seeing if it's possible to use it better for other attacks.

8
Troubleshooting / Re: FF7-PC Item Creation
« on: 2010-05-26 17:31:51 »
Going by what you've been asking in previous posts (an item restoring both half of HP *and* MP), I don't believe FF7 allows this to be easily possible.  Very few things affect both HP and MP at the same time, and none of them do exactly what you want.

So the next best thing would be to create an item that calls an additional effect.

Item: FF FF FF FF FF FF FF FF 2D 00 F8 FF 01 02 24 10 00 FF 18 7B FF FF FF FF 00 02 FF FF

Setting this as your item will cause it to heal half your HP, and then run the effect of the spell 0x7B.  0x7B is unused (it's immediately after the Blade Beam secondary effect), so you can set something like this in it:

0x7B: FF FF FF FF FF FF FF FF FF FF FF FF 01 02 24 10 00 FF FF FF FF FF FF FF 00 02 FE FF

This does exactly the same thing as the item, but affects MP instead.  Also note that this is the *Spell ID* 0x7B, not the Item ID: the 0x18 special effect can only target spell IDs.

The drawback to this method is that when using the item, the item throwing animation will occur twice, once for each effect.  Also, a blank message box will appear when performing the second effect -- this blank message box seems to be reading names from the item name table too, so just giving 0x7B a name might not work.  Someone better acquainted with animation IDs and setups might be able to help fix those.

9
FF7 Tools / Wall Market, FFVII KERNEL.BIN editor
« on: 2010-03-30 19:13:50 »
Battle Victory - What is the id of this script?

0x6.  So immediately after Magic Counter and immediately before PreTurn.  Though looking at the proposed name for it again, I'm no longer as sure about that name... battles can end in other states than simply Victory, and I'm not sure of all the conditions that 0x6 fires on (I just know that it doesn't fire on Ally Death and definitely waits until the end of battle to apply its affects).

Doesn't matter though: I'm sure Akari knows where all the hooks are better than I -- I'm working on information I dug out years ago.

10
FF7 Tools / Wall Market, FFVII KERNEL.BIN editor
« on: 2010-03-30 18:31:57 »
Going back to this, could it be accurate to call this section "Battle Victory" and sections 8-15 be "Custom Event"? I can't get any scripts 8-14 to fire (The Midgar Zolom is acting really weird. Executing script that I erased and confirmed isn't in the scene anymore. Spooky...), but that's likely what they would do.

I'd pretty much agree with that naming scheme, yes.  If any further information about how they can be used turns up, it can always be changed again.

11
FF7 Tools / Wall Market, FFVII KERNEL.BIN editor
« on: 2010-03-30 16:12:14 »
While on the subject of Diamond weapon, maybe you can clarify something for me. At the end of his Death-Counter Script he's got a 60 22 60 0F 92 command that Akari told me that means execute script section 0F. He doesn't have anything in his Post-Battle section. It's possible that this interpretation of the 22 command is wrong and it doesn't execute scripts. Do you have any idea what this does?

All I know about 0x92 is that it shoves the command, ability and targetting data onto the ability queue (stored at 009A988C, which can hold up to 64 queued abilities), and the priority usually depends on either what part of the AI script is running or what type of player ability is used (although there are also possibly exceptions to that).  I'm fairly sure Akari's done more work than me on the scripting engine, so I cannot confirm or contradict his findings.  I know that during a simple test I did I was unable to use 0x22 to run arbitrary script IDs, but I still don't know any firm details about what it does.

This is also very interesting. I didn't know that White Wind and "? ? ? ?" are considered physical attacks. That would explain why White Wind sometimes flashes the screen as if it were a critical attack. This would be a real simple change to make too.

Be aware that although the chance of a critical hit will be calculated, not all attacks will use the Critical Hit modifier.  In fact, I think only the Physical Formula uses it, and since Critical Hit chance is only used with the Physical Attack Types, it doesn't seem possible to get a Magical Critical Hit without editing the executable, even if you used a Magical attack using the Physical Formula.

The Weapon Special Formulas will all use the standard Physical Formula as a base though, rather than replacing it entirely, so they can work with Critical Hits when given the opportunity.

You might also want to test out the various Attack Types and Formulas yourself so you can think of better ways to describe them from the point of view of a modder: the way I've described them is somewhat concise, but not always as clear as it could be.

12
FF7 Tools / Wall Market, FFVII KERNEL.BIN editor
« on: 2010-03-30 14:27:54 »
The timing on this always occurred after damage was calculated. That's now things like this can happen (Red XIII is my test subject for most of these). I gave him a simple "Display string: 'Script 07'" script for that section and it showed up at the end of the action being performed. In retrospect that might not be the best way of telling since displaying strings will wait until the end of the currently happening action to display. "Post-Attack" just seemed logical because that's when you'll see the effects.

The problem is that it simply isn't true that it occurs after damage calculation.  If that was the case, Limit Breaks simply *wouldn't work* against Diamond Weapon until he begins his countdown.  Note his PreTurn counter: he specifically checks if the skill being used is Summon, W-Summon or Limit, and if this is the case, he will turn off his Physical Immunity for just that attack.  As a result, this has to occur before damage is calculated, otherwise the limit would just do nothing, and the timing for his invulnerability being turned off would not be as observed.

EDIT: Oh, and yes, strings and attacks would only show up after the current action due to the standard queue system.  There's only so much this counter can do, but at least it can juggle variables fine without relying on queuing.

I think Akari's been trying to convince me of that for a while. I'd love to add it, but I can't really tell what they all do. The only reason I haven't done so yet is I haven't figured out what the values are. I know that the upper nibble and lower nibble are significant of each other.

Akari can probably give you more details, but it's mostly pretty straightforward.  You have the basic Attack Formulas:
Code: [Select]
x0: No damage
x1: Physical Formula (Pwr / 16) * (Stat + [(Lvl + Stat) / 32] * [(Lvl * Stat) / 32])
x2: Magical Formula (Pwr / 16) * ((Lvl + Stat) * 6)
x3: HP% Formula
x4: Max HP% Formula
x5: Cure Formula (Pwr * 22) + ((Lvl + Stat) * 6)
x6: Fixed Formula (20 * Pwr)
x7: Item Formula (16 * Pwr)
x8: Full Recovery
x9: Throw Formula
xA: Coin Formula

And the Attack Types are essentially:
Code: [Select]
0x: Physical, no hit checks
1x: Physical, Phys Accuracy, Crit Hit
2x: Magical, Mag Accuracy
3x: Physical, 100% Hit
4x: Magical, 100% Hit
5x: Magical, 100% Hit
6x: Physical, Phys Accuracy, Crit Hit, uses Special Formulas
7x: Magical, Mag Accuracy, uses Special Formulas
8x: Magical, uses Lv?-Based condition
9x: Magical, uses Manipulate Accuracy
Ax: Physical, Phys Accuracy, Crit Hit, uses Weapon Special Formulas
Bx: Physical, Phys Accuracy, no Criticals

I'm not sure what the difference is between 4x and 5x, if any exist.  And you have most of the Special Formulas already, and the Weapon Special Formulas can all be found by matching from the Weapon Data.

13
FF7 Tools / Wall Market, FFVII KERNEL.BIN editor
« on: 2010-03-30 07:04:23 »
Since I've got a bit of time and was poking around stuff, I thought I might as well clear this up.

Code: [Select]
Char Level H MHP L MHP

Cloud: 7 334 323
Cloud: 12 474 441
Cloud: 22 955 892
Cloud: 32 1753 1658
Cloud: 42 2806 2639
Cloud: 52 4069 3826
Cloud: 62 5435 5123
Cloud: 82 7834 7381
Cloud: 99 9554 9007
Code: [Select]
BaseDifference = 40 * CurveBase + (level - 1) * CurveGradient  [CurveBase is between -128 - 127 inclusive]
Difference = (1 .. 8) + (100 * BaseDifference / CurrentMHP) - 100   [capped between 0 and 11; L MHP uses 1 and H MHP uses 8]
NewMHP = CurrentMHP + Floor(RandomBonus(Difference) * CurveGradient)

Your problems are twofold.  First, you were rounding (100 * BaseDifference / CurrentMHP) to the nearest number, not rounding down/truncating.  As such, it's really no wonder your ranges are much higher than they should be.  If you rounded down, you'd get the theoretical base range of 8965-9508 for Cloud at L99.

But that's still not the fulll range of 8960-9511, of course.  Why is that?  Simple:
Quote from: Party Mechanics Guide
But, you should know that achieving max HP requires that you must take lower than max gains at some levels....

At L11, Cloud's HP range is 385-410, which matches the "always take lowest gain" to "always take highest gain" values.  But at L12, the correct range is 435-472, not 439-464 as you might expect.

If you had 410 HP at L11, your difference would be 2% of the baseline of 422, giving you a maximum HP Gain of 1.3 * 42 = 54.  So 410 + 54 = 464.

But if you had 409 HP at L11, your difference would instead be 3% of the baseline of 422, giving you a maximum HP Gain of 1.5 * 42 = 63.  So 409 + 63 = 472.

It's not a huge increase, and the lower HP quickly catches up, and in fact can still get to Cloud's highest max HP from that value... but this example just showcases the mechanic that makes even more of a difference at higher level, where there's less chance to catch up and every point counts.

Oh, and you can easily test the 'base' range ingame by simply altering the executable at the HP/MP growth stage and get it to always spit out 1s or 8s, and then just level from 6 to 99 quickly (easy if you also set Cloud's starting XP to a large enough value).  Obviously, this won't get the true range (and you can't without a far more complex and time-consuming routine), but it'll be close enough.

EDIT: I also just found an error in his example:
Quote
The minimum for him in that level bracket would, of course, be 40% of 98, or 58 (remember to round down).
40% of 98 is not 58, it's 39. 58 is ~60% of 98

That was a by-hand example, and yeah, looks like I took 40% of 147 instead.  My apologies on that.  The actual range data was calculated via a program, and have been proven by people after Max Stats (although FF7's crappy RNG meant that a new path had to be found by someone because it's impossible to get both Max HP and Max MP at the same time).



And while I'm taking a quick look at things, I'll note the following about certain things in Wall Market/Proud Clod.

AI Trigger: Ally Death: This trigger is actually run at the End of Battle, not on Ally Death.

AI Trigger: Post-Attack: This is a far worse name than what I've tended to call it (PreTurn).  I never called it PreTurn because I thought it happened as soon as someone's Time Bar finished filling.  I called it PreTurn because it happens before whatever command you enter gets to do things.  You could call it Pre-Command, I guess, but since it's triggered by any queued command (including Poison damage, I believe), it's a really difficult thing to name.  The point is that the changes it makes all occur before the attack is run.  Of course, an enemy can't use it to attack before you hit due to the attack queue, but it can certainly do stuff like alter its invincibility state or evasion before your attack even connects.

Battle-specific Party AI: Proud Clod could use the ability to set/change the Battle specific AI data for party members.  Much like Enemy AI starts at 0xE80 with 3 records (one for each enemy), Party AI starts at 0xC80 with 4 records (one for each enemy formation).  This is used in FF7 to deal with things like removing Waterpolo from a dead party member, but it has the potential to be used for so much more.

Attack Data: Attack Damage: You really need to split this up into the two different pieces of data it really is: the Attack Type and the Attack Formula.  The Attack Type dictates whether the attack is Physical or Magical (and thus whether Att or MAt is used), whether there will be a Critical Hit or not, what type of accuracy is used, and whether any custom formulas must be used.  The Attack Formula dictates how the damage is calculated, and with the exception of Attack Types 6, 7 and A, the formulas work the same no matter what the Attack Type.  Being able to set both Type and Formula individually offers far more customisation.

14
One question regarding co.bin. I'm looking at the second file and it's all easy enough stuff to read (the first file just looks like a graphic of some sort). 384 rows of seven values of BP and slot index. Does the mechanics pick an slot config based on three rows at a time or something more complicated than that?

Ex.
Battle Arena wants slot config 100. Does it take from rows at 0x20D0, 0x20EC, 0x2108 (consecutive rows) or from 0x0AF0, 0x15E0, 0x20D0 (correlated rows) or something like that?

Consecutive.  The code for, say, calculating earned BP is at 006E37A3, and that should demonstrate how FF7 expects the data to be laid out.

15
You're reversing each dword.  It should be: 00 00 00 00 00 00 01 0E 0E 0E 02 0E 03 04 05 06 07 08 09 0A 0B 0C 0E 0D

And anything marked 0E is skipped at this point: it uses a further array that covers only those values later.  All the Break Materia routines are under 00, anyways.

I didn't know these were dwords, actually, and just read them as plain bytes. ;)

They aren't dwords: I'm just predicting what your debugger/disassembler was doing when you were reading this code.  A hex editor used on FF7.exe confirms that they're in the order I stated, when taken as an array of bytes (which is exactly how FF7 reads them in this case).

16
A few things:

It looks like the game chooses from an array of 24 values as follows:

00 00 00 00 0E 01 00 00 0E 02 0E 0E 06 05 04 03 0A 09 08 07 0D 0E 0C 0B

You're reversing each dword.  It should be: 00 00 00 00 00 00 01 0E 0E 0E 02 0E 03 04 05 06 07 08 09 0A 0B 0C 0E 0D

And anything marked 0E is skipped at this point: it uses a further array that covers only those values later.  All the Break Materia routines are under 00, anyways.

Now if you look carefully, this leaves out eight slots:

Poison
Toad
Mini
Seal Items
Lucky 7
Weapon broken
Armor broken
RestoreHP

Needless to say I'm quite confused. Can someone tell me where these slots are handled?

Lucky 7 simply never does anything.  Weapon and Armor Broken are set up in the second list of routines, and simply halve your Att or Def (they don't touch your equipment).  The rest simply set bits in 00DC3BA0 which is handled sometime later: I'm not entirely sure when.

Look at 0B! I don't remember seeing that in the arena before.

That's because it can never be called.  FF7 instead has a table of 128 different reel variations, one of which is chosen at "random" (or rather, it just takes the current time and mods it by 128, and that's the reel set it uses) when this run of the battle arena begins.  Each reel variation has all 21 possible disadvantages over the 7 reels that will be used for the upcoming series of battles, as well as their associated BP bonuses.  0B is not used for any one of them.

The full table's in the 2nd file in co.bin, in case you're interested.

Code: [Select]
dword (SomeLimitFunction(dword time)
{
   dword some_var;

   if (time >= 360000 )  //this is 100 hours in seconds.
      time = 359999;     // 99:59:59 which happens to be the game's max

   some_var = ((time / 41100); //11:25:00; No remainders. Max result of 8
   some_var = some_var * 10;  // some_var is now, at most, 80.
   time = (time mod 41100); //it was passed by value so this doesn't really change anything. No remainders. Max of 9
   some_var = (time / 4110) + some_var; //some_var is max of 89.
   return some_var;
}

Once again, you're reversing your words.  It's 0x8CA0, not 0xA08C.

17
But apart from that random variable (which really cant be random) I believe he got most of the mechanics correct. So i guess my actually interest is that "random" one and its actual behavior.

http://en.wikipedia.org/wiki/Pseudorandom_number_generator

It is a "random" variable... for a given meaning of random.  However, just because they used a fancy algorithm doesn't mean it's a *GOOD* random number generator.  In fact, it's a pretty crap random number generator.  *All* of FF7's generators are crap.  The only reason you're noticing *this* one is because only a few things call it, as opposed to other generators in the game that are called almost all the time, muddying the results.

Your 2nd variable is the seed, from 0 to 255.  This is used to look up a table containing 256 numbers already distributed from 0 to 255 in a seemingly random manner... which is pretty much how FF7 gets almost all its random numbers.  Every time it wants a "random" number, it increments the seed by 1 and gets the next "random" value in the table.

Your 3rd variable is the offset, which is an extra little thing FF7 is doing to further muddy the waters.  Once it gets its "random" value, it subtracts this offset from the value.  And there it has a "random" number.

So for your example, with a seed of 76 and an offset of 0, it'd look up the 77th number in the table, which happens to be 3, and then subtract 0 from that.  So it returned the "random" number of 3.  This has to be less than [Danger Counter * Enemy Lure Value / 256].  A Danger Counter value of 1023, when divided by 256, would return [3.996] = 3.  So no battle, since the "random" number is not less than that.  But if it were 1024, that would return 4.  Since 3 < 4, well, there's your battle.

You noticed that it actually incremented the seed by *2* per Battle Check... the first of those is actually it comparing the first "random" value it picks to the Pre-Emptive chance, to see if you get a Pre-Emptive battle.  Yes, it does this each time, even before it knows whether you'll be getting a battle or not.  There's also a bunch of other things that also use this seed, as well as a couple of things during the Battle Check that use the same random table but with a different seed (like an even *simple* PRNG that decides what battle you'll get next), but it all gets kinda immaterial after that.

 ===

The bottom line is this.  Yes, it's not *truly* random.  It's not even a good use of a pseudo-random number generator - it's among the crappiest I've seen, really, seeing how it's a bad random number generator (strike 1) that's used in a terrible manner (strike 2).  (Of course, even good random number generators used in a terrible manner can suck: just take a look at Golden Sun for an example there)

However, without actually doing the maths every time you want to check something, there is absolutely no way to predict when and where you'll battle beforehand.  The rules may be simple, but they produce complex results and the only way to know what you'll be battling is to run through the numbers.  So there is no benefit to knowing how this works, and as such, I will likely never cover it in any of my guides seeing how it's far too technical.

Do you remember why I continually recommend to people doing Chocobo Breeding, that when they continually keep getting the same Chocobo when they really want a different one, they should run in and out of the barn a few times to 'generate' new random numbers instead of just resetting and reloading?  It may be a different random generator, but it's the same principle here: it's a pseudo-random number generator that doesn't have its seed updated every millisecond, and the only way to have things happen differently than before is to have more "random" things happen that depend on that generator.

So if you're going to do any analyzing, I'd suggest you focus on what is actually happening in the game, rather than on the numbers behind it... because with a 256 order seed with 256 possible values for the offset... that gives you a sequence of 65536 random numbers before it repeats.  There's also a few uses of that particular seed that increments the seed by 1 but *doesn't* increase the offset if it overflows, which can *further* complicate this whole mess.  Given different Area Encounter Values, whether you're walking or running, and how many other things update the seed, I don't think you're going to get any useful information out of the mechanics behind it all.

18
From my old notes (and since I'm idle enough to post):

Code: [Select]
File003: Character Stat Growth, Growth Requirements, Basic AI Scripting

0x000: Cloud - Str Curve ID
0x001: Cloud - Vit Curve ID
0x002: Cloud - Mag Curve ID
0x003: Cloud - Spr Curve ID
0x004: Cloud - Dex Curve ID
0x005: Cloud - Lck Curve ID
0x006: Cloud - HP Curve ID
0x007: Cloud - MP Curve ID
0x008: Cloud - XP Curve ID
0x009: Cloud - FF (padding)
0x00A: Cloud - Starting Level
0x00B: Cloud - FF (padding)
0x00C: Cloud - Limit Command 1-1
0x00D: Cloud - Limit Command 1-2
0x00E: Cloud - Limit Command 1-3 (UNUSED)
0x00F: Cloud - Limit Command 2-1
0x010: Cloud - Limit Command 2-2
0x011: Cloud - Limit Command 2-3 (UNUSED)
0x012: Cloud - Limit Command 3-1
0x013: Cloud - Limit Command 3-2
0x014: Cloud - Limit Command 3-3 (UNUSED)
0x015: Cloud - Limit Command 4-1
0x016: Cloud - Limit Command 4-2 (UNUSED)
0x017: Cloud - Limit Command 4-3 (UNUSED)
0x018: Cloud - Kills required for Limit Level 2
0x01A: Cloud - Kills required for Limit Level 3
0x01C: Cloud - Uses required for Limit 1-2
0x01E: Cloud - Uses required for Limit 1-3 (UNUSED)
0x020: Cloud - Uses required for Limit 2-2
0x022: Cloud - Uses required for Limit 2-3 (UNUSED)
0x024: Cloud - Uses required for Limit 3-2
0x026: Cloud - Uses required for Limit 3-3 (UNUSED)
0x028: Cloud - HP Divisor for Limit Level 1
0x02C: Cloud - HP Divisor for Limit Level 2
0x030: Cloud - HP Divisor for Limit Level 3
0x034: Cloud - HP Divisor for Limit Level 4
0x038: Barret (as above)
0x070: Tifa (as above)
0x0A8: Aeris (as above)
0x0E0: Red XIII (as above)
0x118: Yuffie (as above)
0x150: Cait Sith (as above)
0x188: Vincent (as above)
0x1C0: Cid (as above)

0x1F8: Random Bonus to Primary Stats (12 records, 1 byte each)
0x204: Random Bonus% to HP (12 records, 1 byte each)
0x210: Random Bonus% to MP (12 records, 1 byte each)

0x21C: Primary Stat Curve  0 - L 2-11 Gradient
0x21D: Primary Stat Curve  0 - L 2-11 Baseline
0x21E: Primary Stat Curve  0 - L12-21 Gradient
0x21F: Primary Stat Curve  0 - L12-21 Baseline
0x220: Primary Stat Curve  0 - L22-31 Gradient
0x221: Primary Stat Curve  0 - L22-31 Baseline
0x222: Primary Stat Curve  0 - L32-41 Gradient
0x223: Primary Stat Curve  0 - L32-41 Baseline
0x224: Primary Stat Curve  0 - L42-51 Gradient
0x225: Primary Stat Curve  0 - L42-51 Baseline
0x226: Primary Stat Curve  0 - L52-61 Gradient
0x227: Primary Stat Curve  0 - L52-61 Baseline
0x228: Primary Stat Curve  0 - L62-81 Gradient
0x229: Primary Stat Curve  0 - L62-81 Baseline
0x22A: Primary Stat Curve  0 - L82-99 Gradient
0x22B: Primary Stat Curve  0 - L82-99 Baseline
0x22C: Primary Stat Curve  1
0x23C: Primary Stat Curve  2
0x24C: Primary Stat Curve  3
 .....................
0x44C: Primary Stat Curve 35
0x45C: Primary Stat Curve 36
0x46C: HP Stat Curve 37 (Base multiplied by 40)
 .....................
0x4EC: HP Stat Curve 45 (Base multiplied by 40)
0x4FC: MP Stat Curve 46 (Base multiplied by  2)
 .....................
0x57C: MP Stat Curve 54 (Base multiplied by  2)
0x58C: EXP Curve 55     (Gradient is quadratic, no Base)
 .....................
0x60C: EXP Curbe 63     (Gradient is quadratic, no Base)

0x61C: Character AI Data (12 Objects, see below)
0xC00: FF Padding
0xE1C: Random Number Lookup Table - 256 numbers from 00 to FF used by the RNG to return pseudo-random numbers
0xF1C: Scene.bin File Lookup Table - 64 bytes
       Each byte contains the ID of the first file in the specific 8192 byte block in Scene.bin
       For example, the first four bytes in this table are 00 0C 12 19
       This means that the first 8192 bytes in Scene.bin holds the compressed data for files 00 to 0B, while the next
          8192 holds the data for files 0C to 11 and so on
       Support is here for 64 blocks of 8192, and only 33 blocks are used, so there is a lot of empty space available

0xF5C: Spell Order in Inbattle Magic Menu - 56 bytes
       This is the ID order for the way spells are displayed in battle
          00-1F means Restore Magic
          20-3F means Attack Magic
          40-5F means Indirect Magic
          60-7F means Advanced Magic (always last)

*Regarding AI*
Cloud, Barret, Tifa, Aeris and Yuffie have AI Data regarding Battle Affection.  This adjusts a variable that starts at
   100 either up or down depending on what happens in battle.  This value is definitely not used in the date,
   and can probably be thought of as a working system whose effects have been dummied out.

Vincent's Limit AI data is stored here, but is only run when his AI Mode is turned on.
Sephiroth's AI data is stored here, and his AI Setup subroutine automatically turns on AI Mode at the start of every
   battle.
There's a 12th Object, but it is both unused and there is no hint as to who it might've been meant for.  Consider
   it padding.

19
Archive / Stealing Rates
« on: 2006-01-05 14:53:19 »
Quote from: smithie
The only problem with this method is that the engine allows for monsters that exist within different scenes to have different stats, so when modding you will not be able take advantage of this.


The correct method to deal with that is to make a new enemy, not modify a single Scene file.  Modifying encounters to be 'special' when they're not already a unique enemy requires that you know exactly where this encounter appears.  Please note the Battle Square example I've already brought up.  Most encounters that should be unique already use a unique monster anyways.

Quote from: smithie
Another thing about the battle square, you wouldn't happen to know what the bonus is that monsters within the battle square have applied to them. They are deffinatly harder even without penalties, to kill than they're standard form.


Enemy Mechanics FAQ.

Quote from: The Skillster
Try to remember that the field file calls up the IDs for the scene files it wants to use.
From there it uses the Fight IDs/Formation IDs, which are unique.


<sigh>

It really helps if you know what FF7 expects from its Scene.bin file.

Scene.bin contains 256 sub-files, which are compressed and divided up into several 'segments' of 8kb each.

Each 8kb segment contains 16 4-byte offsets at the start, allowing up to 16 files to be allocated to this segment - this offset list takes up the first 64 bytes.  Each offset is multiplied by 4 before used, so the first offset is always 0x00000010.  These files are individually gzip compressed and stored.

So, when FF7 wants a particular scene file, it must know two things: (1) which segment to check, (2) which file in the segment to decompress.

Both (1) and (2) are handled by a table in one of the kernel.bin files, which has the ID of the *FIRST* file in each Scene.bin segment.  FF7 can support up to 64 segments leading to a maximum Scene.bin size of 512kb.  However, the standard English PC version only requires 33 segments, leading to a size of 264kb.  (Note: The French version of Scene.bin requires 34 segments, leading to a larger size and an obvious adjustment in kernel.bin - the two files are thus incompatible without a modification of kernel.bin)

So, when it wants, say, the Sample:H0512-opt fight, it will know it has to look for Encounter 456.  (Note: I am going to use my standard calculation where the first file of Scene.bin is *0*, not 1, which is exactly how FF7 uses its IDs)  The Scene file we need is thus [456 / 4] = 114, and it's the first encounter of that file.  Now, we look up Scene 114.

From the table in Kernel.bin, FF7 knows that Scene 114 is contained in the 14th segment of Scene.bin, and is the *first* file in that segment.  So, FF7 fetches that segment and then fetches the 1st file of that segment and decompresses it.  It now has what it believes to be the correct scene file, and will act accordingly.

If, however, due to editing, one of the previous scene files is just a little bigger after compression than it used to be... you may find that you can't fit the original files back into their original segments.  Not know exactly how the program you're using works, I'm willing to bet it's pushing them into the next segment instead.  Which is all well and good, but without kernel.bin being updated, FF7 will still believe that Scene 114 is the first file in the 14th segment of Scene.bin.

In our possibly not so hypothetical example, Scene 113 no longer fits in the 13th segment, so got shoved into the 14th segment instead.  It's now the first file in the 14th segment.  Scene 113 no longer exists: FF7 now believes that this is now Scene 114.  So it loads up the Sample:H0512-opt fight, and wouldn't you know it?  A Zenene approaches.  Command?

And of course, this creates a domino effect where later encounters from that same segment are also affected.  Instead of Hundred Gunner, say hello to Sample:H0512-opt.  Instead of Rufus, I hope you like having solo-Cloud for a Hundred Gunner/Heli Gunner fight.  Rufus will be ambushing you on the highway *AND* in the swamp, and you'll get random Midgar Zolom encounters in the Mythril Mines.  And all this continues until there's enough space in a segment to fit all the Scene files FF7 expects and the IDs match up again.

So now do you see the problem?

20
Archive / Stealing Rates
« on: 2006-01-05 01:17:53 »
Quote from: smithie
It doesn't have any nasty effects on battle square. I've tried with a previous mod all the way up to a lvl 90 character, completing everything along the way including battle square. and didn't notice anything out of the ordinary, nor experienced any technical difficulties. There are two main places that the problem occurs (Shinra HQ & Wutia Tower) and is usually/alway's realated to monsters of the same type.


Just because you didn't see it doesn't mean it's not there.  There are four fights in each Group A and B for the 4th Battle, and you only see the Moth Slasher fights up until you get the Tiny Bronco, at which point they never again appear in Battle Square.  Had you fought enough time in Battle Square to face those particular battles?

Just because something only has a 25% chance of happening at a time that very few people will be doing a lot of Battle Square fighting doesn't mean it isn't a problem and doesn't mean it isn't there.  And like I said, it requires that you copied Scene 111 over Scene 110's data - you will not see it if you left Scene 110 alone and copied that over Scene 111.

 ===

As for where the fault lies, I haven't looked at the problems in question, and don't exactly have lots of time too, but #1 suspect would be whatever's putting the scene files back together again.  Final Fantasy 7 has many expectations on its data and stores some of these expectations in a lot of different places.  It could be something as simple as not packing the file correctly such that one of the compressed files exceeds the size FF7 expects.  Or it could be that the method of putting the files back together into chunks is suspect such that one of the files suddenly finds itself into the next chunk, and unless kernel.bin is also updated, this will effect other things.  (And such an action would effect more than just Gi Nattak's fight)

That said, I'm leery about any Scene Editor that looks at each of the Scene Files individually and not as a whole - really, all the monsters and attacks should be extracted from *all* the files and seperated out, sorted into ID order, and then edited seperately.  From there, you can compile all that back into their relevant Scene files (with the correct attacks and monsters updated exactly the same no matter *where* they appear) and then recompiled, possibly updating kernel.bin at the same time.  Of course, this is a lot more work, but it's the only really sensible way to do it.

21
Archive / Stealing Rates
« on: 2006-01-04 23:48:20 »
It most certainly does affect Battle Square if you, say, replace Scene 110's Encounter data with Scene 111.  One of the Group A 4th Battles (1x Moth Slasher) and one of the Group B 4th Battles (2x Moth Slasher) both exist in Scene 110, and the data that tells the game what the next battle *after* those are in Battle Square is also held in the Scene file.  If you overwrite that data, not only will Battle Square have a different fight if you happen to get either of those battles, but it will also quite likely end immediately after that battle (though not having tested fully, I can't be sure how it'll react).  Either way, this is not a desirable outcome, by any means.

Quote from: smithie
Not a noticable change, as its just the same monsters in a different formation, i think it may even be an unused encounter


It's multiple encounters.

Enc #436: 1x Moth Slasher
Enc #437: 1x SOLDIER:3rd, 1x SOLDIER:3rd (2nd Row)
Enc #438: 1x Moth Slasher, 1x Moth Slasher (2nd Row)
Enc #439: 1x Moth Slasher (Back Attack)
Enc #440: 2x SOLDIER:3rd, 1x SOLDIER:3rd (2nd Row)
Enc #441: 1x Moth Slasher, 1x Moth Slasher (2nd Row), 1x Moth Slasher (3rd Row)
Enc #442: 1x Moth Slasher, 2x SOLDIER:3rd (2nd Row)
Enc #443: 2x SOLDIER:3rd (Back Attack)

Enc #436-#439 are all found on Floor 67 (Before Escape).  Enc #436 and #438 are also found in Battle Square.  Enc #436 is *ALSO* on several floors of the 59 Floor Elevator battle.
Enc #440-#443 are all found on Floor 68 (Before Escape).

None of those encounters are unused.

The upshot of this is that, apart from the Warning Boards, you are replacing the encounters on Floor 67 with Floor 68, or vice versa.  And if you copy the wrong one over the other (ie Scene 110 gets overwritten with 111's data), then you break Battle Square as well if they happen to get those particular encounters.

This is not the sort of hidden after-effect I would at all like or expect in any mod, and if this one exists, then you'd have to be doubly sure other problems don't exist as well.  The source of this problem needs to be fixed.[/quote]

22
Archive / Stealing Rates
« on: 2006-01-04 16:04:38 »
Quote from: smithie
So, dont worry about it salk. However here is a fix in advance, scenes 110-111 have to be exactly identical. problems always occur with these two files. So after you have finished modding delete one of them and replace it with the other.


No, they must not be identical.  While the enemy data is the same (they use the same monster IDs, so the exact same monster data will be stored in those scene files for safe keeping), the *encounter* data is different.

Copying one over the other will at best change some of the encounters at Shinra HQ, and at worst, break Battle Square.

23
Quote from: Sir Canealot
I didn't mention FFXII's music.


My apologies then - it seemed like a standard "Uematsu is gone, nothing will ever be good again" post that I've seen a lot of around.  But...

Quote from: Sir Canealot
It's a case of those are Uematsu's songs, and anyone else touching them without his guiding hand is just stupid.


No, it really isn't.  Arrangements and mixes of other people's work are not uncommon, and sometimes add more than they take away.  Collaborations between different composers has happened very often in Squaresoft's history.

Take a look at Final Fantasy Origins.  Tsuyoshi Sekito arranged Uematsu's work for that, and it was pretty well received, so you can't exactly say it was a bad idea or that he did a terrible job.

And once again, I know there's certain tracks in FF7 that I really don't like.  Would another composer lending their own style to Uematsu's originals make them better?  Would it spoil the overall feel of FF7?  I can't say.  But I'm not going to state "no chance", because it most certainly *isn't* "no chance".  Yes, if an FF7 remake gets done in the far future, whoever ends up dealing with *any* part of the game is going to have a lot to live up to. But it's been done before and it has been done both well and badly, so again... it's a premature verdict.

24
Quote from: Sir Canealot
...and unless Uematsu does this there is NO chance of it coming out sounding good (by my standards).


Dangerously close to fanboy conventions there.

Funnily enough, Uematsu isn't the only decent composer around.  Hitoshi Sakimoto (who's *actually* doing the music for FFXII) was responsible for much of Final Fantasy Tactics and the entirety of Vagrant Story (among other things), both of which are masterpieces in their own rights.  Yasunori Mitsuda worked on Chrono Trigger, Chrono Cross and Xenogears, and that's quality work worth owning as well.  And then, on a non-Square theme, we have Tenpei Sato, who did Disgaea and Phantom Brave... Heaven's Garden is currently my favourite vocal piece, right after 1000 Words.

Furthermore, Uematsu has left Square, yes, but he is now *FREELANCE*.  Just like Mitsuda and Sakimoto.  Not being a Square-Enix composer doesn't mean he'll never work for them ever again.

The only real advantage Uematsu has over and above those I've mentioned is that he's been a composer for an amazingly popular series that has lasted over ten years.  This does give discussions about his work a lot of the power of nostalgia.  But not all of his work has been wonderful or appeal to all tastes.  Not all of Mitsuda's work appeals to me.  Not all of Sakimoto's work appeals to me.  Everyone has their off days.  That doesn't automatically make one composer better than another.

I think it's a little premature to write FFXII off musically.  Uematsu is certainly not the be-all and end-all of Final Fantasy composition.[/i]

25
Quote from: L. Spiro
When an enemy element attribute is listed as 0x01, literally, it means nothing.
The enemy will report itself as being weak to that element, but in fact it is a bug.

NO enemy is actually weak to Hit, Cut, Shoot, Shout, or Punch, even though they, as elements work just as the other elements do (namely in the formula for dealing damage).


Not actually a bug - you were right to be suspicious all that time ago.  It's just too bad we'd never have found it with just experimental testing, especially when so few enemies have it.

Just as 0x00 grants Deadly weakness and 0x02 grants Double Damage weakness, 0x01 gives the Unavoidable weakness.  Any attack that has this element and is used against an enemy which has 0x01 weakness to it, that attack will have a Hit% of 255.

(However, a Hit% of 255 can still be avoided if the attack is a physical hit - in particular, Luck-based evade can still work against it, if the target has higher Luck than you do)

Quote from: L. Spiro
As for #2, to my knowledge, we don’t know FOR SURE what these are.
In the case of 0x20, it could indicate the following element causes instant death.
The others are probably similar.


Found this a couple of months back at the same time I cracked 0x1 weakness.  These are *statuses* the target has 'elemental' weaknesses or immunities too.  They work differently from Status Immunities in that they don't affect the status itself (unless it's an elemental immunity) - instead, they affect the damage of the attack that is inflicting the status.

Ghost Ship, Dragon Zombie, Zenene and Ghost all absorb attacks that attempt to inflict the 'Death' status.  This means that they will, for example, absorb the damage from Hyper Jump, which is a non-elemental attack.  (Finishing Touch and Satam Slam are affected differently because they actually have their Death part seperate from the damage part).  On the other hand, Palmer, who is immune to the Sleep Status, is *WEAK* to attacks that inflict 'Sleep'.  Hades (if you could get it that early) or placing Seal/Hades+Added Effect on your weapon would both cause the respective attacks to deal double damage to him, even though he's immune to the status.  He won't *suffer* from Sleep status, but the extra damage will still hurt him.

Only the first 16 statuses in the code are able to be utilised in this manner.  Of course, as you'll note, only three statuses are actually *used* - and it's so rare, most people will never ever notice the difference.

Quote from: Lord_Skylark

But looking at the enemies with 20 at seem to be undead...could that possibly mean that they absorb Life spells, etc so that they would take damage from them?


Life spells are Restorative element, that all those *and* more already absorb.  Gi Nattak and Black Bats, for instance, absorb Restorative, so are affected by Life.  If you cast Death on them though, they won't absorb it.  It'll miss against Gi Nattak, and against Black Bats, it'll kill them outright.  Cast Death on the Ghost Ship though, and it'll get a Recovery.[/quote]

Pages: [1] 2 3 4 5 6 7