feat(battlenode): attack resolves on engine state via view-untangle (M-HC-4a)
Drive ATTACK frames through the headless receive conductor and assert on engine board state (node-native harness). Two cases: follower -> enemy leader (leader life drops by atk, attacker spent) and a lethal follower-vs-follower trade (both removed). ATTACK opcode confirmed = 10 (NetworkBattleDefine.PlayActionType). Headless view-untangle (no Engine logic edits; drift clean): - IBattlePlayerView.AttackSelectControl -> non-null HeadlessAttackSelectControl (no-op RegisterAttackPair/ResetCardAfterAttack); IsCardTranslatable left to base. - IBattleCardView.CardInfo -> backing card via BuildInfo (so IsCardTranslatable reads authentic IsClass); class/null view ctors now chain : base(buildInfo). - IBattleCardView._inPlayFrameEffect -> non-null no-op control. - Seed Certification.viewer_id headless so the IsRecovery target parse (vid != UserViewerID) does not throw inside SavedataManager and silently drop the parsed targetList. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ namespace Wizard.Battle.View {
|
||||
Vector3 global::Wizard.Battle.View.IBattleCardView.ForecastIconPosition { get => default!; }
|
||||
Vector3 global::Wizard.Battle.View.IBattleCardView.ForecastIconScale { get => default!; }
|
||||
float global::Wizard.Battle.View.IBattleCardView.OriginalRootYPosition { get => default!; }
|
||||
IReadOnlyBattleCardInfo global::Wizard.Battle.View.IBattleCardView.CardInfo { get => default!; }
|
||||
IReadOnlyBattleCardInfo global::Wizard.Battle.View.IBattleCardView.CardInfo { get => HeadlessCardInfo; } // HEADLESS-FIX (M-HC-4a): the backing card (from BuildInfo) — AttackSelectControl.IsCardTranslatable reads CardInfo.IsClass
|
||||
BattlePlayerReadOnlyInfoPair global::Wizard.Battle.View.IBattleCardView.PlayerInfoPair { get => default!; }
|
||||
IReadOnlyVoiceInfo global::Wizard.Battle.View.IBattleCardView.VoiceInfo { get => global::Wizard.Battle.View.HeadlessVoiceInfo.Instance; } // HEADLESS-FIX (M7): non-null voice info for the death-voice tail
|
||||
GameObject global::Wizard.Battle.View.IBattleCardView.GameObject { get => default!; }
|
||||
@@ -27,7 +27,7 @@ namespace Wizard.Battle.View {
|
||||
BackGroundBase global::Wizard.Battle.View.IBattleCardView.m_BackGround { get => default!; }
|
||||
HandParameter global::Wizard.Battle.View.IBattleCardView.HandParam { get => default!; }
|
||||
BattleCardView.AttackTargetSelectInfo global::Wizard.Battle.View.IBattleCardView._attackTargetSelectInfo { get => default!; set { } }
|
||||
InPlayCardFrameEffectControl global::Wizard.Battle.View.IBattleCardView._inPlayFrameEffect { get => default!; set { } }
|
||||
InPlayCardFrameEffectControl global::Wizard.Battle.View.IBattleCardView._inPlayFrameEffect { get => _headlessInPlayFrameEffect; set { _headlessInPlayFrameEffect = value; } } // HEADLESS-FIX (M-HC-4a): non-null no-op frame-effect control (HideFrameEffect/UpdateCanAttackEffect are no-ops) for the receive ATTACK path
|
||||
bool global::Wizard.Battle.View.IBattleCardView.areArrowsForcedOff { get => default!; set { } }
|
||||
bool global::Wizard.Battle.View.IBattleCardView._isCardQueuedToBePlayed { get => default!; set { } }
|
||||
bool global::Wizard.Battle.View.IBattleCardView.isHiddenFromHandView { get => default!; set { } }
|
||||
@@ -228,7 +228,7 @@ namespace Wizard.Battle.View {
|
||||
// shared no-op PlayQueueViewBase so the presentation call is a safe NullVfx (the authoritative
|
||||
// play mutation runs in PlayHandCardReflection.Play, not in this view).
|
||||
PlayQueueViewBase global::Wizard.Battle.View.IBattlePlayerView.PlayQueueView { get => global::Wizard.Battle.View.HeadlessPlayQueueViewStub.Instance; }
|
||||
AttackSelectControl global::Wizard.Battle.View.IBattlePlayerView.AttackSelectControl { get => default!; }
|
||||
AttackSelectControl global::Wizard.Battle.View.IBattlePlayerView.AttackSelectControl { get => global::Wizard.Battle.View.HeadlessAttackSelectControl.Instance; } // HEADLESS-FIX (M-HC-4a): non-null no-op attack-select-control for the receive ATTACK path (RegisterPairToAttackSelectControl + ActionProcessor.Attack reset arm)
|
||||
InPlayViewBase global::Wizard.Battle.View.IBattlePlayerView.InPlayView { get => default!; }
|
||||
GameObject global::Wizard.Battle.View.IBattlePlayerView.StatusParentPanel { get => default!; }
|
||||
GameObject global::Wizard.Battle.View.IBattlePlayerView.AnchorL { get => default!; }
|
||||
@@ -335,7 +335,7 @@ namespace Wizard.Battle.View {
|
||||
// shared no-op PlayQueueViewBase so the presentation call is a safe NullVfx (the authoritative
|
||||
// play mutation runs in PlayHandCardReflection.Play, not in this view).
|
||||
PlayQueueViewBase global::Wizard.Battle.View.IBattlePlayerView.PlayQueueView { get => global::Wizard.Battle.View.HeadlessPlayQueueViewStub.Instance; }
|
||||
AttackSelectControl global::Wizard.Battle.View.IBattlePlayerView.AttackSelectControl { get => default!; }
|
||||
AttackSelectControl global::Wizard.Battle.View.IBattlePlayerView.AttackSelectControl { get => global::Wizard.Battle.View.HeadlessAttackSelectControl.Instance; } // HEADLESS-FIX (M-HC-4a): non-null no-op attack-select-control for the receive ATTACK path (RegisterPairToAttackSelectControl + ActionProcessor.Attack reset arm)
|
||||
InPlayViewBase global::Wizard.Battle.View.IBattlePlayerView.InPlayView { get => default!; }
|
||||
GameObject global::Wizard.Battle.View.IBattlePlayerView.StatusParentPanel { get => default!; }
|
||||
GameObject global::Wizard.Battle.View.IBattlePlayerView.AnchorL { get => default!; }
|
||||
|
||||
Reference in New Issue
Block a user