Entry 294
Fidchell, Outbreak's first phase boss, and its four spells
Documented in Bosses - Fidchell.
Filescrates/piney-battle/src/boss/fidchell.rscrates/piney-battle/src/boss/fidchell/eff.rscrates/piney-battle/src/boss/fidchell/tests.rscrates/piney-battle/src/boss.rscrates/piney-battle/examples/battle_probe/fidchell.rscrates/piney-world/src/combat/boss.rscrates/piney-game/src/fx.rscrates/piney-game/src/session/tests/survey.rscrates/piney-gen/src/manifest.rstools/test_battle_fidchell_rs.pydocs/engine/boss-fidchell.md
Outbreak's event 207 now fights Fidchell in field 4 and runs to its end.
Block 9's entry type=7 code=3 makes ccBoss04 (bossTbl row 3, file
x41) and block 11's absent type=7 code=3 follows once it dies. The
reference is docs/engine/boss-fidchell.md.
How it was taken apart
The 31 functions of boss04.cpp are Infection's (INF gcmn
0x00491af0-0x00496ee4, with DWARF: PRED_TEXT, PREDICTION_T and the
class's 0x230 bytes of own members), but the fight is Outbreak's, so the
port is Outbreak's code (OUT gcmn 0x004a3470-0x004a900c). Outbreak's
compile is still close to Infection's unoptimised output, so Magus's
lifter (straight-line pseudo-C over the disassembly, 274) read it as
well, and a normalised diff of the two lifts gave the changes. The class
runs on the base ccBoss (Main, Move, ChangeAction,
ChangeNextPattern, IsValidArea): where Fidchell uses it, Outbreak's
base differs from Mutation's in stack slots and the display size read
from globals (its SelectTarget is recompiled past a text diff; the
harness agrees with the port's).
Fidchell's own acts: the prediction (act 3) picks one of four spells by
ccSys.count & 3, shows its text (x41's ANM_ex41txt1-4) and asks a
voice, then lays @1441's skill (171, 170, 173, 169) on each member;
pattern 15 casts it (act 5): the meteors (ccBossEffMeteoSworm, 50
meteors), Skeith's ice (force generators, ring, ice at each member, the
screen reversed), the thunders (ccBossEffThunderStorm, 16 bolts) or the
quake (ccBossEffRockTower, 128 towers). Beside them the wave, a member
drained through menu 74 (stream 68), chases, escapes, back dashes, dashes,
a skill of @2048 and in the Epitaph a spell of @2081 and a self-heal
(skill 151). Drained, it has 5000 HP.
The game's slips are kept. OnThinkPrediction's last step counts its
frame twice. OnThinkEscape never sets a heading. OnThinkBackDash turns
at its first frame only when already out of the arena. Pattern 9 with a
negative type picks among the members whose dead is set. Pattern 10
draws a skill it drops (OnThinkSkill draws again). OnThinkMagic's
request flag is a3 as the frame left it (the harness measures 1). The
ice deletes its ccBufferReverce and layer and keeps the pointers.
OnThinkTransfer (act 21, never reached) tests its turn against pi twice.
What Outbreak changed from Infection: the boss camera (250 and a
MaxRenge of 600 against 200); shorter Normal and Super tables; cinemas
on the prediction (64-67), the spell (14-17), the skill and the spell
(OnCinemaMode with a skill id, OUT 0x004733b0) and the member drain; the
menu cursor turned off around every move off the targets; the spell's
camera (1800 off the centre, then behind the target) and Fidchell's turn
to the centre; the ice's end (no second ChangeNextPattern, its SEs at
the target); the thunders' camera call dropped (its vectors still worked
out).
The square root
Outbreak's main has the FPU's sqrt.s inline in ccGetDist (OUT
0x001e6ec0) and in _ccBossSkillDamage, where Infection and Mutation call
newlib's sqrtf. sqrt.s truncates, so the two part in the last bit
wherever newlib's rounds up. With newlib's the harness's case 8100 parts
at frame 61 (targetDist one bit high). The port's boss rules now take sqrt_of(cx, v) by the
disc's volume (the field's Sqrt choice, 280), in Fidchell's frame
and target and in the skill damage's range test; on Infection and
Mutation nothing changes. Other callers of the battle's get_dist on
Outbreak still take newlib's.
The spells
The spells' effects are what the boss waits on, and three of them draw
ccRand and play sounds in their Draws, and the meteors write the
boss's camera view each frame, so their rules are ported
(fidchell::eff): the meteors' flights (ccBossEffMeteo2::Init and
Move: heading, pitch by atan2f, a pull in doubles), the bolts' growth,
strike and fade (16 ccRandF a Draw plus one a segment, 16 at the
strike), the storm's waits and rumbles (and the magic square the first
bolt's end makes inside the manager's pass), the towers' waits, rise and
fade. Their pictures are named (Out::Fidchell), not drawn.
Checks
tools/test_battle_fidchell_rs.py (PINEY_VOLUME=outbreak) builds the
game's ccBoss04 and runs the base's Main natively (with the manager's
pass, the three spells native) against battle_probe's fidchell, frame by
frame. A case has one to three members, 800 to 7000 frames, hits and the
gauge, the drain's 13 and 21 with hits after, its own skills ending, a
member down for a while, a push, the menu's type, the camera turning and
checkCameraShakeRange answering no on every nth frame. Compared each
frame: the acts, movement, place, target, HP, gauge, flags, clips, every
own member, the boss camera's MaxRenge, the effects' slots, the party,
the calls, the menu, rand() and ccRand's index. bulk 40 (seed
9700): 40 cases, 125,426 frames agree; acts 0, 3-7, 12-14, 16, 18, 22, 24
and 25 and all four spells are reached. test_effect_lives runs the nine
stand-ins' Creates and Draws natively: the WaveShock 45, the magic
squares 91, 71, 91, the force generators 133 and 193, the ring 20, the ice
123, the dead effect 120, the port's lives. Skeith's, Innis's, Magus's and
Kyvia's harnesses still pass. boss::fidchell::tests hold five cases.
Under the autopilot
PINEY_SURVEY_ONLY=207 PINEY_SURVEY_GOD=1 PINEY_SURVEY_FRAMES=120000 ends
story 207: done. The fight begins at frame 43,650. Two aids were
needed. Kite stood where the pilot left him while Fidchell roamed its
arena (its skills need a foe within 400): the pilot now walks him to
within 350 of Fidchell when no other foe is near (approach_roamer). And
at the story's levels (about 53) the gauge (a physical defence of 2000,
maxPP 16000) took 50,000 frames and the Epitaph's self-heal outpaced
the party: the party is raised to 75 through the console's exp while
Fidchell is up (levels_for_boss). A broken protect no longer waits out
the last skill's 240 frames before Kite drains (the break lasts under 300).
Even so the first break (77,350) is missed, Kite far and stuck; the second
(96,950) is drained, and the body dies at 112,100. With these aids
Mutation's 107 and 108 (150,000 frames) and Outbreak's 203 (60,000) still
end done; Mutation's 115 (200,000) stops in field 52, before Magus's
field, with or without them (4880 places either way).
- The pictures: the prediction's text, the meteors and their light, the bolts, the towers and the dust are named, not drawn; the voices are not played; a skill's cinema shows its bars without the name (OUT 0x00472550's rows are not read). -
effSkillStart's controller is taken to end 8 frames on; its real end under the effect task is not run with the boss (any end under 30 frames gives the same fight). -OnThinkTransferis ported but no pattern reaches it, so it is unchecked; acts 20 and 23 likewise. - Why the pilot's first drain fails: Kite is held against something about 1200 off Fidchell when the gauge breaks.