Chrono Cross Enemy Stats
File 2535 defines the characteristics of enemies. Each enemy definition is 176 (0xb0) bytes long.
Breakdown by byte:
- 0x00 unknown
- 0x01 Innate:
- 00 unknown
- 01 absorb [all?]
- 02 green
- 03 white
- 04 black
- 05 red
- 06 yellow
- 07 blue
- 0x02-0x14 unknown
- 0x15 Gender (00=random, 40=male, 80 or A0=female)
- 0x16-0x17 HP
- 0x18 ATK
- 0x19 DEF
- 0x1A HIT
- 0x1B EVD %
- 0x1C MAG
- 0x1D M. DEF
- 0x1E Status effect length
- 0x1F Unknown
- 0x20-0x21 Equipped weapon
- 01 - 1F: Raw materials (Yes, like @Seed and @Copper.)
- 20 - 26: Swallows
- 27 - 2C: Daggers
- 2D - 36: Rods (2D - 2F repeat in the 30 - 36 range)
- 37 - 41: Swords
- 42 - 47: Guns
- 48 - 4D: Picks
- 4E - 4F: Carrots
- 50 - 58: Axes (56 is blank)
- 59 - 5D: Lures
- 5F - 63: Boomerangs
- 65 - 6A: Shot
- 6B - 6C: Cards
- 6E - 73: Utensils
- 75 - 7A: Gloves
- 0x22-0x23 Equipped armour, range 0x96 to 0xB1
- 0x24-0x25 Accessory 1, range 0xBA to 0xFE
- 0x26-0x27 Accessory 2, range 0xBA to 0xFE
- 0x28-0x29 Accessory 3, range 0xBA to 0xFE
- 0x2A unknown
- 0x2B Doppelgang monster ID
- 0x2C unknown
- 0x2D Model ID (numbered consecutively in file order, enemy Radius is 40)
- 0x2E Action Points
- 0x2F Weapon model (from the file bloc 3691-3707, no weapon model is 00, generic sword is 01)
- 0x30-0x3F Element Grid definition for Doppelgangs. Takes the form of a series of bitflags; each level of the grid uses 16 bits, starting with the first bit in the top left corner and working down to the bottom right (L to R first). If the flag is set, the grid position is open and can have an Element installed.
- 0x40-0x99 Elements with which to fill the Grid during Doppelgangs. A series of 2-byte little-endian values indicating Element indices (with each mysteriously inflated by 0x4000). Open slots in the Grid defined by the previous section are filled in the order in which they were defined.
- 0xA0 Treasure drop ID as defined in file 0008
- 0xA1 unknown (or 2nd byte of treasure drop pointer?)
- 0xA2-0xA3 Gold dropped
- 0xA4 Hit for medium attack
- 0xA5 Hit for heavy attack
- 0xA6 The monster is Doppelgangable if and only if the high bit is //not// set.
- 0xA7-0xAD unknown
- 0xAE-0xAF Monster type, for special weapon effects:
- bit 0 Floating
- bit 1 Undead
- bit 2 Soft
- bit 3 Inorganic
- bit 4 ? Beach Bum, Mantarrey, Lagoonate
- bit 13 Dragon
- bit 14 Human
- bit 15 Demon
Scaling before Recruiting First PC
Thanks to glennxserge
Here's what I found testing Beach Bums at Cape Howl.
- With one character, they had 16 HP (50%)
- With two characters, they had 33 HP (100%+1HP, which is maybe probably just the bonus 5% given to male enemies when rounded down)
- With three characters, they also have 33 HP.
The next time in the game you have a solo character is as Lynx in the Temporal Vortex, but you recruit Sprigg before any battles, so that was a bust.
The only other scenario I could think of is in Lucca's orphanage since your party gradually decreases as you work your way through the house. This is what I found there: Lava-boys (and girls) - these have a random sex, so they'll get +/- 5% HP depending on Male or Female. My calculations account for the bonus in order to better match the stat block on disc.
- 1 char - 780 HP (Male 819, Female 741)
- 2 char - 780 HP (Male 819, Female 741)
- 3 char - 780 HP (Male 819, Female 741)
That's the regular value on disc for that encounter, so I don't think scaling is used after you recruit your first character, regardless how many are actually in your current party, and it seems like it has nothing to do with star level. At zero stars if you recruit Poshul, enemy HP will be normal.
There is another factor though, that you noticed Grobycftw, NG+ enemies will have 2x HP. It looks like this is a separate scaling factor that is applied alongside the early game difficulty scaling. I tested this in a NG+ game and enemies had the normal HP, until I recruited a character, and then they had 2x.
Here's my hunch about the way it's calculated, order of operations:
- HP is multiplied by 2 if it is a NG+
- HP is then divided by 2 if it's early game
- 5% is then +/- from HP depending on Male/Female
The order of operations does seem to matter here, since a shift down or divide with integers could clear the low bit before shifting back up (in the case of NG+ and early game). However it doesn't seem to matter since no enemies in the beginning have stat blocks with odd values. The 5% definitely happens after the scaling though, as it is testable (male Beach Bums have 67 HP, not 66 in NG+).
I'm tempted to try and dump emu states before and after recruiting Poshul to see if I can find where that value gets set, but feeling a bit lazy at the moment.
Maximum Enemy HP Possible
Thanks to glennxserge
First thing to look at is if HP is actually used as a signed integer. I would've thought that the game logic would just check for underflow (HP after damage greater than initial HP), and set to zero, but it's also possible that they would use a signed data type and just check for a less than zero value, since there are cases where damage actually does heal (plate armor stolen from dragons).
WARNING: Wall of text incoming
- Set an enemy HP right at the 32,767 max
- Modify an attack element to make enemy HP visible
- Heal enemy and check HP
(I'll list my disc modifications based on a 2352 sector size, and using disc 1 only)
So I set the Beach Bum HP to 32,767. since these are always male, the value is actually 31,207 * 1.05. The disc address and values used:
- 0x13B8EDEE: 0xE7
- 0x13B8EDEF: 0x79
Next I modified Aquabeam so that it does zero damage but shows enemy HP:
- 0x13BA00FC: 0x00 (zero damage)
- 0x13BA00FE: 0x64 (stat effect 100% chance of hitting)
- 0x13BA010E: 0x40 (HP vis stat)
And last, I changed Tablet, so that it targets enemies:
- 0x13BA1538: 0x80
Then I started a battle, and cast Aquabeam on a full HP Beach Bum. When I targeted him next, he had 32,767/32,767 HP. So far so good.
Next I used a Tablet on him, which did... something odd. He sagged like he was close to death. And when I checked his HP it was far outside the 16bit boundary: 934,557/32,767 (and colored red like low HP). A single 1 stamina attack then killed it :shock: So it seems like the game doesn't display negative HP values properly, but it sure acted like one. This makes me think that HP, while not explicitly signed, is contingent on some game logic that treats it as such, but isn't well enforced.
I also double checked that an enemy with a reasonable HP value, when healed, doesn't go above it's max HP. It seems like this overflow is only possible during the heal calculation if the result is lower than the max HP because of the sign change.
The last thing to note, giving an enemy a default HP value of 32768, made it's max HP overflow too, which creates some odd interactions. This seems like a bug in the game logic. It might be possible to fix the damage formula to allow for full 16bit values, but that'll take someone with more experience than me. In the meantime, probably best to only use HP values under 32,767. Or, if you are planning on having a mod that can be played in NG+, 16,383.