Show vanguard, rear-guard and guard cards face up
CI / test (push) Successful in 2m11s
Details
CI / test (push) Successful in 2m11s
Details
This commit is contained in:
parent
7035c11873
commit
e23116946c
|
|
@ -1421,6 +1421,44 @@ namespace Vanguard.UI
|
|||
Muted,
|
||||
TextAnchor.MiddleRight);
|
||||
UiKit.SetPreferredHeight(guardian, 32f);
|
||||
|
||||
AddGuardCards(guard, view);
|
||||
}
|
||||
|
||||
private void AddGuardCards(Transform parent, MatchView view)
|
||||
{
|
||||
var cards = view.Battle?.GuardCards;
|
||||
if (cards == null || cards.Count == 0)
|
||||
return;
|
||||
|
||||
var row = UiKit.CreatePanel(parent, "GuardCards", Color.clear);
|
||||
var element = row.gameObject.AddComponent<LayoutElement>();
|
||||
element.preferredWidth = cards.Count * 52f;
|
||||
element.preferredHeight = 58f;
|
||||
element.flexibleWidth = 0f;
|
||||
UiKit.AddHorizontalLayout(row, 0, 4);
|
||||
|
||||
foreach (var card in cards)
|
||||
{
|
||||
var tile = UiKit.CreatePanel(row, "Guard_" + card.InstanceId, Color.white);
|
||||
var tileElement = tile.gameObject.AddComponent<LayoutElement>();
|
||||
tileElement.preferredWidth = 48f;
|
||||
tileElement.preferredHeight = 58f;
|
||||
tileElement.flexibleWidth = 0f;
|
||||
|
||||
var image = tile.GetComponent<Image>();
|
||||
_catalog.TryGetValue(card.PrintingId, out var meta);
|
||||
CardImageService.Apply(
|
||||
image,
|
||||
meta != null ? meta.ImageKey : null,
|
||||
CardArt.ForCard(
|
||||
meta != null ? meta.NameId : card.PrintingId,
|
||||
meta != null ? meta.Clan : "None"));
|
||||
|
||||
var outline = tile.gameObject.AddComponent<Outline>();
|
||||
outline.effectColor = new Color(0.55f, 0.86f, 1f, 0.85f);
|
||||
outline.effectDistance = new Vector2(1f, -1f);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddHand(PlayerView self)
|
||||
|
|
|
|||
|
|
@ -184,6 +184,10 @@ namespace Vanguard.Tests
|
|||
ActivePlayer = 0,
|
||||
Phase = GamePhase.Main,
|
||||
Players = new List<PlayerView> { self, opponent },
|
||||
Battle = new Vanguard.Shared.Protocol.BattleView
|
||||
{
|
||||
GuardCards = new List<CardView> { Card("BT01/011EN", 7) },
|
||||
},
|
||||
Clock = new ClockView(),
|
||||
LegalIntents = new List<IntentPayload>(),
|
||||
};
|
||||
|
|
@ -199,6 +203,7 @@ namespace Vanguard.Tests
|
|||
Assert.IsTrue(Exists("Damage_0"));
|
||||
Assert.IsTrue(Exists("Damage_1"));
|
||||
Assert.IsTrue(Exists("Damage_2"));
|
||||
Assert.IsTrue(Exists("Guard_7"));
|
||||
Assert.IsTrue(Exists("Card_R4"));
|
||||
var hasSidewaysCard = Resources.FindObjectsOfTypeAll<GameObject>()
|
||||
.Where(go => go.name == "Card_R4")
|
||||
|
|
|
|||
|
|
@ -71,8 +71,9 @@ http://localhost:5080
|
|||
триггер, сила/крит, REST поворотом на бок и рубашка для скрытых карт;
|
||||
call/ride-въезд, пульс атаки и призрак ухода в дроп.
|
||||
- Зона урона: видимые карты на боку; heal выбирает карту урона, Counter
|
||||
Blast принимает выбранную закрытую карту. Маллиган — выбор карт в руке
|
||||
с обменом и добиром до пяти.
|
||||
Blast принимает выбранную открытую карту. Маллиган — выбор карт в руке
|
||||
с обменом и добиром до пяти. Карты V/R и круга защиты открыты, в защите
|
||||
показывается ряд карт.
|
||||
- Реальные арты: `CardImageService` ищет `Resources/CardArt/{imageKey}`;
|
||||
`imageKey` приходит из `/api/cards`. Скачаны все **124** арта;
|
||||
импорт — `tools/import_card_art.py`.
|
||||
|
|
|
|||
|
|
@ -828,5 +828,7 @@ Battle; Boot и общие сервисы остаются персистент
|
|||
раз, оба игрока; в первый ход атака запрещена; первый игрок случайный
|
||||
(для тестов можно зафиксировать); `DeckValidator` требует ровно 16
|
||||
триггеров, декбилдер показывает счётчик.
|
||||
- Карты на поле (`V`, `R`) и в круге защиты принудительно отдаются
|
||||
клиенту открытыми; в круге защиты дополнительно рисуется ряд карт.
|
||||
- Classic-режим не включает Stride/Вознесение, Legacy, Gift, Front-триггер
|
||||
и Grade support.
|
||||
|
|
|
|||
|
|
@ -63,7 +63,8 @@
|
|||
без истории, MMR и наград.
|
||||
- Боевой экран: реальный арт на всю карту, рамка по клану, имя, ранг,
|
||||
триггер, сила/крит и рубашка; fallback — процедурная плашка.
|
||||
Rest поворачивает карту на бок.
|
||||
Rest поворачивает карту на бок. Карты в кругах V/R и в круге защиты
|
||||
показываются открытыми.
|
||||
- Поле: у каждого игрока два ряда `R V R` / `R R R`, слева зона урона
|
||||
(+soul), справа колода и ниже дроп; у противника зеркально; между
|
||||
полями — зона защиты со щитом и проверками.
|
||||
|
|
|
|||
|
|
@ -309,6 +309,9 @@ Draw, Stand.
|
|||
8. Heal срабатывает при уроне **>=** урона соперника.
|
||||
9. Mulligan: один раз, любое количество карт, возврат в низ → добор → shuffle.
|
||||
10. В первый ход атаковать нельзя.
|
||||
11. Все карты на поле (авангард, арьергард) и в круге защиты лежат
|
||||
открытыми; закрытыми могут быть только карты в руке/колоде/уроне после
|
||||
Counter Blast.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -597,6 +597,7 @@ public sealed class GameEngine
|
|||
|
||||
p.Soul.Remove(card);
|
||||
card.Rested = false;
|
||||
card.FaceUp = true;
|
||||
p.RearGuards[slot] = card;
|
||||
|
||||
_events.Add(new UnitCalledEvent(player, slot, card.PrintingId));
|
||||
|
|
@ -1178,6 +1179,7 @@ public sealed class GameEngine
|
|||
}
|
||||
|
||||
card.Rested = false;
|
||||
card.FaceUp = true;
|
||||
p.RearGuards[slot] = card;
|
||||
_events.Add(new UnitCalledEvent(player, slot, card.PrintingId));
|
||||
|
||||
|
|
@ -1220,6 +1222,7 @@ public sealed class GameEngine
|
|||
}
|
||||
|
||||
card.Rested = false;
|
||||
card.FaceUp = true;
|
||||
p.Vanguard = card;
|
||||
_events.Add(new UnitRodeEvent(player, card.PrintingId));
|
||||
|
||||
|
|
@ -1703,6 +1706,7 @@ public sealed class GameEngine
|
|||
|
||||
var card = p.Deck[index];
|
||||
p.Deck.RemoveAt(index);
|
||||
card.FaceUp = true;
|
||||
p.Vanguard = card;
|
||||
}
|
||||
|
||||
|
|
@ -1832,6 +1836,7 @@ public sealed class GameEngine
|
|||
|
||||
player.Hand.RemoveAt(index);
|
||||
card.Rested = false;
|
||||
card.FaceUp = true;
|
||||
player.Vanguard = card;
|
||||
|
||||
_events.Add(new UnitRodeEvent(State.ActivePlayer, card.PrintingId));
|
||||
|
|
@ -1877,6 +1882,7 @@ public sealed class GameEngine
|
|||
var card = player.Hand[index];
|
||||
player.Hand.RemoveAt(index);
|
||||
card.Rested = false;
|
||||
card.FaceUp = true;
|
||||
player.RearGuards[slot] = card;
|
||||
|
||||
_events.Add(new UnitCalledEvent(State.ActivePlayer, slot, card.PrintingId));
|
||||
|
|
@ -2097,6 +2103,7 @@ public sealed class GameEngine
|
|||
var shield = def.IsSentinel ? 0 : def.Shield;
|
||||
|
||||
defender.Hand.RemoveAt(index);
|
||||
card.FaceUp = true;
|
||||
defender.Guardian.Add(card);
|
||||
battle.GuardCards.Add(card);
|
||||
battle.GuardShield += shield;
|
||||
|
|
@ -2161,6 +2168,7 @@ public sealed class GameEngine
|
|||
return CommandResult.Reject("Эта карта не может перехватывать.");
|
||||
|
||||
defender.RearGuards[slot] = null;
|
||||
unit.FaceUp = true;
|
||||
defender.Guardian.Add(unit);
|
||||
battle.GuardCards.Add(unit);
|
||||
battle.Interceptor = unit;
|
||||
|
|
|
|||
|
|
@ -76,12 +76,18 @@ public static class MatchProjection
|
|||
? player.Hand.Select(card => ProjectCard(engine, card)).ToList()
|
||||
: new List<CardView>(),
|
||||
|
||||
Vanguard = player.Vanguard is null ? null : ProjectCard(engine, player.Vanguard),
|
||||
Vanguard = player.Vanguard is null
|
||||
? null
|
||||
: ProjectCard(engine, player.Vanguard, forceFaceUp: true),
|
||||
RearGuards = player.RearGuards
|
||||
.Select(card => card is null ? null : ProjectCard(engine, card))
|
||||
.Select(card => card is null
|
||||
? null
|
||||
: ProjectCard(engine, card, forceFaceUp: true))
|
||||
.ToArray(),
|
||||
|
||||
Guardian = player.Guardian.Select(card => ProjectCard(engine, card)).ToList(),
|
||||
Guardian = player.Guardian
|
||||
.Select(card => ProjectCard(engine, card, forceFaceUp: true))
|
||||
.ToList(),
|
||||
Soul = player.Soul.Select(card => ProjectCard(engine, card)).ToList(),
|
||||
|
||||
FaceDownDamage = player.Damage.Count(card => !card.FaceUp),
|
||||
|
|
@ -96,7 +102,10 @@ public static class MatchProjection
|
|||
};
|
||||
}
|
||||
|
||||
private static CardView ProjectCard(GameEngine engine, CardInstance card)
|
||||
private static CardView ProjectCard(
|
||||
GameEngine engine,
|
||||
CardInstance card,
|
||||
bool forceFaceUp = false)
|
||||
{
|
||||
var definition = engine.State.Catalog.CardOf(card.PrintingId);
|
||||
|
||||
|
|
@ -105,7 +114,7 @@ public static class MatchProjection
|
|||
InstanceId = card.Id,
|
||||
PrintingId = card.PrintingId,
|
||||
Rested = card.Rested,
|
||||
FaceUp = card.FaceUp,
|
||||
FaceUp = forceFaceUp || card.FaceUp,
|
||||
BasePower = definition.Power,
|
||||
Power = engine.EffectivePower(card),
|
||||
BaseCritical = definition.Critical,
|
||||
|
|
@ -133,7 +142,9 @@ public static class MatchProjection
|
|||
? -1
|
||||
: Array.IndexOf(defender.RearGuards, battle.Interceptor),
|
||||
BoosterSlot = battle.BoosterSlot,
|
||||
GuardCards = battle.GuardCards.Select(card => ProjectCard(engine, card)).ToList(),
|
||||
GuardCards = battle.GuardCards
|
||||
.Select(card => ProjectCard(engine, card, forceFaceUp: true))
|
||||
.ToList(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue