feat(battle-engine-port): M3 COMPLETE — fixed-damage spell resolves headless (leader-life-delta oracle passes)
Card 900124030 (ELF cost-3, when_play damage=3 to enemy leader) resolves to correct authoritative state headless via the IsForecast/IsRecovery + ActionProcessor.PlayCard path. New oracle dimension (opponent leader-life delta) passes; 3/3 tests green; engine still 0 errors; check_drift clean. Four headless gaps, each mechanical (no logic/Unity wall): - Data seam: InitLeaderLife (SetupInitialGameState->InitializeClassLife subset); leader BaseMaxLife was 0 => game-over => play silently rejected. M2 missed it (only asserted leader life unchanged: 0==0). - Runtime cast: re-attach IClassBattleCardView on the generated NullClassBattleCardView stub (members already present; base-clause recovery stripped the decl). Compiled fine -> M1 loop never surfaced it. - M1 mis-cut: copy NullVfxWithLoading verbatim (its GetInstance() lazy singleton was stubbed to default!/null). Same pattern as M2 NullCardVfxCreator. - Card events: CreateHeadlessHandCard now calls SetupCardEvent so a spell's OnPlay->RemoveSpellCardFromHand / OnFinishWhenPlaySkill->AddSpellCardToCemetery fire (the bare CreateCardWithoutResources seam skips them). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -61,6 +61,16 @@ namespace Wizard.Battle.View
|
||||
public virtual void ClearSpineObject() { }
|
||||
}
|
||||
public class NullBattleCardView : BattleCardView { public NullBattleCardView() { } public NullBattleCardView(BuildInfo buildInfo) { } public static void ReleaseSharedDummy() { } }
|
||||
|
||||
// The decomp NullClassBattleCardView is `: NullBattleCardView, IClassBattleCardView, IBattleCardView`;
|
||||
// base-clause recovery kept only the base class. IBattleCardView is satisfied via the BattleCardView
|
||||
// base, but IClassBattleCardView was dropped. The generated NullClassBattleCardView stub already
|
||||
// provides that interface's members (public no-ops), so just re-attach the dropped interface here.
|
||||
// The resolution path's VirtualClone (createNullView) -> ClassBattleCardBase.Setup casts the null
|
||||
// view to IClassBattleCardView, which throws InvalidCastException at runtime without this (M3,
|
||||
// fixed-damage spell: Skill_damage.TakeDamageSingle clones the leader before applying damage).
|
||||
// Compiles fine without it (it's a cast, not a member call), so the M1 loop never surfaced it.
|
||||
public partial class NullClassBattleCardView : IClassBattleCardView { }
|
||||
}
|
||||
|
||||
namespace Wizard.Battle.View.Vfx
|
||||
|
||||
Reference in New Issue
Block a user