diff --git a/client/Assets/Vanguard/Runtime/Board3D/View/Card3D.cs b/client/Assets/Vanguard/Runtime/Board3D/View/Card3D.cs index 6546e03..db97989 100644 --- a/client/Assets/Vanguard/Runtime/Board3D/View/Card3D.cs +++ b/client/Assets/Vanguard/Runtime/Board3D/View/Card3D.cs @@ -126,13 +126,19 @@ namespace Vanguard.Board3D _front.SetPropertyBlock(_block); } - public void SetState(Quaternion baseRotation, bool faceUp, bool rested) + public void SetState( + Quaternion baseRotation, + bool faceUp, + bool rested, + bool damageLayout = false) { _baseRotation = baseRotation; _faceUp = faceUp; _rested = rested; - var rest = Quaternion.Euler(0f, rested ? 90f : 0f, 0f); + // Атака/Rest — по часовой стрелке (+90°), урон лежит против (-90°). + var restYaw = rested ? (damageLayout ? -90f : 90f) : 0f; + var rest = Quaternion.Euler(0f, restYaw, 0f); var flip = Quaternion.Euler(faceUp ? 0f : 180f, 0f, 0f); _targetRotation = rest * baseRotation * flip; } @@ -142,9 +148,10 @@ namespace Vanguard.Board3D Quaternion baseRotation, bool faceUp, bool rested, - bool immediate) + bool immediate, + bool damageLayout = false) { - SetState(baseRotation, faceUp, rested); + SetState(baseRotation, faceUp, rested, damageLayout); _targetPosition = position; _targetScale = Vector3.one; _immediate = immediate; diff --git a/client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs b/client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs index 50af016..4845365 100644 --- a/client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs +++ b/client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs @@ -202,7 +202,8 @@ namespace Vanguard.Board3D spec.BaseRotation, spec.FaceUp, spec.Rested, - immediateAll || changed); + immediateAll || changed, + spec.DamageLayout); card.SetHighlight(spec.Highlight); } @@ -563,6 +564,7 @@ namespace Vanguard.Board3D BaseRotation = Quaternion.Euler(0f, _layout.BaseYaw(localSeat), 0f), FaceUp = isUp, Rested = true, + DamageLayout = true, Highlight = highlight, }); } @@ -1127,6 +1129,7 @@ namespace Vanguard.Board3D public Quaternion BaseRotation; public bool FaceUp; public bool Rested; + public bool DamageLayout; public Color? Highlight; } } diff --git a/client/Assets/Vanguard/Tests/Editor/ClientSmokeTests.cs b/client/Assets/Vanguard/Tests/Editor/ClientSmokeTests.cs index 29c1477..3b72935 100644 --- a/client/Assets/Vanguard/Tests/Editor/ClientSmokeTests.cs +++ b/client/Assets/Vanguard/Tests/Editor/ClientSmokeTests.cs @@ -224,6 +224,11 @@ namespace Vanguard.Tests && card.Ref.Player == 0).ToList(); Assert.AreEqual(3, damage.Count); Assert.IsFalse(damage.Single(card => card.Ref.Index == 2).IsFaceUp); + Assert.AreEqual( + -90f, + Mathf.DeltaAngle(0f, damage.Single(card => card.Ref.Index == 0).TargetYaw), + 0.1f, + "Damage cards must be turned counter-clockwise"); Assert.IsTrue(cards.Any(card => card.Ref.Zone == BoardZone.Guardian diff --git a/client/Assets/Vanguard/Tests/Editor/GameBoard3DTests.cs b/client/Assets/Vanguard/Tests/Editor/GameBoard3DTests.cs index 81d1854..6ea3bfd 100644 --- a/client/Assets/Vanguard/Tests/Editor/GameBoard3DTests.cs +++ b/client/Assets/Vanguard/Tests/Editor/GameBoard3DTests.cs @@ -55,6 +55,11 @@ namespace Vanguard.Tests && card.Ref.Player == 0 && card.Ref.Index == 0); Assert.IsTrue(visibleDamage.IsFaceUp); + Assert.AreEqual( + -90f, + Mathf.DeltaAngle(0f, visibleDamage.TargetYaw), + 0.1f, + "Damage cards must rest counter-clockwise"); } finally { diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 44f44d9..0578dda 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -848,8 +848,9 @@ Battle; Boot и общие сервисы остаются персистент — Ride только на V, Call только на пустой RC, Move только в своей колонке (0↔3, 2↔4, занятый круг меняется местами), Guard — в общий круг. - `Card3D` — тонкая коробка: отдельные лицо/рубашка/торец, коллайдер, арт из - `CardImageService`, переворот вокруг X, Rest вокруг Y, плавный снап. - Карты пулятся (`GameBoard3D`), материалы общие, instancing включён. + `CardImageService`, переворот вокруг X, Rest вокруг Y по часовой стрелке, + урон — против часовой, плавный снап. Карты пулятся (`GameBoard3D`), + материалы общие, instancing включён. - `GameBoard3D` строит стол, круги, зоны, стопки и веер руки; raycast-клики, drag&drop на плоскость стола с подъёмом, подсветкой допустимых кругов и индикатором точки броска. Ошибка интента возвращает карту на место. diff --git a/docs/SESSION-STATE.md b/docs/SESSION-STATE.md index feb6c34..dabd02d 100644 --- a/docs/SESSION-STATE.md +++ b/docs/SESSION-STATE.md @@ -63,7 +63,8 @@ без истории, MMR и наград. - Боевой экран: поле, рука и стопки — **3D** (`GameBoard3D`), HUD/кнопки остаются uGUI. Карты — тонкие 3D-объекты с артом, рубашкой, торцом и - коллайдером. Rest — поворот вокруг Y, закрытость — переворот вокруг X. + коллайдером. Rest (атака/поддержка) — поворот по часовой стрелке вокруг Y, + урон лежит на боку против часовой; закрытость — переворот вокруг X. Драг-н-дроп на плоскость стола с подсветкой целей и плавным снапом. - Поле: у каждого игрока два ряда `R V R` / `R R R` (V + 5 RC), у противника зеркально; между полями общий круг защиты; душа — стопка под