Add trigger target selection and finish battle UX
CI / test (push) Successful in 6m48s
Details
CI / test (push) Successful in 6m48s
Details
This commit is contained in:
parent
5874d6982f
commit
8217e8225e
|
|
@ -279,7 +279,8 @@
|
|||
сила/крит; REST/скрытая карта.
|
||||
- [x] Старт: маллиган (сервер пока даёт только «закончить маллиган»).
|
||||
- [x] Ввод: кнопки легальных интентов; клик по картам/зонам,
|
||||
подсветка целей, группировка действий и журнал боя.
|
||||
подсветка целей, группировка действий, выбор силы/эффекта триггера
|
||||
и журнал боя.
|
||||
- [x] Boost: выбор карты заднего ряда как поддержки перед атакой.
|
||||
- [x] Event-фидбек: атака, guard, drive, урон, heal, retire, perfect guard.
|
||||
- [x] Отображение силы/крита из `MatchView`; модификаторы уже посчитаны сервером.
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ namespace Vanguard.UI
|
|||
private readonly List<IntentPayload> _pendingIntents = new List<IntentPayload>();
|
||||
private readonly HashSet<string> _highlightKeys = new HashSet<string>(StringComparer.Ordinal);
|
||||
private int _pendingBoosterSlot = -1;
|
||||
private int? _triggerPowerSlot;
|
||||
|
||||
public BattleView(Transform parent, MetaService meta, Action onExit)
|
||||
{
|
||||
|
|
@ -187,6 +188,7 @@ namespace Vanguard.UI
|
|||
_pendingIntents.Clear();
|
||||
_highlightKeys.Clear();
|
||||
_pendingBoosterSlot = -1;
|
||||
_triggerPowerSlot = null;
|
||||
_showAllIntents = false;
|
||||
_logLines.Clear();
|
||||
RebuildLog();
|
||||
|
|
@ -432,7 +434,8 @@ namespace Vanguard.UI
|
|||
_finished = _view.IsFinished;
|
||||
_pendingIntents.Clear();
|
||||
_highlightKeys.Clear();
|
||||
_pendingBoosterSlot = -1;
|
||||
_triggerPowerSlot = null;
|
||||
PrepareTriggerSelection();
|
||||
if (_view.Clock != null)
|
||||
{
|
||||
_clockServerMs = _view.Clock.ServerTimeMs;
|
||||
|
|
@ -624,6 +627,7 @@ namespace Vanguard.UI
|
|||
_pendingIntents.Clear();
|
||||
_highlightKeys.Clear();
|
||||
_pendingBoosterSlot = -1;
|
||||
_triggerPowerSlot = null;
|
||||
_sending = true;
|
||||
SetStatus("Отправляем: " + Label(intent), Muted);
|
||||
|
||||
|
|
@ -1115,6 +1119,12 @@ namespace Vanguard.UI
|
|||
|
||||
var legal = _view.LegalIntents ?? new List<IntentPayload>();
|
||||
|
||||
if (_pendingIntents.Any(intent => intent is ResolveTriggerIntent)
|
||||
&& HandleTriggerTarget(target))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pendingIntents.Count > 0)
|
||||
{
|
||||
// Клик по своему заднему ряду выбирает карту поддержки.
|
||||
|
|
@ -1199,13 +1209,84 @@ namespace Vanguard.UI
|
|||
_pendingIntents.Clear();
|
||||
_highlightKeys.Clear();
|
||||
_pendingBoosterSlot = -1;
|
||||
_triggerPowerSlot = null;
|
||||
if (rebuild && _view != null)
|
||||
RebuildIntents(_view);
|
||||
}
|
||||
|
||||
private void PrepareTriggerSelection()
|
||||
{
|
||||
if (_view?.Trigger == null || _view.ActivePlayer != _view.You)
|
||||
return;
|
||||
|
||||
var triggers = (_view.LegalIntents ?? new List<IntentPayload>())
|
||||
.OfType<ResolveTriggerIntent>()
|
||||
.ToList();
|
||||
if (triggers.Count == 0)
|
||||
return;
|
||||
|
||||
_pendingIntents.Clear();
|
||||
_pendingIntents.AddRange(triggers);
|
||||
_triggerPowerSlot = null;
|
||||
RebuildHighlights();
|
||||
}
|
||||
|
||||
private bool HandleTriggerTarget(BoardTarget target)
|
||||
{
|
||||
if (_view?.Trigger == null || target.Player != _view.You)
|
||||
return false;
|
||||
|
||||
var triggers = _pendingIntents.OfType<ResolveTriggerIntent>().ToList();
|
||||
if (triggers.Count == 0)
|
||||
return false;
|
||||
|
||||
if (_triggerPowerSlot == null)
|
||||
{
|
||||
var powerTargets = triggers
|
||||
.Where(trigger => trigger.PowerTarget == target.Slot)
|
||||
.ToList();
|
||||
if (powerTargets.Count == 0)
|
||||
return false;
|
||||
|
||||
_triggerPowerSlot = target.Slot;
|
||||
_pendingIntents.Clear();
|
||||
_pendingIntents.AddRange(powerTargets);
|
||||
RebuildHighlights();
|
||||
RebuildIntents(_view);
|
||||
SetStatus(
|
||||
"Триггер: выберите цель эффекта.",
|
||||
new Color(0.98f, 0.82f, 0.42f));
|
||||
return true;
|
||||
}
|
||||
|
||||
var effect = triggers.FirstOrDefault(trigger => trigger.EffectTarget == target.Slot);
|
||||
if (effect == null)
|
||||
return false;
|
||||
|
||||
ClearSelection(rebuild: false);
|
||||
OnIntentClicked(effect);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void RebuildHighlights()
|
||||
{
|
||||
_highlightKeys.Clear();
|
||||
|
||||
if (_pendingIntents.Any(intent => intent is ResolveTriggerIntent))
|
||||
{
|
||||
foreach (var trigger in _pendingIntents.OfType<ResolveTriggerIntent>())
|
||||
{
|
||||
var slot = _triggerPowerSlot == null
|
||||
? trigger.PowerTarget
|
||||
: trigger.EffectTarget;
|
||||
var card = CardAt(_view.You, slot);
|
||||
_highlightKeys.Add(TargetKey(
|
||||
_view.You, slot, card != null ? card.PrintingId : null));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var intent in _pendingIntents)
|
||||
{
|
||||
if (TryGetTarget(intent, out var target))
|
||||
|
|
@ -1358,11 +1439,15 @@ namespace Vanguard.UI
|
|||
var prompt = UiKit.CreateText(
|
||||
_intents,
|
||||
"TargetPrompt",
|
||||
_pendingBoosterSlot >= 0
|
||||
? "Поддержка: " + CardName(
|
||||
CardAt(_view.You, _pendingBoosterSlot)?.PrintingId ?? string.Empty)
|
||||
+ ".\nВыберите цель атаки или «Отмена»."
|
||||
: "Выберите цель на поле.\nНажмите «Отмена», чтобы снять выбор.",
|
||||
_pendingIntents.Any(intent => intent is ResolveTriggerIntent)
|
||||
? (_triggerPowerSlot == null
|
||||
? "Триггер: выберите цель силы."
|
||||
: "Триггер: выберите цель эффекта.")
|
||||
: _pendingBoosterSlot >= 0
|
||||
? "Поддержка: " + CardName(
|
||||
CardAt(_view.You, _pendingBoosterSlot)?.PrintingId ?? string.Empty)
|
||||
+ ".\nВыберите цель атаки или «Отмена»."
|
||||
: "Выберите цель на поле.\nНажмите «Отмена», чтобы снять выбор.",
|
||||
16,
|
||||
new Color(0.98f, 0.82f, 0.42f),
|
||||
TextAnchor.UpperLeft);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,8 @@ http://localhost:5080
|
|||
- Боевой gray-box: доска, рука, часы, кнопки всех легальных интентов,
|
||||
сдача с подтверждением и экран результата.
|
||||
- Боевой UX: клик по картам/зонам, подсветка целей, сгруппированные
|
||||
действия, журнал событий и подсказки; event-анимации с очередью и скипом.
|
||||
действия, выбор силы/эффекта триггера, журнал событий и подсказки;
|
||||
event-анимации с очередью и скипом.
|
||||
- Карты в бою и коллекции: процедурные арты по клану, рамка, имя, ранг,
|
||||
триггер, сила/крит, REST и рубашка для скрытых карт.
|
||||
- Реальные арты: `CardImageService` ищет `Resources/CardArt/{imageKey}`;
|
||||
|
|
|
|||
|
|
@ -756,7 +756,8 @@ Battle; Boot и общие сервисы остаются персистент
|
|||
- Event-фидбек: всплывающие атака/guard/drive/урон/heal/retire, не
|
||||
блокирует ввод; очередь событий и кнопка «Пропустить анимации».
|
||||
- Боевой UX: клик по карте/зоне, подсветка целей, отдельная группировка
|
||||
действий, журнал последних событий и подсказки выбора.
|
||||
действий, выбор силы/эффекта триггера, журнал последних событий и
|
||||
подсказки выбора.
|
||||
- Поле: `R V R` / `R R R` у каждого игрока, зона урона слева, колода и
|
||||
дроп справа, зеркально у противника, зона защиты между полями.
|
||||
- Проверки визуального блока: Unity EditMode 2/2, `SCENE_SMOKE success=True`,
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@
|
|||
`tools/import_card_art.py`.
|
||||
- Взаимодействие в бою: клик по картам/зонам, подсветка целей,
|
||||
группировка действий (карты → цели, глобальные кнопки отдельно),
|
||||
журнал последних событий.
|
||||
выбор силы/эффекта триггера, журнал последних событий.
|
||||
- Отдельная сцена `Collection` и `CollectionView` удалены; коллекция
|
||||
открывается из Lobby кнопкой «Коллекция» (сцена `DeckBuilder`).
|
||||
- Не готово: файлы реальных артов (пайплайн готов), 3D-модели,
|
||||
|
|
|
|||
Loading…
Reference in New Issue