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,
|
Muted,
|
||||||
TextAnchor.MiddleRight);
|
TextAnchor.MiddleRight);
|
||||||
UiKit.SetPreferredHeight(guardian, 32f);
|
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)
|
private void AddHand(PlayerView self)
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,10 @@ namespace Vanguard.Tests
|
||||||
ActivePlayer = 0,
|
ActivePlayer = 0,
|
||||||
Phase = GamePhase.Main,
|
Phase = GamePhase.Main,
|
||||||
Players = new List<PlayerView> { self, opponent },
|
Players = new List<PlayerView> { self, opponent },
|
||||||
|
Battle = new Vanguard.Shared.Protocol.BattleView
|
||||||
|
{
|
||||||
|
GuardCards = new List<CardView> { Card("BT01/011EN", 7) },
|
||||||
|
},
|
||||||
Clock = new ClockView(),
|
Clock = new ClockView(),
|
||||||
LegalIntents = new List<IntentPayload>(),
|
LegalIntents = new List<IntentPayload>(),
|
||||||
};
|
};
|
||||||
|
|
@ -199,6 +203,7 @@ namespace Vanguard.Tests
|
||||||
Assert.IsTrue(Exists("Damage_0"));
|
Assert.IsTrue(Exists("Damage_0"));
|
||||||
Assert.IsTrue(Exists("Damage_1"));
|
Assert.IsTrue(Exists("Damage_1"));
|
||||||
Assert.IsTrue(Exists("Damage_2"));
|
Assert.IsTrue(Exists("Damage_2"));
|
||||||
|
Assert.IsTrue(Exists("Guard_7"));
|
||||||
Assert.IsTrue(Exists("Card_R4"));
|
Assert.IsTrue(Exists("Card_R4"));
|
||||||
var hasSidewaysCard = Resources.FindObjectsOfTypeAll<GameObject>()
|
var hasSidewaysCard = Resources.FindObjectsOfTypeAll<GameObject>()
|
||||||
.Where(go => go.name == "Card_R4")
|
.Where(go => go.name == "Card_R4")
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,9 @@ http://localhost:5080
|
||||||
триггер, сила/крит, REST поворотом на бок и рубашка для скрытых карт;
|
триггер, сила/крит, REST поворотом на бок и рубашка для скрытых карт;
|
||||||
call/ride-въезд, пульс атаки и призрак ухода в дроп.
|
call/ride-въезд, пульс атаки и призрак ухода в дроп.
|
||||||
- Зона урона: видимые карты на боку; heal выбирает карту урона, Counter
|
- Зона урона: видимые карты на боку; heal выбирает карту урона, Counter
|
||||||
Blast принимает выбранную закрытую карту. Маллиган — выбор карт в руке
|
Blast принимает выбранную открытую карту. Маллиган — выбор карт в руке
|
||||||
с обменом и добиром до пяти.
|
с обменом и добиром до пяти. Карты V/R и круга защиты открыты, в защите
|
||||||
|
показывается ряд карт.
|
||||||
- Реальные арты: `CardImageService` ищет `Resources/CardArt/{imageKey}`;
|
- Реальные арты: `CardImageService` ищет `Resources/CardArt/{imageKey}`;
|
||||||
`imageKey` приходит из `/api/cards`. Скачаны все **124** арта;
|
`imageKey` приходит из `/api/cards`. Скачаны все **124** арта;
|
||||||
импорт — `tools/import_card_art.py`.
|
импорт — `tools/import_card_art.py`.
|
||||||
|
|
|
||||||
|
|
@ -828,5 +828,7 @@ Battle; Boot и общие сервисы остаются персистент
|
||||||
раз, оба игрока; в первый ход атака запрещена; первый игрок случайный
|
раз, оба игрока; в первый ход атака запрещена; первый игрок случайный
|
||||||
(для тестов можно зафиксировать); `DeckValidator` требует ровно 16
|
(для тестов можно зафиксировать); `DeckValidator` требует ровно 16
|
||||||
триггеров, декбилдер показывает счётчик.
|
триггеров, декбилдер показывает счётчик.
|
||||||
|
- Карты на поле (`V`, `R`) и в круге защиты принудительно отдаются
|
||||||
|
клиенту открытыми; в круге защиты дополнительно рисуется ряд карт.
|
||||||
- Classic-режим не включает Stride/Вознесение, Legacy, Gift, Front-триггер
|
- Classic-режим не включает Stride/Вознесение, Legacy, Gift, Front-триггер
|
||||||
и Grade support.
|
и Grade support.
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,8 @@
|
||||||
без истории, MMR и наград.
|
без истории, MMR и наград.
|
||||||
- Боевой экран: реальный арт на всю карту, рамка по клану, имя, ранг,
|
- Боевой экран: реальный арт на всю карту, рамка по клану, имя, ранг,
|
||||||
триггер, сила/крит и рубашка; fallback — процедурная плашка.
|
триггер, сила/крит и рубашка; fallback — процедурная плашка.
|
||||||
Rest поворачивает карту на бок.
|
Rest поворачивает карту на бок. Карты в кругах V/R и в круге защиты
|
||||||
|
показываются открытыми.
|
||||||
- Поле: у каждого игрока два ряда `R V R` / `R R R`, слева зона урона
|
- Поле: у каждого игрока два ряда `R V R` / `R R R`, слева зона урона
|
||||||
(+soul), справа колода и ниже дроп; у противника зеркально; между
|
(+soul), справа колода и ниже дроп; у противника зеркально; между
|
||||||
полями — зона защиты со щитом и проверками.
|
полями — зона защиты со щитом и проверками.
|
||||||
|
|
|
||||||
|
|
@ -309,6 +309,9 @@ Draw, Stand.
|
||||||
8. Heal срабатывает при уроне **>=** урона соперника.
|
8. Heal срабатывает при уроне **>=** урона соперника.
|
||||||
9. Mulligan: один раз, любое количество карт, возврат в низ → добор → shuffle.
|
9. Mulligan: один раз, любое количество карт, возврат в низ → добор → shuffle.
|
||||||
10. В первый ход атаковать нельзя.
|
10. В первый ход атаковать нельзя.
|
||||||
|
11. Все карты на поле (авангард, арьергард) и в круге защиты лежат
|
||||||
|
открытыми; закрытыми могут быть только карты в руке/колоде/уроне после
|
||||||
|
Counter Blast.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -597,6 +597,7 @@ public sealed class GameEngine
|
||||||
|
|
||||||
p.Soul.Remove(card);
|
p.Soul.Remove(card);
|
||||||
card.Rested = false;
|
card.Rested = false;
|
||||||
|
card.FaceUp = true;
|
||||||
p.RearGuards[slot] = card;
|
p.RearGuards[slot] = card;
|
||||||
|
|
||||||
_events.Add(new UnitCalledEvent(player, slot, card.PrintingId));
|
_events.Add(new UnitCalledEvent(player, slot, card.PrintingId));
|
||||||
|
|
@ -1178,6 +1179,7 @@ public sealed class GameEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
card.Rested = false;
|
card.Rested = false;
|
||||||
|
card.FaceUp = true;
|
||||||
p.RearGuards[slot] = card;
|
p.RearGuards[slot] = card;
|
||||||
_events.Add(new UnitCalledEvent(player, slot, card.PrintingId));
|
_events.Add(new UnitCalledEvent(player, slot, card.PrintingId));
|
||||||
|
|
||||||
|
|
@ -1220,6 +1222,7 @@ public sealed class GameEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
card.Rested = false;
|
card.Rested = false;
|
||||||
|
card.FaceUp = true;
|
||||||
p.Vanguard = card;
|
p.Vanguard = card;
|
||||||
_events.Add(new UnitRodeEvent(player, card.PrintingId));
|
_events.Add(new UnitRodeEvent(player, card.PrintingId));
|
||||||
|
|
||||||
|
|
@ -1703,6 +1706,7 @@ public sealed class GameEngine
|
||||||
|
|
||||||
var card = p.Deck[index];
|
var card = p.Deck[index];
|
||||||
p.Deck.RemoveAt(index);
|
p.Deck.RemoveAt(index);
|
||||||
|
card.FaceUp = true;
|
||||||
p.Vanguard = card;
|
p.Vanguard = card;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1832,6 +1836,7 @@ public sealed class GameEngine
|
||||||
|
|
||||||
player.Hand.RemoveAt(index);
|
player.Hand.RemoveAt(index);
|
||||||
card.Rested = false;
|
card.Rested = false;
|
||||||
|
card.FaceUp = true;
|
||||||
player.Vanguard = card;
|
player.Vanguard = card;
|
||||||
|
|
||||||
_events.Add(new UnitRodeEvent(State.ActivePlayer, card.PrintingId));
|
_events.Add(new UnitRodeEvent(State.ActivePlayer, card.PrintingId));
|
||||||
|
|
@ -1877,6 +1882,7 @@ public sealed class GameEngine
|
||||||
var card = player.Hand[index];
|
var card = player.Hand[index];
|
||||||
player.Hand.RemoveAt(index);
|
player.Hand.RemoveAt(index);
|
||||||
card.Rested = false;
|
card.Rested = false;
|
||||||
|
card.FaceUp = true;
|
||||||
player.RearGuards[slot] = card;
|
player.RearGuards[slot] = card;
|
||||||
|
|
||||||
_events.Add(new UnitCalledEvent(State.ActivePlayer, slot, card.PrintingId));
|
_events.Add(new UnitCalledEvent(State.ActivePlayer, slot, card.PrintingId));
|
||||||
|
|
@ -2097,6 +2103,7 @@ public sealed class GameEngine
|
||||||
var shield = def.IsSentinel ? 0 : def.Shield;
|
var shield = def.IsSentinel ? 0 : def.Shield;
|
||||||
|
|
||||||
defender.Hand.RemoveAt(index);
|
defender.Hand.RemoveAt(index);
|
||||||
|
card.FaceUp = true;
|
||||||
defender.Guardian.Add(card);
|
defender.Guardian.Add(card);
|
||||||
battle.GuardCards.Add(card);
|
battle.GuardCards.Add(card);
|
||||||
battle.GuardShield += shield;
|
battle.GuardShield += shield;
|
||||||
|
|
@ -2161,6 +2168,7 @@ public sealed class GameEngine
|
||||||
return CommandResult.Reject("Эта карта не может перехватывать.");
|
return CommandResult.Reject("Эта карта не может перехватывать.");
|
||||||
|
|
||||||
defender.RearGuards[slot] = null;
|
defender.RearGuards[slot] = null;
|
||||||
|
unit.FaceUp = true;
|
||||||
defender.Guardian.Add(unit);
|
defender.Guardian.Add(unit);
|
||||||
battle.GuardCards.Add(unit);
|
battle.GuardCards.Add(unit);
|
||||||
battle.Interceptor = unit;
|
battle.Interceptor = unit;
|
||||||
|
|
|
||||||
|
|
@ -76,12 +76,18 @@ public static class MatchProjection
|
||||||
? player.Hand.Select(card => ProjectCard(engine, card)).ToList()
|
? player.Hand.Select(card => ProjectCard(engine, card)).ToList()
|
||||||
: new List<CardView>(),
|
: 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
|
RearGuards = player.RearGuards
|
||||||
.Select(card => card is null ? null : ProjectCard(engine, card))
|
.Select(card => card is null
|
||||||
|
? null
|
||||||
|
: ProjectCard(engine, card, forceFaceUp: true))
|
||||||
.ToArray(),
|
.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(),
|
Soul = player.Soul.Select(card => ProjectCard(engine, card)).ToList(),
|
||||||
|
|
||||||
FaceDownDamage = player.Damage.Count(card => !card.FaceUp),
|
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);
|
var definition = engine.State.Catalog.CardOf(card.PrintingId);
|
||||||
|
|
||||||
|
|
@ -105,7 +114,7 @@ public static class MatchProjection
|
||||||
InstanceId = card.Id,
|
InstanceId = card.Id,
|
||||||
PrintingId = card.PrintingId,
|
PrintingId = card.PrintingId,
|
||||||
Rested = card.Rested,
|
Rested = card.Rested,
|
||||||
FaceUp = card.FaceUp,
|
FaceUp = forceFaceUp || card.FaceUp,
|
||||||
BasePower = definition.Power,
|
BasePower = definition.Power,
|
||||||
Power = engine.EffectivePower(card),
|
Power = engine.EffectivePower(card),
|
||||||
BaseCritical = definition.Critical,
|
BaseCritical = definition.Critical,
|
||||||
|
|
@ -133,7 +142,9 @@ public static class MatchProjection
|
||||||
? -1
|
? -1
|
||||||
: Array.IndexOf(defender.RearGuards, battle.Interceptor),
|
: Array.IndexOf(defender.RearGuards, battle.Interceptor),
|
||||||
BoosterSlot = battle.BoosterSlot,
|
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