Add guard choices and target 1920x1080 layout
CI / test (push) Successful in 2m34s
Details
CI / test (push) Successful in 2m34s
Details
This commit is contained in:
parent
30aed3b25d
commit
a3d2157925
|
|
@ -30,6 +30,8 @@ namespace Vanguard.App
|
||||||
Instance = this;
|
Instance = this;
|
||||||
DontDestroyOnLoad(gameObject);
|
DontDestroyOnLoad(gameObject);
|
||||||
Application.targetFrameRate = 60;
|
Application.targetFrameRate = 60;
|
||||||
|
if (!Application.isEditor)
|
||||||
|
Screen.SetResolution(1920, 1080, FullScreenMode.FullScreenWindow);
|
||||||
Loc.Initialize();
|
Loc.Initialize();
|
||||||
|
|
||||||
var config = new AppConfig();
|
var config = new AppConfig();
|
||||||
|
|
|
||||||
|
|
@ -1247,6 +1247,54 @@ namespace Vanguard.UI
|
||||||
UiKit.SetPreferredHeight(button, 46f);
|
UiKit.SetPreferredHeight(button, 46f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddGuardButton(IReadOnlyList<GuardIntent> guards)
|
||||||
|
{
|
||||||
|
if (guards == null || guards.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var button = UiKit.CreateButton(
|
||||||
|
_intents,
|
||||||
|
"GuardAction",
|
||||||
|
"Защититься",
|
||||||
|
() => OpenGuardSelector(guards),
|
||||||
|
16);
|
||||||
|
button.interactable = !_inputLock.IsLocked;
|
||||||
|
UiKit.SetPreferredHeight(button, 46f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenGuardSelector(IReadOnlyList<GuardIntent> guards)
|
||||||
|
{
|
||||||
|
var groups = guards
|
||||||
|
.GroupBy(guard => guard.PrintingId)
|
||||||
|
.ToList();
|
||||||
|
if (groups.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (groups.Count == 1)
|
||||||
|
{
|
||||||
|
var variants = groups[0].ToList();
|
||||||
|
if (variants.Count > 1)
|
||||||
|
ShowGuardDiscardChoice(variants);
|
||||||
|
else
|
||||||
|
OnIntentClicked(variants[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = groups
|
||||||
|
.Select(group => new CardActionMenuItem(
|
||||||
|
"Защититься: " + CardName(group.Key),
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
var variants = group.ToList();
|
||||||
|
if (variants.Count > 1)
|
||||||
|
ShowGuardDiscardChoice(variants);
|
||||||
|
else
|
||||||
|
OnIntentClicked(variants[0]);
|
||||||
|
}))
|
||||||
|
.ToList();
|
||||||
|
ShowChoiceMenu("Защита", items);
|
||||||
|
}
|
||||||
|
|
||||||
private void OpenAbilitySelector(IReadOnlyList<ActivateAbilityIntent> abilities)
|
private void OpenAbilitySelector(IReadOnlyList<ActivateAbilityIntent> abilities)
|
||||||
{
|
{
|
||||||
var groups = abilities
|
var groups = abilities
|
||||||
|
|
@ -2155,8 +2203,11 @@ namespace Vanguard.UI
|
||||||
var legal = view.LegalIntents ?? new List<IntentPayload>();
|
var legal = view.LegalIntents ?? new List<IntentPayload>();
|
||||||
var playable = legal.Where(intent => intent is not ConcedeIntent).ToList();
|
var playable = legal.Where(intent => intent is not ConcedeIntent).ToList();
|
||||||
var abilities = playable.OfType<ActivateAbilityIntent>().ToList();
|
var abilities = playable.OfType<ActivateAbilityIntent>().ToList();
|
||||||
|
var guards = playable.OfType<GuardIntent>().ToList();
|
||||||
var board = playable
|
var board = playable
|
||||||
.Where(intent => IsBoardIntent(intent) && intent is not ActivateAbilityIntent)
|
.Where(intent => IsBoardIntent(intent)
|
||||||
|
&& intent is not ActivateAbilityIntent
|
||||||
|
&& intent is not GuardIntent)
|
||||||
.ToList();
|
.ToList();
|
||||||
var global = playable
|
var global = playable
|
||||||
.Where(intent => !IsBoardIntent(intent)
|
.Where(intent => !IsBoardIntent(intent)
|
||||||
|
|
@ -2271,6 +2322,9 @@ namespace Vanguard.UI
|
||||||
if (abilities.Count > 0)
|
if (abilities.Count > 0)
|
||||||
AddAbilityButton(abilities);
|
AddAbilityButton(abilities);
|
||||||
|
|
||||||
|
if (guards.Count > 0)
|
||||||
|
AddGuardButton(guards);
|
||||||
|
|
||||||
foreach (var intent in global)
|
foreach (var intent in global)
|
||||||
AddIntentButton(intent);
|
AddIntentButton(intent);
|
||||||
|
|
||||||
|
|
@ -2374,7 +2428,7 @@ namespace Vanguard.UI
|
||||||
+ (attack.BoosterSlot >= 0 ? " + boost" : string.Empty);
|
+ (attack.BoosterSlot >= 0 ? " + boost" : string.Empty);
|
||||||
case GuardIntent guard: return "Guard: " + CardName(guard.PrintingId);
|
case GuardIntent guard: return "Guard: " + CardName(guard.PrintingId);
|
||||||
case InterceptIntent intercept: return "Intercept: " + SlotName(intercept.Slot);
|
case InterceptIntent intercept: return "Intercept: " + SlotName(intercept.Slot);
|
||||||
case PassGuardIntent _: return "Пропустить Guard";
|
case PassGuardIntent _: return "Не защищаться";
|
||||||
case ResolveTriggerIntent trigger:
|
case ResolveTriggerIntent trigger:
|
||||||
return "Триггер: сила " + SlotName(trigger.PowerTarget)
|
return "Триггер: сила " + SlotName(trigger.PowerTarget)
|
||||||
+ ", эффект " + SlotName(trigger.EffectTarget);
|
+ ", эффект " + SlotName(trigger.EffectTarget);
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,10 @@ namespace Vanguard.UI
|
||||||
["Без сброса"] = "No discard",
|
["Без сброса"] = "No discard",
|
||||||
["Guard без сброса"] = "Guard without discard",
|
["Guard без сброса"] = "Guard without discard",
|
||||||
["Perfect Guard: сбросить "] = "Perfect Guard: discard ",
|
["Perfect Guard: сбросить "] = "Perfect Guard: discard ",
|
||||||
|
["Защититься"] = "Guard",
|
||||||
|
["Защититься: "] = "Guard: ",
|
||||||
|
["Защита"] = "Guard",
|
||||||
|
["Не защищаться"] = "Do not guard",
|
||||||
["Действия"] = "Actions",
|
["Действия"] = "Actions",
|
||||||
["Переместить"] = "Move",
|
["Переместить"] = "Move",
|
||||||
["Подробнее"] = "Details",
|
["Подробнее"] = "Details",
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,26 @@ namespace Vanguard.Tests
|
||||||
Object.DestroyImmediate(go);
|
Object.DestroyImmediate(go);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Canvas_Reference_Resolution_Is_1920x1080()
|
||||||
|
{
|
||||||
|
var canvas = UiKit.CreateCanvas("Reference Resolution Canvas");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var scaler = canvas.GetComponent<CanvasScaler>();
|
||||||
|
Assert.IsNotNull(scaler);
|
||||||
|
Assert.AreEqual(1920f, scaler.referenceResolution.x);
|
||||||
|
Assert.AreEqual(1080f, scaler.referenceResolution.y);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Object.DestroyImmediate(canvas.gameObject);
|
||||||
|
var eventSystem = Object.FindAnyObjectByType<EventSystem>();
|
||||||
|
if (eventSystem != null)
|
||||||
|
Object.DestroyImmediate(eventSystem.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Battle_Layout_Fits_Reference_Resolution()
|
public void Battle_Layout_Fits_Reference_Resolution()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ PlayerSettings:
|
||||||
androidAutoRotationBehavior: 1
|
androidAutoRotationBehavior: 1
|
||||||
androidPredictiveBackSupport: 1
|
androidPredictiveBackSupport: 1
|
||||||
androidApplicationEntry: 1
|
androidApplicationEntry: 1
|
||||||
defaultIsNativeResolution: 1
|
defaultIsNativeResolution: 0
|
||||||
macRetinaSupport: 1
|
macRetinaSupport: 1
|
||||||
runInBackground: 0
|
runInBackground: 0
|
||||||
callOnDisableOnAssetBundleUnload: 1
|
callOnDisableOnAssetBundleUnload: 1
|
||||||
|
|
|
||||||
|
|
@ -959,7 +959,7 @@ Battle; Boot и общие сервисы остаются персистент
|
||||||
- Добавлен `Battle_Layout_Fits_Reference_Resolution`: проверяет блоки зон,
|
- Добавлен `Battle_Layout_Fits_Reference_Resolution`: проверяет блоки зон,
|
||||||
панель фаз и боевую плашку на 1920×1080 и отсутствие пересечений; при
|
панель фаз и боевую плашку на 1920×1080 и отсутствие пересечений; при
|
||||||
другом разрешении CanvasScaler масштабирует reference-раскладку.
|
другом разрешении CanvasScaler масштабирует reference-раскладку.
|
||||||
- Проверки: клиент EditMode **29/29**, `SCENE_SMOKE success=True`,
|
- Проверки: клиент EditMode **30/30**, `SCENE_SMOKE success=True`,
|
||||||
`PLAYMAT_SMOKE success=True cards=25 hand=5/5 fieldVisible=True`.
|
`PLAYMAT_SMOKE success=True cards=25 hand=5/5 fieldVisible=True`.
|
||||||
- Дальше: только 3D-модели/наполнение сцен, анимации retire/ghost и
|
- Дальше: только 3D-модели/наполнение сцен, анимации retire/ghost и
|
||||||
декбилдер; prefab-оверлеи и раскладка закрыты.
|
декбилдер; prefab-оверлеи и раскладка закрыты.
|
||||||
|
|
@ -992,8 +992,12 @@ Battle; Boot и общие сервисы остаются персистент
|
||||||
кнопка «Активировать способность». Если целей/вариантов несколько —
|
кнопка «Активировать способность». Если целей/вариантов несколько —
|
||||||
отдельный overlay, затем выбор карты для сброса (без duplicate-кнопок).
|
отдельный overlay, затем выбор карты для сброса (без duplicate-кнопок).
|
||||||
- Guard: варианты Perfect Guard/сброса показываются отдельным overlay;
|
- Guard: варианты Perfect Guard/сброса показываются отдельным overlay;
|
||||||
случайный первый интент больше не выбирается.
|
случайный первый интент больше не выбирается. В фазе защиты есть
|
||||||
|
«Защититься» (при наличии допустимых карт) и «Не защищаться».
|
||||||
- Камера боя: `(0, 4.2, -8)` → цель `(0, 0, 0)`, только наклон по X;
|
- Камера боя: `(0, 4.2, -8)` → цель `(0, 0, 0)`, только наклон по X;
|
||||||
поле по центру, без бокового смещения.
|
поле по центру, без бокового смещения.
|
||||||
|
- UI: reference-разрешение **1920×1080**, CanvasScaler `matchWidthOrHeight
|
||||||
|
= 0.5`; standalone принудительно `1920×1080 FullScreenWindow`,
|
||||||
|
`defaultIsNativeResolution = 0`.
|
||||||
- Проверки: сервер **141** правил + **45** серверных, `validate` и
|
- Проверки: сервер **141** правил + **45** серверных, `validate` и
|
||||||
`translations check` OK; клиент EditMode **29/29**.
|
`translations check` OK; клиент EditMode **30/30**.
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,9 @@
|
||||||
- Переходы — `SceneFlow`; очередь/онбординг — оверлеи **Lobby**.
|
- Переходы — `SceneFlow`; очередь/онбординг — оверлеи **Lobby**.
|
||||||
- 3D-окружение сейчас из примитивов (`SceneEnvironment`): камера, свет,
|
- 3D-окружение сейчас из примитивов (`SceneEnvironment`): камера, свет,
|
||||||
пол, тематические кубы. UI — code-generated uGUI, пока gray-box.
|
пол, тематические кубы. UI — code-generated uGUI, пока gray-box.
|
||||||
|
- Интерфейс рассчитан на reference **1920×1080** (`CanvasScaler`,
|
||||||
|
`matchWidthOrHeight = 0.5`); standalone принудительно открывается в
|
||||||
|
1920×1080 fullscreen, `defaultIsNativeResolution` выключен.
|
||||||
- Login: тёмный неон + 3D-карточный стол, форма по центру на
|
- Login: тёмный неон + 3D-карточный стол, форма по центру на
|
||||||
полупрозрачной панели.
|
полупрозрачной панели.
|
||||||
- Сервисы: `ApiClient`, `AuthService`, `MetaService`, `TokenStore`,
|
- Сервисы: `ApiClient`, `AuthService`, `MetaService`, `TokenStore`,
|
||||||
|
|
@ -85,6 +88,8 @@
|
||||||
нескольких вариантах открывается overlay выбора, затем — выбор карты
|
нескольких вариантах открывается overlay выбора, затем — выбор карты
|
||||||
для сброса. Perfect Guard также спрашивает карту для сброса отдельным
|
для сброса. Perfect Guard также спрашивает карту для сброса отдельным
|
||||||
overlay, а не выбирает случайную.
|
overlay, а не выбирает случайную.
|
||||||
|
- В фазе защиты доступны «Защититься» (если есть допустимые карты) и
|
||||||
|
«Не защищаться»; выбор карты защиты и сброса идёт через overlay.
|
||||||
- Статистика карт — отдельное UI-наложение: своя панель снизу слева,
|
- Статистика карт — отдельное UI-наложение: своя панель снизу слева,
|
||||||
противника — сверху справа. Блоки `Рука/Колода/Дроп/Душа/Урон/Защита/Триггер`
|
противника — сверху справа. Блоки `Рука/Колода/Дроп/Душа/Урон/Защита/Триггер`
|
||||||
кликабельны и открывают общий горизонтальный `CardListView`; из списка
|
кликабельны и открывают общий горизонтальный `CardListView`; из списка
|
||||||
|
|
@ -181,7 +186,7 @@ Standalone Windows:
|
||||||
-executeMethod Vanguard.Editor.SceneSmoke.RunPlaymat
|
-executeMethod Vanguard.Editor.SceneSmoke.RunPlaymat
|
||||||
```
|
```
|
||||||
|
|
||||||
Клиентские проверки: **29/29** EditMode (сборка всех экранов, импорт арта,
|
Клиентские проверки: **30/30** EditMode (сборка всех экранов, импорт арта,
|
||||||
перевод статических/динамических строк, live-переключение языка, рендер
|
перевод статических/динамических строк, live-переключение языка, рендер
|
||||||
3D-доски с уроном и отдыхающей картой, геометрия поля, правила
|
3D-доски с уроном и отдыхающей картой, геометрия поля, правила
|
||||||
перемещения, рука в поле зрения камеры, обмен колоды/дропа, триггер-зона,
|
перемещения, рука в поле зрения камеры, обмен колоды/дропа, триггер-зона,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue