Entry 299
A Data Bug drawn and held at half its HP: the area's entry copy, virusFlag on the character
Documented in Battle rules.
Filescrates/piney-battle/src/tables.rscrates/piney-battle/src/enemy_ai.rscrates/piney-battle/src/races.rscrates/piney-battle/src/world.rscrates/piney-world/src/combat/cast.rscrates/piney-world/src/field_world.rscrates/piney-game/src/session/tests/data_bug.rstools/test_battle_spawn_rs.pydocs/engine/battle.md
Reported in play (INF, Mistral's side quest, a dungeon's B3): a Data Bug
(an enemyTbl row of type 0x40) fought with no model on screen, the hits
and "DATA DRAIN OK" shown, and one hit of 1813 took its HP down; normal
hits could finish it.
What the game does
The 45 middle-boss rows (type 0x40: 54, 55, ... 115, ... 302 on INF) have
no animation table of their own and a file named with a fourth letter X
(row 115 EETX, base form 113 EET1).
- Loading.
ccAddRequestFileListEntry(INF GCMN.PRG:0x0042f5a0) copies the base form's (base.gold)entry.anm(+0x80 of the row),clut(+0x88, 30 bytes) andfileList(+0xa8, +0xac) into a registered middle boss's entry, loads that file and the name with its fourth letterX.initEntryCCS(0x0042feb0) setsccscandccsc2from them. The same function is at MUT 0x00444f88, OUT 0x0043fdf8, QUA 0x00332708 (its 0x40 test and the +0x80 copy). - The models.
initEnemyCCS(0x00432fc0) makesCMP_trallofccscplayinganm[6](ANM_eet1nut0), and for a middle boss (the only caller ofccCheckMiddleBoss, 0x004330c4)CMP_trallofccsc2playing the same name with its eighth letterx(ANM_eetxnut0, ineetx), shadow off.dispEnemy(0x004348b0) draws that one on layer 5, then the body. - The HP rule.
initEnemyCCSsetsvirusFlag(ccEnemy+0x250 bit 6, 0x004331f8-0x0043320c) when the row'smaxPPis not -1.affectEnemy(0x00433c0c-0x00433c8c) is the only reader: damage and poison taked / 10(toward 0), and HP belowmaxHP / 2is set tomaxHP / 2. The fly font (0x00433bb8) shows the wholed.CalcBattleDamage(0x0056d910) and the skill paths have no case for type 0x40 (no other function tests the bit or callsccCheckMiddleBoss), so the numbers are ordinary and the HP stops at half: row 115 (20169 HP) at 10084. Only Data Drain after the protect breaks ends it. Nothing restores HP, and the name's garbling is the row's own name text.
Why the port differed
- The battle tables kept the disc's empty
anmfor the middle bosses (the spawn check's interpreter read EE address 0xb4 as empty too, since it never ran the loading's copy).races::init_enemyset the clip "",Cast::setfound no look with that clip, no actor was made, and nothing was drawn; the skill list was empty, so it never attacked. - An actor's look was the first look holding its clip: row 115 would have
drawn as 113 (no second model; rows sharing a file with an earlier row
took its palette). The second model's clip was played on the body's own
file, which lacks the
xclips. virusFlagwas set on the port'sEnemy, butaffect_enemyreads the character'senemy_flags(the sameccEnemyword), which nothing set.
The fix
Tables::ofapplies the loading's copy (with_base_forms).init_enemysetsenemy_flag::VIRUSon the character withvirus_flag.- A new
World::enemy_ccs(who, row)(default nothing), called first inraces::init_enemy: the field'sCast::enemy_ccsmakes the actor from the row's own look and keeps the second clump's file (second_file), which the second slot'sSetAnmand_AnimateForwardnow use. FieldWorld::put_enemy(tests and tools) puts an enemy as an event'sentry 5does, loading the row's look (Looks::add_enemies, split out ofload_looks).tools/test_battle_spawn_rs.pydoes the loading's copy in its scene, so itsracecheck covers the middle bosses with their clips.
Tests: middle_bosses_take_their_base_forms_entry and
a_data_bug_is_not_beaten_by_damage (piney-battle) fail without the fix
(no clips; no virus bit). a_data_bug_is_drawn_and_not_beaten_by_damage
(session) puts row 115 in a field, sees it drawn with both models on 1154
frames and the console's kill every 20 frames leave it at 10084; without
the fix it fails with no actor. test_battle_spawn_rs.py bulk 300 of
race, entry and frame_enemies: 0 mismatches (all 299 rows); the piney-game suite passes (163).
- Which Data Bug the report met (Mistral's quest, B3) was not identified; the fix covers all 45 rows but none was checked in that dungeon. - The second model's look on screen (layer 5, alpha from the camera) was not compared with the game's pictures; only that it is drawn. -
tools/test_battle_enemy_motion_rs.pystill leaves the middle bosses out of its rows; their motion with the copied clips is unchecked there.