valtech-components 4.0.586 → 4.0.587
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/components/organisms/mini-games/christianity-game.component.mjs +1529 -994
- package/esm2022/lib/components/organisms/mini-games/christianity-rules.mjs +46 -13
- package/esm2022/lib/version.mjs +2 -2
- package/fesm2022/valtech-components.mjs +1561 -993
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/molecules/phone-display/phone-display.component.d.ts +1 -1
- package/lib/components/organisms/mini-games/chessimals-game.component.d.ts +1 -1
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -59,7 +59,7 @@ import fixWebmDuration from 'fix-webm-duration';
|
|
|
59
59
|
* Current version of valtech-components.
|
|
60
60
|
* This is automatically updated during the publish process.
|
|
61
61
|
*/
|
|
62
|
-
const VERSION = '4.0.
|
|
62
|
+
const VERSION = '4.0.587';
|
|
63
63
|
|
|
64
64
|
// Control de estado de refresco (singleton a nivel de módulo)
|
|
65
65
|
let isRefreshing = false;
|
|
@@ -73992,7 +73992,14 @@ function canPlayCard(game, seat, card) {
|
|
|
73992
73992
|
if (card.type === 'offering')
|
|
73993
73993
|
return !player.offeringPlayedThisTurn;
|
|
73994
73994
|
if (card.type === 'character') {
|
|
73995
|
-
return readyOfferings(player) >= (card.cost ?? 0) &&
|
|
73995
|
+
return (readyOfferings(player) >= (card.cost ?? 0) &&
|
|
73996
|
+
player.battleZone.length < CHRISTIANITY_BATTLE_SLOTS);
|
|
73997
|
+
}
|
|
73998
|
+
if (card.type === 'action' ||
|
|
73999
|
+
card.type === 'wisdom' ||
|
|
74000
|
+
card.type === 'event' ||
|
|
74001
|
+
card.type === 'tool') {
|
|
74002
|
+
return readyOfferings(player) >= (card.cost ?? 0);
|
|
73996
74003
|
}
|
|
73997
74004
|
if (card.type === 'place')
|
|
73998
74005
|
return true;
|
|
@@ -74028,7 +74035,7 @@ function playCardFromHand(game, seat, card, options = {}) {
|
|
|
74028
74035
|
player.offeringPlayedThisTurn = true;
|
|
74029
74036
|
}
|
|
74030
74037
|
else if (card.type === 'character') {
|
|
74031
|
-
const occupiedSlots = new Set(player.battleZone.map((character, index) => Number.isInteger(character.slot) ? character.slot ?? index : index));
|
|
74038
|
+
const occupiedSlots = new Set(player.battleZone.map((character, index) => Number.isInteger(character.slot) ? (character.slot ?? index) : index));
|
|
74032
74039
|
const targetSlot = options.slotIndex ?? [0, 1, 2, 3].find(index => !occupiedSlots.has(index));
|
|
74033
74040
|
if (targetSlot === undefined || occupiedSlots.has(targetSlot)) {
|
|
74034
74041
|
return { game, played: false, playedOfferingValue: 0, spentOfferings: 0, log: [] };
|
|
@@ -74050,6 +74057,16 @@ function playCardFromHand(game, seat, card, options = {}) {
|
|
|
74050
74057
|
});
|
|
74051
74058
|
player.battleZone.sort((left, right) => (left.slot ?? 0) - (right.slot ?? 0));
|
|
74052
74059
|
}
|
|
74060
|
+
else if (card.type === 'action' ||
|
|
74061
|
+
card.type === 'wisdom' ||
|
|
74062
|
+
card.type === 'event' ||
|
|
74063
|
+
card.type === 'tool') {
|
|
74064
|
+
spentOfferings = card.cost ?? 0;
|
|
74065
|
+
if (spentOfferings > 0) {
|
|
74066
|
+
spendOfferings(player, spentOfferings);
|
|
74067
|
+
}
|
|
74068
|
+
next.historyZone.push(card.id);
|
|
74069
|
+
}
|
|
74053
74070
|
else if (card.type === 'place') {
|
|
74054
74071
|
const previousPlace = next.placeZone[0];
|
|
74055
74072
|
if (previousPlace) {
|
|
@@ -74086,9 +74103,7 @@ function resolveOfferingAbility(game, seat, offeringInstanceId, messages) {
|
|
|
74086
74103
|
}
|
|
74087
74104
|
const reserveGain = offeringAbilityReserveGain(liveOffering.abilityText, liveOffering.value);
|
|
74088
74105
|
player.temporaryOfferingReserve = (player.temporaryOfferingReserve ?? 0) + reserveGain;
|
|
74089
|
-
player.offerings = player.offerings.map(card =>
|
|
74090
|
-
? { ...card, abilityUsedThisTurn: true }
|
|
74091
|
-
: card));
|
|
74106
|
+
player.offerings = player.offerings.map(card => card.instanceId === offeringInstanceId ? { ...card, abilityUsedThisTurn: true } : card);
|
|
74092
74107
|
player.leaderHp = Math.max(0, player.leaderHp - 1);
|
|
74093
74108
|
next.revision++;
|
|
74094
74109
|
const log = [`${liveOffering.name}: ${liveOffering.abilityName}.`];
|
|
@@ -74103,6 +74118,12 @@ function playCardLog(card, displayName) {
|
|
|
74103
74118
|
return `${displayName} queda lista como ofrenda.`;
|
|
74104
74119
|
if (card.type === 'place')
|
|
74105
74120
|
return `${displayName} queda como lugar activo.`;
|
|
74121
|
+
if (card.type === 'action' || card.type === 'event')
|
|
74122
|
+
return `${displayName} fue jugada.`;
|
|
74123
|
+
if (card.type === 'wisdom')
|
|
74124
|
+
return `${displayName} fue revelada.`;
|
|
74125
|
+
if (card.type === 'tool')
|
|
74126
|
+
return `${displayName} fue equipada.`;
|
|
74106
74127
|
return `${displayName} entra en batalla.`;
|
|
74107
74128
|
}
|
|
74108
74129
|
function resolveAttackLeader(game, attackerSeat, attackerInstanceId, messages) {
|
|
@@ -74117,7 +74138,9 @@ function resolveAttackLeader(game, attackerSeat, attackerInstanceId, messages) {
|
|
|
74117
74138
|
const damage = attacker.attack;
|
|
74118
74139
|
next.players[defenderSeat].leaderHp = Math.max(0, next.players[defenderSeat].leaderHp - damage);
|
|
74119
74140
|
attacker.canAttack = false;
|
|
74120
|
-
const log = [
|
|
74141
|
+
const log = [
|
|
74142
|
+
`${attacker.name} ${attackerSeat === 'P1' ? messages.attacksOpponentLeader : messages.attacksYourLeader}`,
|
|
74143
|
+
];
|
|
74121
74144
|
evaluateVictory(next, log, messages);
|
|
74122
74145
|
next.revision++;
|
|
74123
74146
|
next.log = [...log, ...next.log].slice(0, 4);
|
|
@@ -74142,7 +74165,13 @@ function resolveAttackCharacter(game, attackerSeat, attackerInstanceId, targetIn
|
|
|
74142
74165
|
evaluateVictory(next, log, messages);
|
|
74143
74166
|
next.revision++;
|
|
74144
74167
|
next.log = [...log, ...next.log].slice(0, 4);
|
|
74145
|
-
return {
|
|
74168
|
+
return {
|
|
74169
|
+
game: next,
|
|
74170
|
+
attacked: true,
|
|
74171
|
+
attackerDamage: target.attack,
|
|
74172
|
+
targetDamage: attacker.attack,
|
|
74173
|
+
log,
|
|
74174
|
+
};
|
|
74146
74175
|
}
|
|
74147
74176
|
function advanceTurn(game, messages) {
|
|
74148
74177
|
game.players[game.turnOwner].temporaryOfferingReserve = 0;
|
|
@@ -74150,7 +74179,11 @@ function advanceTurn(game, messages) {
|
|
|
74150
74179
|
game.turnCount++;
|
|
74151
74180
|
const current = game.players[game.turnOwner];
|
|
74152
74181
|
current.offeringPlayedThisTurn = false;
|
|
74153
|
-
current.offerings = current.offerings.map(offering => ({
|
|
74182
|
+
current.offerings = current.offerings.map(offering => ({
|
|
74183
|
+
...offering,
|
|
74184
|
+
ready: true,
|
|
74185
|
+
abilityUsedThisTurn: false,
|
|
74186
|
+
}));
|
|
74154
74187
|
current.battleZone = current.battleZone.map(card => ({ ...card, canAttack: true }));
|
|
74155
74188
|
const drawnCard = game.sharedDeck.shift();
|
|
74156
74189
|
const log = [];
|
|
@@ -74172,16 +74205,16 @@ function advanceTurn(game, messages) {
|
|
|
74172
74205
|
];
|
|
74173
74206
|
}
|
|
74174
74207
|
function evaluateVictory(game, log, messages) {
|
|
74175
|
-
if (game.players.P1.leaderHp > 0
|
|
74176
|
-
&& game.players.P2.leaderHp > 0
|
|
74177
|
-
&& game.sharedDeck.length > 0)
|
|
74208
|
+
if (game.players.P1.leaderHp > 0 && game.players.P2.leaderHp > 0 && game.sharedDeck.length > 0)
|
|
74178
74209
|
return;
|
|
74179
74210
|
game.status = 'finished';
|
|
74180
74211
|
const winner = game.players.P1.leaderHp <= 0
|
|
74181
74212
|
? 'P2'
|
|
74182
74213
|
: game.players.P2.leaderHp <= 0
|
|
74183
74214
|
? 'P1'
|
|
74184
|
-
: game.players.P1.leaderHp >= game.players.P2.leaderHp
|
|
74215
|
+
: game.players.P1.leaderHp >= game.players.P2.leaderHp
|
|
74216
|
+
? 'P1'
|
|
74217
|
+
: 'P2';
|
|
74185
74218
|
game.matchScore[winner] += 1;
|
|
74186
74219
|
log.push(winner === 'P1' ? messages.youWin : messages.opponentWins);
|
|
74187
74220
|
}
|
|
@@ -74573,10 +74606,58 @@ const STARTER_CARDS = {
|
|
|
74573
74606
|
author: 'MVP',
|
|
74574
74607
|
rarity: 'normal',
|
|
74575
74608
|
},
|
|
74576
|
-
p_guard: {
|
|
74577
|
-
|
|
74578
|
-
|
|
74579
|
-
|
|
74609
|
+
p_guard: {
|
|
74610
|
+
id: 'p_guard',
|
|
74611
|
+
name: 'Guard',
|
|
74612
|
+
type: 'character',
|
|
74613
|
+
cost: 2,
|
|
74614
|
+
attack: 1,
|
|
74615
|
+
life: 3,
|
|
74616
|
+
edition: 'GEN',
|
|
74617
|
+
collectorNumber: '003/020',
|
|
74618
|
+
year: '2026',
|
|
74619
|
+
author: 'MVP',
|
|
74620
|
+
rarity: 'normal',
|
|
74621
|
+
},
|
|
74622
|
+
p_warrior: {
|
|
74623
|
+
id: 'p_warrior',
|
|
74624
|
+
name: 'Warrior',
|
|
74625
|
+
type: 'character',
|
|
74626
|
+
cost: 2,
|
|
74627
|
+
attack: 2,
|
|
74628
|
+
life: 2,
|
|
74629
|
+
edition: 'GEN',
|
|
74630
|
+
collectorNumber: '004/020',
|
|
74631
|
+
year: '2026',
|
|
74632
|
+
author: 'MVP',
|
|
74633
|
+
rarity: 'normal',
|
|
74634
|
+
},
|
|
74635
|
+
p_elder: {
|
|
74636
|
+
id: 'p_elder',
|
|
74637
|
+
name: 'Elder',
|
|
74638
|
+
type: 'character',
|
|
74639
|
+
cost: 3,
|
|
74640
|
+
attack: 2,
|
|
74641
|
+
life: 4,
|
|
74642
|
+
edition: 'GEN',
|
|
74643
|
+
collectorNumber: '005/020',
|
|
74644
|
+
year: '2026',
|
|
74645
|
+
author: 'MVP',
|
|
74646
|
+
rarity: 'uncommon',
|
|
74647
|
+
},
|
|
74648
|
+
p_champion: {
|
|
74649
|
+
id: 'p_champion',
|
|
74650
|
+
name: 'Champion',
|
|
74651
|
+
type: 'character',
|
|
74652
|
+
cost: 4,
|
|
74653
|
+
attack: 4,
|
|
74654
|
+
life: 4,
|
|
74655
|
+
edition: 'GEN',
|
|
74656
|
+
collectorNumber: '006/020',
|
|
74657
|
+
year: '2026',
|
|
74658
|
+
author: 'MVP',
|
|
74659
|
+
rarity: 'rare',
|
|
74660
|
+
},
|
|
74580
74661
|
};
|
|
74581
74662
|
const STARTING_SHARED_DECK = [
|
|
74582
74663
|
'o_simple',
|
|
@@ -74620,7 +74701,14 @@ const STARTING_GAME = {
|
|
|
74620
74701
|
leaderHp: 15,
|
|
74621
74702
|
leaderMaxHp: 15,
|
|
74622
74703
|
offerings: [
|
|
74623
|
-
{
|
|
74704
|
+
{
|
|
74705
|
+
instanceId: 'p1_offering_001',
|
|
74706
|
+
cardId: 'o_simple',
|
|
74707
|
+
name: 'Ofrenda simple',
|
|
74708
|
+
owner: 'P1',
|
|
74709
|
+
ready: true,
|
|
74710
|
+
value: 1,
|
|
74711
|
+
},
|
|
74624
74712
|
{
|
|
74625
74713
|
instanceId: 'p1_offering_002',
|
|
74626
74714
|
cardId: 'o_forbidden',
|
|
@@ -74645,7 +74733,16 @@ const STARTING_GAME = {
|
|
|
74645
74733
|
leaderName: 'Noah',
|
|
74646
74734
|
leaderHp: 15,
|
|
74647
74735
|
leaderMaxHp: 15,
|
|
74648
|
-
offerings: [
|
|
74736
|
+
offerings: [
|
|
74737
|
+
{
|
|
74738
|
+
instanceId: 'p2_offering_001',
|
|
74739
|
+
cardId: 'o_simple',
|
|
74740
|
+
name: 'Ofrenda simple',
|
|
74741
|
+
owner: 'P2',
|
|
74742
|
+
ready: true,
|
|
74743
|
+
value: 1,
|
|
74744
|
+
},
|
|
74745
|
+
],
|
|
74649
74746
|
offeringPlayedThisTurn: false,
|
|
74650
74747
|
handCount: 4,
|
|
74651
74748
|
battleZone: [
|
|
@@ -74680,7 +74777,9 @@ class ChristianityGameComponent {
|
|
|
74680
74777
|
const nextIndex = (currentIndex + direction + items.length) % items.length;
|
|
74681
74778
|
const item = items[nextIndex];
|
|
74682
74779
|
if (item.kind === 'history') {
|
|
74683
|
-
return this.definitionToRenderCard(this.cardDefinition(item.cardId), {
|
|
74780
|
+
return this.definitionToRenderCard(this.cardDefinition(item.cardId), {
|
|
74781
|
+
statusText: this.t('christianityHistory'),
|
|
74782
|
+
});
|
|
74684
74783
|
}
|
|
74685
74784
|
if (item.kind === 'hand') {
|
|
74686
74785
|
return this.definitionToRenderCard(this.cardDefinition(item.cardId));
|
|
@@ -74787,7 +74886,9 @@ class ChristianityGameComponent {
|
|
|
74787
74886
|
if (this.tutorialPhase() === 'coin') {
|
|
74788
74887
|
return setup.coinWinner === 'P1' ? this.t('christianityCoinYouWon') : this.t('christianityCoinRivalWon');
|
|
74789
74888
|
}
|
|
74790
|
-
return setup.leaderPicker === 'P1'
|
|
74889
|
+
return setup.leaderPicker === 'P1'
|
|
74890
|
+
? this.t('christianityChooseLeaderTitle')
|
|
74891
|
+
: this.t('christianityRivalChoosesLeaderTitle');
|
|
74791
74892
|
});
|
|
74792
74893
|
this.setupBody = computed(() => {
|
|
74793
74894
|
const setup = this.tutorialSetup();
|
|
@@ -74814,7 +74915,11 @@ class ChristianityGameComponent {
|
|
|
74814
74915
|
this.hasOpponentGuards = computed(() => this.opponent().battleZone.length > 0);
|
|
74815
74916
|
this.opponentHandCount = computed(() => this.opponent().handCount ?? this.opponent().hand?.length ?? 0);
|
|
74816
74917
|
this.galleryCards = computed(() => {
|
|
74817
|
-
const query = this.gallerySearch()
|
|
74918
|
+
const query = this.gallerySearch()
|
|
74919
|
+
.trim()
|
|
74920
|
+
.toLowerCase()
|
|
74921
|
+
.normalize('NFD')
|
|
74922
|
+
.replace(/[\u0300-\u036f]/g, '');
|
|
74818
74923
|
const type = this.galleryType();
|
|
74819
74924
|
return this.allCatalogCards()
|
|
74820
74925
|
.filter(card => this.isClassicGalleryCard(card))
|
|
@@ -74849,12 +74954,12 @@ class ChristianityGameComponent {
|
|
|
74849
74954
|
{ value: 'place', label: this.t('christianityPlaceCard') },
|
|
74850
74955
|
{ value: 'event', label: this.t('christianityEventCard') },
|
|
74851
74956
|
]);
|
|
74852
|
-
this.hasModalOverlay = computed(() => !!this.selectedPreview()
|
|
74853
|
-
|
|
74854
|
-
|
|
74855
|
-
|
|
74856
|
-
|
|
74857
|
-
|
|
74957
|
+
this.hasModalOverlay = computed(() => !!this.selectedPreview() ||
|
|
74958
|
+
!!this.selectedInfo() ||
|
|
74959
|
+
this.showHistory() ||
|
|
74960
|
+
this.showPlace() ||
|
|
74961
|
+
this.showGallery() ||
|
|
74962
|
+
!!this.offeringsSeat());
|
|
74858
74963
|
this.previewCarouselItems = computed(() => this.currentPreviewCarouselItems());
|
|
74859
74964
|
this.canNavigatePreview = computed(() => this.previewCarouselItems().length > 1);
|
|
74860
74965
|
this.previewPositionLabel = computed(() => {
|
|
@@ -74880,25 +74985,28 @@ class ChristianityGameComponent {
|
|
|
74880
74985
|
canUse: this.canUsePreviewAbility(index),
|
|
74881
74986
|
}))
|
|
74882
74987
|
: text.abilityName || text.abilityText
|
|
74883
|
-
? [
|
|
74988
|
+
? [
|
|
74989
|
+
{
|
|
74884
74990
|
index: 0,
|
|
74885
74991
|
title: text.abilityName ?? this.t('christianityAbility'),
|
|
74886
74992
|
body: text.abilityText ?? '',
|
|
74887
74993
|
canUse: this.canUsePreviewAbility(0),
|
|
74888
|
-
}
|
|
74889
|
-
|
|
74994
|
+
},
|
|
74995
|
+
]
|
|
74996
|
+
: [
|
|
74997
|
+
{
|
|
74890
74998
|
index: 0,
|
|
74891
74999
|
title: this.t('christianityNoAbilityTitle'),
|
|
74892
75000
|
body: this.t('christianityNoAbilityBody'),
|
|
74893
75001
|
canUse: false,
|
|
74894
|
-
}
|
|
75002
|
+
},
|
|
75003
|
+
];
|
|
74895
75004
|
return abilities;
|
|
74896
75005
|
});
|
|
74897
75006
|
this.showPreviewAbilityTabs = computed(() => {
|
|
74898
75007
|
const abilities = this.previewAbilities();
|
|
74899
|
-
return abilities.length > 1
|
|
74900
|
-
|
|
74901
|
-
&& (abilities[0]?.title ?? '') !== this.t('christianityAbility');
|
|
75008
|
+
return (abilities.length > 1 ||
|
|
75009
|
+
(!this.isPreviewAbilityPlaceholder(abilities[0]) && (abilities[0]?.title ?? '') !== this.t('christianityAbility')));
|
|
74902
75010
|
});
|
|
74903
75011
|
this.showPreviewAbilities = computed(() => {
|
|
74904
75012
|
const preview = this.selectedPreview();
|
|
@@ -75071,7 +75179,9 @@ class ChristianityGameComponent {
|
|
|
75071
75179
|
return this.t('christianityWaitTurn');
|
|
75072
75180
|
}
|
|
75073
75181
|
if (attacker) {
|
|
75074
|
-
return this.hasOpponentGuards()
|
|
75182
|
+
return this.hasOpponentGuards()
|
|
75183
|
+
? this.t('christianityChooseCharacterTarget')
|
|
75184
|
+
: this.t('christianityChooseTarget');
|
|
75075
75185
|
}
|
|
75076
75186
|
if (handCard) {
|
|
75077
75187
|
if (!this.canPlay(handCard)) {
|
|
@@ -75080,12 +75190,18 @@ class ChristianityGameComponent {
|
|
|
75080
75190
|
if (handCard.type === 'place') {
|
|
75081
75191
|
return this.t('christianityChoosePlaceSlot');
|
|
75082
75192
|
}
|
|
75193
|
+
if (handCard.type === 'action' ||
|
|
75194
|
+
handCard.type === 'wisdom' ||
|
|
75195
|
+
handCard.type === 'event' ||
|
|
75196
|
+
handCard.type === 'tool') {
|
|
75197
|
+
return this.t('christianityPlayCard');
|
|
75198
|
+
}
|
|
75083
75199
|
return handCard.type === 'offering' ? this.t('christianityPlaceOffering') : this.t('christianityChooseSlot');
|
|
75084
75200
|
}
|
|
75085
75201
|
return this.t('christianityChooseCard');
|
|
75086
75202
|
});
|
|
75087
75203
|
this.i18n.registerDefaults('MiniGames', MINI_GAMES_I18N);
|
|
75088
|
-
effect(
|
|
75204
|
+
effect(onCleanup => {
|
|
75089
75205
|
if (!this.hasModalOverlay())
|
|
75090
75206
|
return;
|
|
75091
75207
|
const previousOverflow = this.document.body.style.overflow;
|
|
@@ -75141,7 +75257,7 @@ class ChristianityGameComponent {
|
|
|
75141
75257
|
try {
|
|
75142
75258
|
const response = await fetch(GENESIS_CATALOG_URL);
|
|
75143
75259
|
if (response.ok) {
|
|
75144
|
-
const catalog = await response.json();
|
|
75260
|
+
const catalog = (await response.json());
|
|
75145
75261
|
const cards = (catalog.cards ?? []).map(card => this.normalizeCatalogCard(card, catalog));
|
|
75146
75262
|
if (cards.length) {
|
|
75147
75263
|
this.cardCatalog.set(Object.fromEntries(cards.map(card => [card.id, card])));
|
|
@@ -75171,19 +75287,19 @@ class ChristianityGameComponent {
|
|
|
75171
75287
|
const editionIcon = card.editionIcon ?? catalog.edition?.icon ?? GENESIS_ICON_URL;
|
|
75172
75288
|
const verseText = card.verseText ?? card.bible?.text;
|
|
75173
75289
|
const scripture = card.scripture ?? this.formatScripture(card.bible);
|
|
75174
|
-
const offeringValue = card.type === 'offering' ? card.offeringValue ?? card.life ?? card.cost ?? 1 : card.offeringValue;
|
|
75290
|
+
const offeringValue = card.type === 'offering' ? (card.offeringValue ?? card.life ?? card.cost ?? 1) : card.offeringValue;
|
|
75175
75291
|
const life = card.type === 'leader'
|
|
75176
|
-
? card.leaderLife ?? card.life ?? 10
|
|
75292
|
+
? (card.leaderLife ?? card.life ?? 10)
|
|
75177
75293
|
: card.type === 'offering'
|
|
75178
75294
|
? offeringValue
|
|
75179
|
-
: card.life ?? 0;
|
|
75295
|
+
: (card.life ?? 0);
|
|
75180
75296
|
return {
|
|
75181
75297
|
...card,
|
|
75182
|
-
cost: card.type === 'offering' ? 0 : card.cost ?? 0,
|
|
75298
|
+
cost: card.type === 'offering' ? 0 : (card.cost ?? 0),
|
|
75183
75299
|
offeringValue,
|
|
75184
75300
|
life,
|
|
75185
|
-
leaderLife: card.type === 'leader' ? card.leaderLife ?? life : card.leaderLife,
|
|
75186
|
-
attack: card.type === 'character' ? card.attack ?? 0 : card.attack,
|
|
75301
|
+
leaderLife: card.type === 'leader' ? (card.leaderLife ?? life) : card.leaderLife,
|
|
75302
|
+
attack: card.type === 'character' ? (card.attack ?? 0) : card.attack,
|
|
75187
75303
|
abilityName: card.abilityName ?? card.abilities?.[0]?.name,
|
|
75188
75304
|
abilityText: card.abilityText ?? card.abilities?.[0]?.text,
|
|
75189
75305
|
verseText,
|
|
@@ -75205,21 +75321,27 @@ class ChristianityGameComponent {
|
|
|
75205
75321
|
createTutorialGame(cards, options = {}) {
|
|
75206
75322
|
const leaders = this.tutorialLeaderCards(cards);
|
|
75207
75323
|
const playerLeader = this.cardById(options.playerLeaderId) ?? this.findCard(leaders, 'Adán') ?? leaders[0];
|
|
75208
|
-
const opponentLeader = this.cardById(options.opponentLeaderId) ??
|
|
75209
|
-
|
|
75324
|
+
const opponentLeader = this.cardById(options.opponentLeaderId) ??
|
|
75325
|
+
this.findCard(leaders, 'Noé') ??
|
|
75326
|
+
leaders.find(card => card.id !== playerLeader?.id) ??
|
|
75327
|
+
leaders[0];
|
|
75328
|
+
const offerings = cards
|
|
75329
|
+
.filter(card => card.type === 'offering' && this.isClassicGalleryCard(card))
|
|
75330
|
+
.slice(0, TUTORIAL_OFFERING_LIMIT);
|
|
75210
75331
|
const places = cards.filter(card => card.type === 'place');
|
|
75211
75332
|
const characters = cards
|
|
75212
|
-
.filter(card => card.type === 'character' &&
|
|
75333
|
+
.filter(card => card.type === 'character' &&
|
|
75334
|
+
this.isClassicGalleryCard(card) &&
|
|
75335
|
+
(card.cost ?? 0) <= 4 &&
|
|
75336
|
+
(card.attack ?? 0) >= 0 &&
|
|
75337
|
+
(card.life ?? 0) > 0)
|
|
75213
75338
|
.slice(0, TUTORIAL_CHARACTER_LIMIT);
|
|
75214
|
-
const tutorialDeck = [
|
|
75215
|
-
...offerings,
|
|
75216
|
-
...characters,
|
|
75217
|
-
...offerings,
|
|
75218
|
-
...characters.slice(0, 6),
|
|
75219
|
-
].slice(0, 28);
|
|
75339
|
+
const tutorialDeck = [...offerings, ...characters, ...offerings, ...characters.slice(0, 6)].slice(0, 28);
|
|
75220
75340
|
const shuffledDeck = this.prepareTutorialOpeningDeck(this.shuffleCards(tutorialDeck, options.seed ?? TUTORIAL_SEED));
|
|
75221
75341
|
const playerHand = shuffledDeck.slice(0, TUTORIAL_OPENING_HAND_SIZE).map(card => card.id);
|
|
75222
|
-
const opponentHand = shuffledDeck
|
|
75342
|
+
const opponentHand = shuffledDeck
|
|
75343
|
+
.slice(TUTORIAL_OPENING_HAND_SIZE, TUTORIAL_OPENING_HAND_SIZE * 2)
|
|
75344
|
+
.map(card => card.id);
|
|
75223
75345
|
const sharedDeck = shuffledDeck.slice(TUTORIAL_OPENING_HAND_SIZE * 2).map(card => card.id);
|
|
75224
75346
|
return {
|
|
75225
75347
|
...structuredClone(STARTING_GAME),
|
|
@@ -75289,7 +75411,7 @@ class ChristianityGameComponent {
|
|
|
75289
75411
|
return cards.find(card => this.translatedCardText(card).name.toLowerCase().includes(namePart.toLowerCase()));
|
|
75290
75412
|
}
|
|
75291
75413
|
cardById(cardId) {
|
|
75292
|
-
return cardId ? this.cardCatalog()[cardId] ?? STARTER_CARDS[cardId] : undefined;
|
|
75414
|
+
return cardId ? (this.cardCatalog()[cardId] ?? STARTER_CARDS[cardId]) : undefined;
|
|
75293
75415
|
}
|
|
75294
75416
|
tutorialLeaderCards(cards) {
|
|
75295
75417
|
const leaders = cards
|
|
@@ -75391,7 +75513,7 @@ class ChristianityGameComponent {
|
|
|
75391
75513
|
type: card.type,
|
|
75392
75514
|
typeLabel: this.cardTypeLabel(card),
|
|
75393
75515
|
cost: card.cost,
|
|
75394
|
-
offeringValue: card.type === 'offering' ? card.offeringValue ?? card.life : undefined,
|
|
75516
|
+
offeringValue: card.type === 'offering' ? (card.offeringValue ?? card.life) : undefined,
|
|
75395
75517
|
attack: card.type === 'character' ? card.attack : undefined,
|
|
75396
75518
|
life: card.life,
|
|
75397
75519
|
currentHp: card.life,
|
|
@@ -75529,8 +75651,17 @@ class ChristianityGameComponent {
|
|
|
75529
75651
|
return this.cardTypeIconUrlForType('character');
|
|
75530
75652
|
}
|
|
75531
75653
|
cardTypeIconUrlForType(type) {
|
|
75532
|
-
const normalized = type
|
|
75533
|
-
|
|
75654
|
+
const normalized = type
|
|
75655
|
+
.toLowerCase()
|
|
75656
|
+
.normalize('NFD')
|
|
75657
|
+
.replace(/[\u0300-\u036f]/g, '');
|
|
75658
|
+
const icon = normalized === 'lider'
|
|
75659
|
+
? 'leader'
|
|
75660
|
+
: normalized === 'personaje'
|
|
75661
|
+
? 'character'
|
|
75662
|
+
: normalized === 'ofrenda'
|
|
75663
|
+
? 'offering'
|
|
75664
|
+
: normalized;
|
|
75534
75665
|
return `assets/games/christianity/icons/${icon}.png`;
|
|
75535
75666
|
}
|
|
75536
75667
|
offeringPips(value) {
|
|
@@ -75543,7 +75674,7 @@ class ChristianityGameComponent {
|
|
|
75543
75674
|
const cards = this.game().players[seat].battleZone;
|
|
75544
75675
|
const positionedCards = new Map();
|
|
75545
75676
|
cards.forEach((card, index) => {
|
|
75546
|
-
const slot = Number.isInteger(card.slot) ? card.slot ?? index : index;
|
|
75677
|
+
const slot = Number.isInteger(card.slot) ? (card.slot ?? index) : index;
|
|
75547
75678
|
if (slot >= 0 && slot < 4 && !positionedCards.has(slot)) {
|
|
75548
75679
|
positionedCards.set(slot, card);
|
|
75549
75680
|
}
|
|
@@ -75557,13 +75688,20 @@ class ChristianityGameComponent {
|
|
|
75557
75688
|
return `christianity-battle-slot-${index}`;
|
|
75558
75689
|
}
|
|
75559
75690
|
dropTargetIds() {
|
|
75560
|
-
return [
|
|
75691
|
+
return [
|
|
75692
|
+
'christianity-offerings-drop',
|
|
75693
|
+
'christianity-place-drop',
|
|
75694
|
+
...this.battleSlots('P1').map((_, index) => this.battleSlotDropId(index)),
|
|
75695
|
+
];
|
|
75561
75696
|
}
|
|
75562
75697
|
ownAttackerDropSourceIds() {
|
|
75563
75698
|
return ['christianity-player-battle-source'];
|
|
75564
75699
|
}
|
|
75565
75700
|
attackTargetDropIds() {
|
|
75566
|
-
return [
|
|
75701
|
+
return [
|
|
75702
|
+
'christianity-opponent-leader-drop',
|
|
75703
|
+
...this.opponent().battleZone.map(card => this.opponentTargetDropId(card)),
|
|
75704
|
+
];
|
|
75567
75705
|
}
|
|
75568
75706
|
opponentTargetDropId(card) {
|
|
75569
75707
|
return `christianity-opponent-target-${card.instanceId}`;
|
|
@@ -75699,7 +75837,11 @@ class ChristianityGameComponent {
|
|
|
75699
75837
|
return `christianity-use-offering-${offering.owner}-${this.testIdPart(offering.instanceId)}`;
|
|
75700
75838
|
}
|
|
75701
75839
|
testIdPart(value) {
|
|
75702
|
-
return value
|
|
75840
|
+
return (value
|
|
75841
|
+
.toLowerCase()
|
|
75842
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
75843
|
+
.replace(/^-|-$/g, '')
|
|
75844
|
+
.slice(0, 48) || 'item');
|
|
75703
75845
|
}
|
|
75704
75846
|
canPlaySelected() {
|
|
75705
75847
|
const selected = this.selectedHandCard();
|
|
@@ -75815,10 +75957,10 @@ class ChristianityGameComponent {
|
|
|
75815
75957
|
this.attackLeader();
|
|
75816
75958
|
}
|
|
75817
75959
|
isValidAttackerInstance(instanceId) {
|
|
75818
|
-
return this.game().status === 'in_progress'
|
|
75819
|
-
|
|
75820
|
-
|
|
75821
|
-
|
|
75960
|
+
return (this.game().status === 'in_progress' &&
|
|
75961
|
+
this.isOwnTurn() &&
|
|
75962
|
+
!this.combatAnimation() &&
|
|
75963
|
+
this.player().battleZone.some(card => card.instanceId === instanceId && card.canAttack));
|
|
75822
75964
|
}
|
|
75823
75965
|
selectHandCard(cardId) {
|
|
75824
75966
|
const wasSelected = this.selectedHandCard() === cardId;
|
|
@@ -75831,9 +75973,7 @@ class ChristianityGameComponent {
|
|
|
75831
75973
|
if (!cardId)
|
|
75832
75974
|
return;
|
|
75833
75975
|
const card = this.cardDefinition(cardId);
|
|
75834
|
-
const resolvedSlotIndex = card.type === 'character' && slotIndex === undefined
|
|
75835
|
-
? this.firstAvailableBattleSlotIndex()
|
|
75836
|
-
: slotIndex;
|
|
75976
|
+
const resolvedSlotIndex = card.type === 'character' && slotIndex === undefined ? this.firstAvailableBattleSlotIndex() : slotIndex;
|
|
75837
75977
|
this.playCardFromHand(cardId, resolvedSlotIndex);
|
|
75838
75978
|
}
|
|
75839
75979
|
firstAvailableBattleSlotIndex() {
|
|
@@ -75914,7 +76054,12 @@ class ChristianityGameComponent {
|
|
|
75914
76054
|
});
|
|
75915
76055
|
return;
|
|
75916
76056
|
}
|
|
75917
|
-
this.startCombatAnimation({
|
|
76057
|
+
this.startCombatAnimation({
|
|
76058
|
+
attackerInstanceId: attacker.instanceId,
|
|
76059
|
+
attackerSeat: 'P1',
|
|
76060
|
+
targetSeat: 'P2',
|
|
76061
|
+
target: 'leader',
|
|
76062
|
+
});
|
|
75918
76063
|
this.selectedAttacker.set(null);
|
|
75919
76064
|
this.combatResolutionTimer = window.setTimeout(() => {
|
|
75920
76065
|
let damage = 0;
|
|
@@ -76009,7 +76154,7 @@ class ChristianityGameComponent {
|
|
|
76009
76154
|
this.resetTransientTableState();
|
|
76010
76155
|
const setup = this.createTutorialSetup();
|
|
76011
76156
|
this.tutorialSetup.set(setup);
|
|
76012
|
-
this.selectedTutorialLeaderId.set(setup.leaderPicker === 'P1' ? setup.availableLeaders[0] ?? null : null);
|
|
76157
|
+
this.selectedTutorialLeaderId.set(setup.leaderPicker === 'P1' ? (setup.availableLeaders[0] ?? null) : null);
|
|
76013
76158
|
this.leaderChoiceSeconds.set(TUTORIAL_LEADER_CHOICE_SECONDS);
|
|
76014
76159
|
this.tutorialPhase.set('coin');
|
|
76015
76160
|
this.screen.set('table');
|
|
@@ -76071,7 +76216,7 @@ class ChristianityGameComponent {
|
|
|
76071
76216
|
return;
|
|
76072
76217
|
this.selectTutorialLeader(leaderId);
|
|
76073
76218
|
this.inspectHandCard(leaderId);
|
|
76074
|
-
this.selectedPreview.update(preview => preview ? { ...preview, source: 'leader-choice' } : preview);
|
|
76219
|
+
this.selectedPreview.update(preview => (preview ? { ...preview, source: 'leader-choice' } : preview));
|
|
76075
76220
|
}
|
|
76076
76221
|
toggleOptions() {
|
|
76077
76222
|
this.showOptions.update(value => !value);
|
|
@@ -76428,7 +76573,7 @@ class ChristianityGameComponent {
|
|
|
76428
76573
|
}
|
|
76429
76574
|
}
|
|
76430
76575
|
combatAnimationAttacker(animation) {
|
|
76431
|
-
return this.game().players[animation.attackerSeat].battleZone.find(card => card.instanceId === animation.attackerInstanceId) ?? null;
|
|
76576
|
+
return (this.game().players[animation.attackerSeat].battleZone.find(card => card.instanceId === animation.attackerInstanceId) ?? null);
|
|
76432
76577
|
}
|
|
76433
76578
|
combatAnimationTargetLabel(animation) {
|
|
76434
76579
|
if (animation.target === 'leader') {
|
|
@@ -76467,7 +76612,7 @@ class ChristianityGameComponent {
|
|
|
76467
76612
|
const dx = to.x - from.x;
|
|
76468
76613
|
const dy = to.y - from.y;
|
|
76469
76614
|
const length = Math.max(12, Math.hypot(dx, dy));
|
|
76470
|
-
const angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
|
76615
|
+
const angle = (Math.atan2(dy, dx) * 180) / Math.PI;
|
|
76471
76616
|
return {
|
|
76472
76617
|
fromX: `${from.x}%`,
|
|
76473
76618
|
fromY: `${from.y}%`,
|
|
@@ -76557,7 +76702,9 @@ class ChristianityGameComponent {
|
|
|
76557
76702
|
const offeringId = hand.find(cardId => this.cardDefinition(cardId).type === 'offering' && canPlayCard(game, 'P2', this.cardDefinition(cardId)));
|
|
76558
76703
|
if (offeringId) {
|
|
76559
76704
|
const card = this.cardDefinition(offeringId);
|
|
76560
|
-
const result = playCardFromHand(game, 'P2', card, {
|
|
76705
|
+
const result = playCardFromHand(game, 'P2', card, {
|
|
76706
|
+
displayName: this.translatedCardText(card).name,
|
|
76707
|
+
});
|
|
76561
76708
|
if (result.played) {
|
|
76562
76709
|
Object.assign(game, result.game);
|
|
76563
76710
|
log.push(...result.log);
|
|
@@ -76628,7 +76775,9 @@ class ChristianityGameComponent {
|
|
|
76628
76775
|
title: leader ? this.translatedCardText(leader).name : player.leaderName,
|
|
76629
76776
|
eyebrow: this.t('christianityLeaderCard'),
|
|
76630
76777
|
meta: `${player.leaderHp}/${player.leaderMaxHp}`,
|
|
76631
|
-
body: seat === 'P2' && this.hasOpponentGuards()
|
|
76778
|
+
body: seat === 'P2' && this.hasOpponentGuards()
|
|
76779
|
+
? this.t('christianityLeaderProtected')
|
|
76780
|
+
: this.t('christianityLeaderBody'),
|
|
76632
76781
|
cardId: player.leaderCardId,
|
|
76633
76782
|
source: 'board',
|
|
76634
76783
|
});
|
|
@@ -76703,7 +76852,7 @@ class ChristianityGameComponent {
|
|
|
76703
76852
|
const preview = this.selectedPreview();
|
|
76704
76853
|
if (!preview?.seat || !preview.offeringInstanceId)
|
|
76705
76854
|
return null;
|
|
76706
|
-
return this.game().players[preview.seat].offerings.find(card => card.instanceId === preview.offeringInstanceId) ?? null;
|
|
76855
|
+
return (this.game().players[preview.seat].offerings.find(card => card.instanceId === preview.offeringInstanceId) ?? null);
|
|
76707
76856
|
}
|
|
76708
76857
|
canUsePreviewAbility(index) {
|
|
76709
76858
|
const offering = this.selectedPreviewOffering();
|
|
@@ -76724,7 +76873,9 @@ class ChristianityGameComponent {
|
|
|
76724
76873
|
this.t('christianityDeckRuleShared'),
|
|
76725
76874
|
this.t('christianityDeckRuleDraw'),
|
|
76726
76875
|
this.t('christianityDeckRuleEmpty'),
|
|
76727
|
-
nextCard
|
|
76876
|
+
nextCard
|
|
76877
|
+
? `${this.t('christianityDeckNextCard')}: ${this.cardDisplayName(nextCard)}`
|
|
76878
|
+
: this.t('christianityDeckNoNextCard'),
|
|
76728
76879
|
],
|
|
76729
76880
|
});
|
|
76730
76881
|
}
|
|
@@ -76739,15 +76890,12 @@ class ChristianityGameComponent {
|
|
|
76739
76890
|
eyebrow: this.t('christianitySharedZone'),
|
|
76740
76891
|
meta: this.t('christianityEmpty'),
|
|
76741
76892
|
body: this.t('christianityPlaceRuleBody'),
|
|
76742
|
-
facts: [
|
|
76743
|
-
this.t('christianityPlaceSlotPlayable'),
|
|
76744
|
-
this.t('christianityPlaceOnlyOne'),
|
|
76745
|
-
],
|
|
76893
|
+
facts: [this.t('christianityPlaceSlotPlayable'), this.t('christianityPlaceOnlyOne')],
|
|
76746
76894
|
});
|
|
76747
76895
|
}
|
|
76748
76896
|
inspectPlaceCard(cardId) {
|
|
76749
76897
|
this.inspectHandCard(cardId);
|
|
76750
|
-
this.selectedPreview.update(preview => preview ? { ...preview, source: 'place' } : preview);
|
|
76898
|
+
this.selectedPreview.update(preview => (preview ? { ...preview, source: 'place' } : preview));
|
|
76751
76899
|
}
|
|
76752
76900
|
inspectHowToPlay() {
|
|
76753
76901
|
this.selectedPreview.set(null);
|
|
@@ -76784,11 +76932,11 @@ class ChristianityGameComponent {
|
|
|
76784
76932
|
}
|
|
76785
76933
|
inspectGalleryCard(cardId) {
|
|
76786
76934
|
this.inspectHandCard(cardId);
|
|
76787
|
-
this.selectedPreview.update(preview => preview ? { ...preview, source: 'gallery' } : preview);
|
|
76935
|
+
this.selectedPreview.update(preview => (preview ? { ...preview, source: 'gallery' } : preview));
|
|
76788
76936
|
}
|
|
76789
76937
|
inspectHistoryCard(cardId) {
|
|
76790
76938
|
this.inspectHandCard(cardId);
|
|
76791
|
-
this.selectedPreview.update(preview => preview ? { ...preview, source: 'history' } : preview);
|
|
76939
|
+
this.selectedPreview.update(preview => (preview ? { ...preview, source: 'history' } : preview));
|
|
76792
76940
|
}
|
|
76793
76941
|
inspectCharacter(card) {
|
|
76794
76942
|
this.selectedInfo.set(null);
|
|
@@ -76892,418 +77040,276 @@ class ChristianityGameComponent {
|
|
|
76892
77040
|
</section>
|
|
76893
77041
|
</section>
|
|
76894
77042
|
} @else {
|
|
76895
|
-
|
|
76896
|
-
|
|
76897
|
-
|
|
76898
|
-
|
|
76899
|
-
|
|
76900
|
-
|
|
76901
|
-
|
|
76902
|
-
|
|
76903
|
-
|
|
76904
|
-
|
|
76905
|
-
|
|
76906
|
-
|
|
76907
|
-
|
|
76908
|
-
|
|
76909
|
-
<div>
|
|
76910
|
-
<
|
|
76911
|
-
<
|
|
77043
|
+
<section
|
|
77044
|
+
class="christianity-match-strip"
|
|
77045
|
+
data-testid="christianity-match-strip"
|
|
77046
|
+
[attr.aria-label]="t('christianityMatchScore')"
|
|
77047
|
+
>
|
|
77048
|
+
<article class="christianity-match-player">
|
|
77049
|
+
<span class="christianity-avatar" [style.background]="player().avatarColor">{{ player().avatar }}</span>
|
|
77050
|
+
<div>
|
|
77051
|
+
<strong>{{ player().displayName }}</strong>
|
|
77052
|
+
<small
|
|
77053
|
+
>{{ playerLeaderDisplayName(player()) }} · {{ player().leaderHp }}/{{ player().leaderMaxHp }}</small
|
|
77054
|
+
>
|
|
77055
|
+
</div>
|
|
77056
|
+
</article>
|
|
77057
|
+
<div class="christianity-scoreboard">
|
|
77058
|
+
<span>{{ t('christianityMatch') }}</span>
|
|
77059
|
+
<strong>{{ game().matchScore.P1 }}-{{ game().matchScore.P2 }}</strong>
|
|
76912
77060
|
</div>
|
|
76913
|
-
|
|
76914
|
-
|
|
77061
|
+
<article class="christianity-match-player christianity-match-player--opponent">
|
|
77062
|
+
<span class="christianity-avatar" [style.background]="opponent().avatarColor">{{ opponent().avatar }}</span>
|
|
77063
|
+
<div>
|
|
77064
|
+
<strong>{{ opponent().displayName }}</strong>
|
|
77065
|
+
<small
|
|
77066
|
+
>{{ playerLeaderDisplayName(opponent()) }} · {{ opponent().leaderHp }}/{{
|
|
77067
|
+
opponent().leaderMaxHp
|
|
77068
|
+
}}</small
|
|
77069
|
+
>
|
|
77070
|
+
</div>
|
|
77071
|
+
</article>
|
|
77072
|
+
</section>
|
|
76915
77073
|
|
|
76916
|
-
|
|
76917
|
-
|
|
76918
|
-
|
|
76919
|
-
|
|
76920
|
-
|
|
76921
|
-
|
|
76922
|
-
|
|
76923
|
-
|
|
76924
|
-
|
|
76925
|
-
|
|
76926
|
-
|
|
76927
|
-
|
|
76928
|
-
</div>
|
|
76929
|
-
<div class="christianity-turn-actions">
|
|
76930
|
-
<button
|
|
76931
|
-
type="button"
|
|
76932
|
-
class="christianity-end-turn"
|
|
76933
|
-
data-testid="christianity-end-turn"
|
|
76934
|
-
[disabled]="!isOwnTurn() || tutorialPhase() !== 'in_progress' || !!combatAnimation()"
|
|
76935
|
-
(click)="endTurn()"
|
|
76936
|
-
>
|
|
76937
|
-
{{ t('christianityEndTurn') }}
|
|
76938
|
-
</button>
|
|
76939
|
-
<button type="button" class="christianity-options-button" data-testid="christianity-options-button" valLightRipple (click)="toggleOptions()">
|
|
76940
|
-
{{ t('christianityOptions') }}
|
|
76941
|
-
</button>
|
|
76942
|
-
</div>
|
|
76943
|
-
@if (showOptions()) {
|
|
76944
|
-
<div class="christianity-options-menu" data-testid="christianity-options-menu">
|
|
76945
|
-
<button type="button" (click)="restartTutorial()">{{ t('christianityRestart') }}</button>
|
|
76946
|
-
<button type="button" [disabled]="game().status === 'finished'" (click)="resignTutorial()">{{ t('christianityResign') }}</button>
|
|
76947
|
-
<button type="button" (click)="returnToChristianityHome()">{{ t('christianityBackToMenu') }}</button>
|
|
77074
|
+
<section
|
|
77075
|
+
class="christianity-turn-banner"
|
|
77076
|
+
data-testid="christianity-turn-banner"
|
|
77077
|
+
[class.is-own-turn]="isOwnTurn()"
|
|
77078
|
+
[class.is-rival-turn]="!isOwnTurn() && game().status === 'in_progress'"
|
|
77079
|
+
[class.is-finished]="game().status === 'finished'"
|
|
77080
|
+
aria-live="polite"
|
|
77081
|
+
>
|
|
77082
|
+
<div>
|
|
77083
|
+
<span>{{ t('christianityTurn') }} {{ game().turnCount }}</span>
|
|
77084
|
+
<strong>{{ turnBannerTitle() }}</strong>
|
|
77085
|
+
<p>{{ turnBannerBody() }}</p>
|
|
76948
77086
|
</div>
|
|
76949
|
-
|
|
76950
|
-
|
|
76951
|
-
|
|
76952
|
-
|
|
76953
|
-
|
|
76954
|
-
|
|
76955
|
-
|
|
76956
|
-
|
|
76957
|
-
|
|
76958
|
-
|
|
77087
|
+
<div class="christianity-turn-actions">
|
|
77088
|
+
<button
|
|
77089
|
+
type="button"
|
|
77090
|
+
class="christianity-end-turn"
|
|
77091
|
+
data-testid="christianity-end-turn"
|
|
77092
|
+
[disabled]="!isOwnTurn() || tutorialPhase() !== 'in_progress' || !!combatAnimation()"
|
|
77093
|
+
(click)="endTurn()"
|
|
77094
|
+
>
|
|
77095
|
+
{{ t('christianityEndTurn') }}
|
|
77096
|
+
</button>
|
|
76959
77097
|
<button
|
|
76960
77098
|
type="button"
|
|
76961
|
-
class="christianity-
|
|
77099
|
+
class="christianity-options-button"
|
|
77100
|
+
data-testid="christianity-options-button"
|
|
76962
77101
|
valLightRipple
|
|
76963
|
-
|
|
76964
|
-
[attr.aria-label]="t('christianityHiddenCard')"
|
|
77102
|
+
(click)="toggleOptions()"
|
|
76965
77103
|
>
|
|
76966
|
-
|
|
77104
|
+
{{ t('christianityOptions') }}
|
|
76967
77105
|
</button>
|
|
77106
|
+
</div>
|
|
77107
|
+
@if (showOptions()) {
|
|
77108
|
+
<div class="christianity-options-menu" data-testid="christianity-options-menu">
|
|
77109
|
+
<button type="button" (click)="restartTutorial()">{{ t('christianityRestart') }}</button>
|
|
77110
|
+
<button type="button" [disabled]="game().status === 'finished'" (click)="resignTutorial()">
|
|
77111
|
+
{{ t('christianityResign') }}
|
|
77112
|
+
</button>
|
|
77113
|
+
<button type="button" (click)="returnToChristianityHome()">{{ t('christianityBackToMenu') }}</button>
|
|
77114
|
+
</div>
|
|
76968
77115
|
}
|
|
76969
77116
|
</section>
|
|
76970
|
-
</section>
|
|
76971
77117
|
|
|
76972
|
-
|
|
76973
|
-
|
|
77118
|
+
<section class="christianity-hand-shelf christianity-hand-shelf--opponent">
|
|
77119
|
+
<div class="christianity-hand-meter christianity-hand-meter--opponent">
|
|
77120
|
+
<span>{{ t('christianityHand') }}</span>
|
|
77121
|
+
<strong>{{ opponentHandCount() }}</strong>
|
|
77122
|
+
</div>
|
|
76974
77123
|
<section
|
|
76975
|
-
class="christianity-
|
|
76976
|
-
|
|
76977
|
-
[
|
|
76978
|
-
data-testid="christianity-setup-panel"
|
|
76979
|
-
aria-live="polite"
|
|
77124
|
+
class="christianity-hand-fan christianity-hand-fan--opponent"
|
|
77125
|
+
data-testid="christianity-opponent-hand"
|
|
77126
|
+
[attr.aria-label]="t('christianityOpponentHand')"
|
|
76980
77127
|
>
|
|
76981
|
-
@
|
|
76982
|
-
<div
|
|
76983
|
-
class="christianity-setup-coin"
|
|
76984
|
-
[class.is-rival-won]="tutorialSetup()?.coinWinner === 'P2'"
|
|
76985
|
-
aria-hidden="true"
|
|
76986
|
-
>
|
|
76987
|
-
<span></span>
|
|
76988
|
-
<span></span>
|
|
76989
|
-
</div>
|
|
76990
|
-
}
|
|
76991
|
-
<div>
|
|
76992
|
-
<span>{{ t('christianityMatchSetup') }}</span>
|
|
76993
|
-
<h2>{{ setupTitle() }}</h2>
|
|
76994
|
-
<p>{{ setupBody() }}</p>
|
|
76995
|
-
</div>
|
|
76996
|
-
@if (tutorialPhase() === 'coin') {
|
|
76997
|
-
<button type="button" class="christianity-primary-action" data-testid="christianity-continue-setup" valLightRipple (click)="continueAfterCoin()">
|
|
76998
|
-
{{ t('christianityContinue') }}
|
|
76999
|
-
</button>
|
|
77000
|
-
}
|
|
77001
|
-
@if (tutorialPhase() === 'leader_pick') {
|
|
77002
|
-
@if (tutorialSetup()?.leaderPicker === 'P1' && (tutorialSetup()?.availableLeaders?.length ?? 0) > 1) {
|
|
77003
|
-
<div class="christianity-leader-choice-meter" aria-live="polite">
|
|
77004
|
-
<span>{{ t('christianityLeaderChoiceTimer').replace('{seconds}', leaderChoiceSeconds().toString()) }}</span>
|
|
77005
|
-
<i [style.transform]="'scaleX(' + (leaderChoiceSeconds() / leaderChoiceTotalSeconds) + ')'"></i>
|
|
77006
|
-
</div>
|
|
77007
|
-
<div class="christianity-leader-choice-grid" data-testid="christianity-leader-choice-grid">
|
|
77008
|
-
@for (leaderId of tutorialSetup()?.availableLeaders ?? []; track leaderId) {
|
|
77009
|
-
@let leader = cardDefinition(leaderId);
|
|
77010
|
-
<article class="christianity-leader-choice-option" [class.is-selected]="selectedTutorialLeaderId() === leaderId">
|
|
77011
|
-
<button
|
|
77012
|
-
type="button"
|
|
77013
|
-
class="christianity-leader-choice-card christianity-render-card-button"
|
|
77014
|
-
valLightRipple
|
|
77015
|
-
[attr.aria-pressed]="selectedTutorialLeaderId() === leaderId"
|
|
77016
|
-
(click)="selectTutorialLeader(leaderId)"
|
|
77017
|
-
>
|
|
77018
|
-
<val-christianity-card [card]="definitionToRenderCard(leader)" variant="baby"></val-christianity-card>
|
|
77019
|
-
</button>
|
|
77020
|
-
<div>
|
|
77021
|
-
<span>{{ selectedTutorialLeaderId() === leaderId ? t('christianityLeaderSelected') : t('christianitySelectLeader') }}</span>
|
|
77022
|
-
<button type="button" class="christianity-leader-choice-detail" valLightRipple (click)="inspectLeaderChoice(leaderId)">
|
|
77023
|
-
{{ t('christianityViewDetails') }}
|
|
77024
|
-
</button>
|
|
77025
|
-
</div>
|
|
77026
|
-
</article>
|
|
77027
|
-
}
|
|
77028
|
-
</div>
|
|
77029
|
-
<button type="button" class="christianity-primary-action" data-testid="christianity-confirm-leader" valLightRipple (click)="confirmTutorialLeader()">
|
|
77030
|
-
{{ t('christianityChooseThisLeader') }}
|
|
77031
|
-
</button>
|
|
77032
|
-
} @else {
|
|
77033
|
-
<button type="button" class="christianity-primary-action" data-testid="christianity-continue-setup" valLightRipple (click)="continueAfterCoin()">
|
|
77034
|
-
{{ t('christianityContinue') }}
|
|
77035
|
-
</button>
|
|
77036
|
-
}
|
|
77037
|
-
}
|
|
77038
|
-
</section>
|
|
77039
|
-
}
|
|
77040
|
-
@if (game().status === 'finished') {
|
|
77041
|
-
<section class="christianity-result-panel" data-testid="christianity-result-panel" aria-live="polite">
|
|
77042
|
-
<span>{{ t('christianityGameOver') }}</span>
|
|
77043
|
-
<h2>{{ resultTitle() }}</h2>
|
|
77044
|
-
<p>{{ resultBody() }}</p>
|
|
77045
|
-
<div>
|
|
77046
|
-
<button type="button" class="christianity-primary-action" data-testid="christianity-play-again" valLightRipple (click)="restartTutorial()">
|
|
77047
|
-
{{ t('christianityPlayAgain') }}
|
|
77048
|
-
</button>
|
|
77049
|
-
<button type="button" class="christianity-secondary-action" valLightRipple (click)="returnToChristianityHome()">
|
|
77050
|
-
{{ t('christianityBackToMenu') }}
|
|
77051
|
-
</button>
|
|
77052
|
-
</div>
|
|
77053
|
-
</section>
|
|
77054
|
-
}
|
|
77055
|
-
<div class="christianity-impact-layer">
|
|
77056
|
-
@if (combatTrail(); as trail) {
|
|
77057
|
-
<span
|
|
77058
|
-
class="christianity-combat-trail"
|
|
77059
|
-
aria-hidden="true"
|
|
77060
|
-
[class.is-leader-target]="trail.tone === 'leader'"
|
|
77061
|
-
[class.is-character-target]="trail.tone === 'character'"
|
|
77062
|
-
[style.--christianity-combat-trail-x]="trail.fromX"
|
|
77063
|
-
[style.--christianity-combat-trail-y]="trail.fromY"
|
|
77064
|
-
[style.--christianity-combat-trail-mid-x]="trail.midX"
|
|
77065
|
-
[style.--christianity-combat-trail-mid-y]="trail.midY"
|
|
77066
|
-
[style.--christianity-combat-trail-length]="trail.length"
|
|
77067
|
-
[style.--christianity-combat-trail-angle]="trail.angle"
|
|
77068
|
-
>
|
|
77069
|
-
<span></span>
|
|
77070
|
-
</span>
|
|
77071
|
-
}
|
|
77072
|
-
@for (impact of impactEvents(); track impact.id) {
|
|
77073
|
-
<val-mini-game-score-pop [props]="impactPopProps(impact)" />
|
|
77074
|
-
}
|
|
77075
|
-
@if (combatCallout(); as callout) {
|
|
77076
|
-
<val-mini-game-callout [props]="callout" />
|
|
77077
|
-
}
|
|
77078
|
-
</div>
|
|
77079
|
-
<section class="christianity-player-side christianity-player-side--opponent">
|
|
77080
|
-
<section class="christianity-player-rack christianity-player-rack--opponent">
|
|
77081
|
-
<div class="christianity-offerings-zone">
|
|
77082
|
-
<button type="button" class="christianity-offering-pile" data-testid="christianity-offerings-P2" [class.is-empty-zone]="!topOffering('P2')" valLightRipple (click)="openOfferings('P2')">
|
|
77083
|
-
@if (offeringStack('P2').length) {
|
|
77084
|
-
<span class="christianity-zone-card-stack" aria-hidden="true">
|
|
77085
|
-
@for (offering of offeringStack('P2'); track offering.instanceId) {
|
|
77086
|
-
<val-christianity-card
|
|
77087
|
-
[card]="offering.ready ? offeringRenderCard(offering) : hiddenCardRenderCard()"
|
|
77088
|
-
[variant]="offering.ready ? 'baby' : 'back'"
|
|
77089
|
-
[style.transform]="zoneStackTransform($index, offeringStack('P2').length)"
|
|
77090
|
-
></val-christianity-card>
|
|
77091
|
-
}
|
|
77092
|
-
</span>
|
|
77093
|
-
} @else {
|
|
77094
|
-
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
77095
|
-
}
|
|
77096
|
-
<span>{{ t('christianityOfferingReserve') }}</span>
|
|
77097
|
-
<strong>{{ readyOfferings(opponent()) }}</strong>
|
|
77098
|
-
<small>{{ t('christianityOfferingBase') }} {{ totalOfferings(opponent()) }}</small>
|
|
77099
|
-
</button>
|
|
77100
|
-
</div>
|
|
77101
|
-
<div
|
|
77102
|
-
class="christianity-attack-drop-target"
|
|
77103
|
-
cdkDropList
|
|
77104
|
-
id="christianity-opponent-leader-drop"
|
|
77105
|
-
[cdkDropListConnectedTo]="ownAttackerDropSourceIds()"
|
|
77106
|
-
[cdkDropListEnterPredicate]="canDropOnOpponentLeader"
|
|
77107
|
-
[cdkDropListSortingDisabled]="true"
|
|
77108
|
-
(cdkDropListDropped)="dropOnOpponentLeader($event)"
|
|
77109
|
-
>
|
|
77128
|
+
@for (_ of hiddenHandCards(opponentHandCount()); track $index) {
|
|
77110
77129
|
<button
|
|
77111
77130
|
type="button"
|
|
77112
|
-
class="christianity-
|
|
77113
|
-
data-testid="christianity-leader-P2"
|
|
77131
|
+
class="christianity-hidden-card-button christianity-render-card-button"
|
|
77114
77132
|
valLightRipple
|
|
77115
|
-
[
|
|
77116
|
-
[
|
|
77117
|
-
[class.is-combat-target]="isCombatLeaderTarget('P2')"
|
|
77118
|
-
(click)="handleOpponentLeader()"
|
|
77133
|
+
[style.transform]="fanTransform($index, opponentHandCount(), true)"
|
|
77134
|
+
[attr.aria-label]="t('christianityHiddenCard')"
|
|
77119
77135
|
>
|
|
77120
|
-
|
|
77136
|
+
<val-christianity-card [card]="hiddenCardRenderCard()" variant="back"></val-christianity-card>
|
|
77121
77137
|
</button>
|
|
77122
|
-
|
|
77123
|
-
<span class="christianity-rack-spacer" aria-hidden="true"></span>
|
|
77138
|
+
}
|
|
77124
77139
|
</section>
|
|
77140
|
+
</section>
|
|
77125
77141
|
|
|
77126
|
-
|
|
77127
|
-
|
|
77128
|
-
|
|
77142
|
+
<section class="christianity-table" data-testid="christianity-table" [attr.aria-label]="t('christianityTable')">
|
|
77143
|
+
@if (tutorialPhase() !== 'in_progress' && tutorialPhase() !== 'finished') {
|
|
77144
|
+
<section
|
|
77145
|
+
class="christianity-setup-panel"
|
|
77146
|
+
[class.christianity-setup-panel--coin]="tutorialPhase() === 'coin'"
|
|
77147
|
+
[class.christianity-setup-panel--leader-pick]="tutorialPhase() === 'leader_pick'"
|
|
77148
|
+
data-testid="christianity-setup-panel"
|
|
77149
|
+
aria-live="polite"
|
|
77150
|
+
>
|
|
77151
|
+
@if (tutorialPhase() === 'coin') {
|
|
77152
|
+
<div
|
|
77153
|
+
class="christianity-setup-coin"
|
|
77154
|
+
[class.is-rival-won]="tutorialSetup()?.coinWinner === 'P2'"
|
|
77155
|
+
aria-hidden="true"
|
|
77156
|
+
>
|
|
77157
|
+
<span></span>
|
|
77158
|
+
<span></span>
|
|
77159
|
+
</div>
|
|
77160
|
+
}
|
|
77161
|
+
<div>
|
|
77162
|
+
<span>{{ t('christianityMatchSetup') }}</span>
|
|
77163
|
+
<h2>{{ setupTitle() }}</h2>
|
|
77164
|
+
<p>{{ setupBody() }}</p>
|
|
77165
|
+
</div>
|
|
77166
|
+
@if (tutorialPhase() === 'coin') {
|
|
77129
77167
|
<button
|
|
77130
77168
|
type="button"
|
|
77131
|
-
class="christianity-
|
|
77132
|
-
|
|
77133
|
-
cdkDropList
|
|
77134
|
-
[id]="opponentTargetDropId(slot.card)"
|
|
77135
|
-
[cdkDropListConnectedTo]="ownAttackerDropSourceIds()"
|
|
77136
|
-
[cdkDropListEnterPredicate]="canDropOnOpponentCharacter"
|
|
77137
|
-
[cdkDropListSortingDisabled]="true"
|
|
77169
|
+
class="christianity-primary-action"
|
|
77170
|
+
data-testid="christianity-continue-setup"
|
|
77138
77171
|
valLightRipple
|
|
77139
|
-
|
|
77140
|
-
[class.is-combat-target]="isCombatCharacterTarget(slot.card)"
|
|
77141
|
-
(cdkDropListDropped)="dropOnOpponentCharacter($event, slot.card)"
|
|
77142
|
-
(click)="handleOpponentCharacter(slot.card)"
|
|
77172
|
+
(click)="continueAfterCoin()"
|
|
77143
77173
|
>
|
|
77144
|
-
|
|
77174
|
+
{{ t('christianityContinue') }}
|
|
77145
77175
|
</button>
|
|
77146
|
-
} @else {
|
|
77147
|
-
<span class="christianity-slot"></span>
|
|
77148
77176
|
}
|
|
77149
|
-
|
|
77150
|
-
|
|
77151
|
-
|
|
77152
|
-
|
|
77153
|
-
|
|
77154
|
-
|
|
77155
|
-
|
|
77156
|
-
|
|
77157
|
-
|
|
77158
|
-
|
|
77159
|
-
|
|
77160
|
-
|
|
77161
|
-
|
|
77162
|
-
|
|
77177
|
+
@if (tutorialPhase() === 'leader_pick') {
|
|
77178
|
+
@if (tutorialSetup()?.leaderPicker === 'P1' && (tutorialSetup()?.availableLeaders?.length ?? 0) > 1) {
|
|
77179
|
+
<div class="christianity-leader-choice-meter" aria-live="polite">
|
|
77180
|
+
<span>{{
|
|
77181
|
+
t('christianityLeaderChoiceTimer').replace('{seconds}', leaderChoiceSeconds().toString())
|
|
77182
|
+
}}</span>
|
|
77183
|
+
<i [style.transform]="'scaleX(' + leaderChoiceSeconds() / leaderChoiceTotalSeconds + ')'"></i>
|
|
77184
|
+
</div>
|
|
77185
|
+
<div class="christianity-leader-choice-grid" data-testid="christianity-leader-choice-grid">
|
|
77186
|
+
@for (leaderId of tutorialSetup()?.availableLeaders ?? []; track leaderId) {
|
|
77187
|
+
@let leader = cardDefinition(leaderId);
|
|
77188
|
+
<article
|
|
77189
|
+
class="christianity-leader-choice-option"
|
|
77190
|
+
[class.is-selected]="selectedTutorialLeaderId() === leaderId"
|
|
77191
|
+
>
|
|
77192
|
+
<button
|
|
77193
|
+
type="button"
|
|
77194
|
+
class="christianity-leader-choice-card christianity-render-card-button"
|
|
77195
|
+
valLightRipple
|
|
77196
|
+
[attr.aria-pressed]="selectedTutorialLeaderId() === leaderId"
|
|
77197
|
+
(click)="selectTutorialLeader(leaderId)"
|
|
77198
|
+
>
|
|
77199
|
+
<val-christianity-card
|
|
77200
|
+
[card]="definitionToRenderCard(leader)"
|
|
77201
|
+
variant="baby"
|
|
77202
|
+
></val-christianity-card>
|
|
77203
|
+
</button>
|
|
77204
|
+
<div>
|
|
77205
|
+
<span>{{
|
|
77206
|
+
selectedTutorialLeaderId() === leaderId
|
|
77207
|
+
? t('christianityLeaderSelected')
|
|
77208
|
+
: t('christianitySelectLeader')
|
|
77209
|
+
}}</span>
|
|
77210
|
+
<button
|
|
77211
|
+
type="button"
|
|
77212
|
+
class="christianity-leader-choice-detail"
|
|
77213
|
+
valLightRipple
|
|
77214
|
+
(click)="inspectLeaderChoice(leaderId)"
|
|
77215
|
+
>
|
|
77216
|
+
{{ t('christianityViewDetails') }}
|
|
77217
|
+
</button>
|
|
77218
|
+
</div>
|
|
77219
|
+
</article>
|
|
77220
|
+
}
|
|
77221
|
+
</div>
|
|
77222
|
+
<button
|
|
77223
|
+
type="button"
|
|
77224
|
+
class="christianity-primary-action"
|
|
77225
|
+
data-testid="christianity-confirm-leader"
|
|
77226
|
+
valLightRipple
|
|
77227
|
+
(click)="confirmTutorialLeader()"
|
|
77228
|
+
>
|
|
77229
|
+
{{ t('christianityChooseThisLeader') }}
|
|
77230
|
+
</button>
|
|
77231
|
+
} @else {
|
|
77232
|
+
<button
|
|
77233
|
+
type="button"
|
|
77234
|
+
class="christianity-primary-action"
|
|
77235
|
+
data-testid="christianity-continue-setup"
|
|
77236
|
+
valLightRipple
|
|
77237
|
+
(click)="continueAfterCoin()"
|
|
77238
|
+
>
|
|
77239
|
+
{{ t('christianityContinue') }}
|
|
77240
|
+
</button>
|
|
77163
77241
|
}
|
|
77164
|
-
</span>
|
|
77165
|
-
} @else {
|
|
77166
|
-
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
77167
|
-
}
|
|
77168
|
-
<span>{{ t('christianityHistory') }}</span>
|
|
77169
|
-
<strong>{{ game().historyZone.length }}</strong>
|
|
77170
|
-
</button>
|
|
77171
|
-
<button type="button" class="christianity-zone-pile christianity-zone-pile--deck" data-testid="christianity-deck-zone" valLightRipple aria-live="polite" (click)="inspectDeck()">
|
|
77172
|
-
<span class="christianity-pile-card-hint christianity-pile-card-hint--deck" aria-hidden="true">
|
|
77173
|
-
<i></i>
|
|
77174
|
-
</span>
|
|
77175
|
-
<span>{{ t('christianityDeck') }}</span>
|
|
77176
|
-
<strong>{{ game().sharedDeck.length }}</strong>
|
|
77177
|
-
</button>
|
|
77178
|
-
<button
|
|
77179
|
-
type="button"
|
|
77180
|
-
class="christianity-zone-card christianity-zone-card--place christianity-render-card-button"
|
|
77181
|
-
data-testid="christianity-place-zone"
|
|
77182
|
-
cdkDropList
|
|
77183
|
-
id="christianity-place-drop"
|
|
77184
|
-
[cdkDropListConnectedTo]="['christianity-hand-source']"
|
|
77185
|
-
[cdkDropListEnterPredicate]="canDropOnPlace"
|
|
77186
|
-
[cdkDropListSortingDisabled]="true"
|
|
77187
|
-
[class.is-empty-zone]="!activePlaceCard()"
|
|
77188
|
-
[class.is-play-target]="canPlaceSelectedPlace() || isDraggingPlace()"
|
|
77189
|
-
valLightRipple
|
|
77190
|
-
(cdkDropListDropped)="dropOnPlace($event)"
|
|
77191
|
-
(click)="playSelectedPlaceOrInspect()"
|
|
77192
|
-
>
|
|
77193
|
-
@if (placeStack().length) {
|
|
77194
|
-
@if (activePlaceCard(); as placeCard) {
|
|
77195
|
-
<div class="christianity-place-backdrop" [style.background-image]="placeBackdropImage(placeCard)" aria-hidden="true"></div>
|
|
77196
77242
|
}
|
|
77197
|
-
|
|
77198
|
-
|
|
77199
|
-
|
|
77200
|
-
|
|
77201
|
-
|
|
77202
|
-
|
|
77203
|
-
|
|
77204
|
-
|
|
77205
|
-
</span>
|
|
77206
|
-
} @else {
|
|
77207
|
-
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
77208
|
-
}
|
|
77209
|
-
<span>{{ t('christianityPlace') }}</span>
|
|
77210
|
-
<strong>{{ game().placeZone.length }}</strong>
|
|
77211
|
-
@if (canPlaceSelectedPlace() || isDraggingPlace()) {
|
|
77212
|
-
<em>{{ t('christianityPlayHere') }}</em>
|
|
77213
|
-
}
|
|
77214
|
-
</button>
|
|
77215
|
-
</section>
|
|
77216
|
-
|
|
77217
|
-
<section class="christianity-player-side">
|
|
77218
|
-
<section
|
|
77219
|
-
class="christianity-battle-zone"
|
|
77220
|
-
data-testid="christianity-battle-P1"
|
|
77221
|
-
cdkDropList
|
|
77222
|
-
id="christianity-player-battle-source"
|
|
77223
|
-
[cdkDropListConnectedTo]="attackTargetDropIds()"
|
|
77224
|
-
[cdkDropListSortingDisabled]="true"
|
|
77225
|
-
[class.is-placing-card]="canPlaceSelectedCharacter() || isDraggingCharacter()"
|
|
77226
|
-
[attr.aria-label]="t('christianityYourBattle')"
|
|
77227
|
-
>
|
|
77228
|
-
@for (slot of battleSlots('P1'); track slot.trackId) {
|
|
77229
|
-
@if (slot.card) {
|
|
77243
|
+
</section>
|
|
77244
|
+
}
|
|
77245
|
+
@if (game().status === 'finished') {
|
|
77246
|
+
<section class="christianity-result-panel" data-testid="christianity-result-panel" aria-live="polite">
|
|
77247
|
+
<span>{{ t('christianityGameOver') }}</span>
|
|
77248
|
+
<h2>{{ resultTitle() }}</h2>
|
|
77249
|
+
<p>{{ resultBody() }}</p>
|
|
77250
|
+
<div>
|
|
77230
77251
|
<button
|
|
77231
77252
|
type="button"
|
|
77232
|
-
class="christianity-
|
|
77233
|
-
|
|
77234
|
-
cdkDrag
|
|
77235
|
-
[cdkDragData]="slot.card.instanceId"
|
|
77236
|
-
[cdkDragDisabled]="!canDragAttacker(slot.card)"
|
|
77253
|
+
class="christianity-primary-action"
|
|
77254
|
+
data-testid="christianity-play-again"
|
|
77237
77255
|
valLightRipple
|
|
77238
|
-
|
|
77239
|
-
[class.is-exhausted]="!slot.card.canAttack"
|
|
77240
|
-
[class.is-ready-attacker]="isOwnTurn() && slot.card.canAttack"
|
|
77241
|
-
[class.is-combat-attacker]="isCombatAttacker(slot.card)"
|
|
77242
|
-
(cdkDragStarted)="startDraggingAttacker(slot.card)"
|
|
77243
|
-
(cdkDragEnded)="endDraggingAttacker()"
|
|
77244
|
-
(click)="selectAttacker(slot.card)"
|
|
77256
|
+
(click)="restartTutorial()"
|
|
77245
77257
|
>
|
|
77246
|
-
|
|
77247
|
-
<ng-template cdkDragPreview>
|
|
77248
|
-
<div class="christianity-card-drag-preview">
|
|
77249
|
-
<val-christianity-card [card]="characterRenderCard(slot.card)" variant="board"></val-christianity-card>
|
|
77250
|
-
</div>
|
|
77251
|
-
</ng-template>
|
|
77252
|
-
<ng-template cdkDragPlaceholder>
|
|
77253
|
-
<div class="christianity-card-drag-placeholder"></div>
|
|
77254
|
-
</ng-template>
|
|
77258
|
+
{{ t('christianityPlayAgain') }}
|
|
77255
77259
|
</button>
|
|
77256
|
-
} @else {
|
|
77257
77260
|
<button
|
|
77258
77261
|
type="button"
|
|
77259
|
-
class="christianity-
|
|
77260
|
-
[attr.data-testid]="battleSlotTestId('P1', $index)"
|
|
77261
|
-
cdkDropList
|
|
77262
|
-
[id]="battleSlotDropId($index)"
|
|
77263
|
-
[cdkDropListData]="$index"
|
|
77264
|
-
[cdkDropListConnectedTo]="['christianity-hand-source']"
|
|
77265
|
-
[cdkDropListEnterPredicate]="canDropOnBattleSlot"
|
|
77266
|
-
[cdkDropListSortingDisabled]="true"
|
|
77267
|
-
[class.christianity-slot--play-target]="canPlaceSelectedCharacter() || isDraggingCharacter()"
|
|
77262
|
+
class="christianity-secondary-action"
|
|
77268
77263
|
valLightRipple
|
|
77269
|
-
(
|
|
77270
|
-
(click)="playSelectedCard($index)"
|
|
77264
|
+
(click)="returnToChristianityHome()"
|
|
77271
77265
|
>
|
|
77272
|
-
|
|
77273
|
-
<span>{{ t('christianityPlayHere') }}</span>
|
|
77274
|
-
}
|
|
77266
|
+
{{ t('christianityBackToMenu') }}
|
|
77275
77267
|
</button>
|
|
77276
|
-
|
|
77277
|
-
|
|
77278
|
-
|
|
77279
|
-
|
|
77280
|
-
|
|
77281
|
-
|
|
77282
|
-
|
|
77283
|
-
|
|
77284
|
-
|
|
77285
|
-
|
|
77286
|
-
[
|
|
77287
|
-
[
|
|
77288
|
-
[
|
|
77289
|
-
[
|
|
77290
|
-
|
|
77268
|
+
</div>
|
|
77269
|
+
</section>
|
|
77270
|
+
}
|
|
77271
|
+
<div class="christianity-impact-layer">
|
|
77272
|
+
@if (combatTrail(); as trail) {
|
|
77273
|
+
<span
|
|
77274
|
+
class="christianity-combat-trail"
|
|
77275
|
+
aria-hidden="true"
|
|
77276
|
+
[class.is-leader-target]="trail.tone === 'leader'"
|
|
77277
|
+
[class.is-character-target]="trail.tone === 'character'"
|
|
77278
|
+
[style.--christianity-combat-trail-x]="trail.fromX"
|
|
77279
|
+
[style.--christianity-combat-trail-y]="trail.fromY"
|
|
77280
|
+
[style.--christianity-combat-trail-mid-x]="trail.midX"
|
|
77281
|
+
[style.--christianity-combat-trail-mid-y]="trail.midY"
|
|
77282
|
+
[style.--christianity-combat-trail-length]="trail.length"
|
|
77283
|
+
[style.--christianity-combat-trail-angle]="trail.angle"
|
|
77291
77284
|
>
|
|
77285
|
+
<span></span>
|
|
77286
|
+
</span>
|
|
77287
|
+
}
|
|
77288
|
+
@for (impact of impactEvents(); track impact.id) {
|
|
77289
|
+
<val-mini-game-score-pop [props]="impactPopProps(impact)" />
|
|
77290
|
+
}
|
|
77291
|
+
@if (combatCallout(); as callout) {
|
|
77292
|
+
<val-mini-game-callout [props]="callout" />
|
|
77293
|
+
}
|
|
77294
|
+
</div>
|
|
77295
|
+
<section class="christianity-player-side christianity-player-side--opponent">
|
|
77296
|
+
<section class="christianity-player-rack christianity-player-rack--opponent">
|
|
77297
|
+
<div class="christianity-offerings-zone">
|
|
77292
77298
|
<button
|
|
77293
77299
|
type="button"
|
|
77294
77300
|
class="christianity-offering-pile"
|
|
77295
|
-
data-testid="christianity-offerings-
|
|
77296
|
-
[class.is-empty-zone]="!topOffering('
|
|
77301
|
+
data-testid="christianity-offerings-P2"
|
|
77302
|
+
[class.is-empty-zone]="!topOffering('P2')"
|
|
77297
77303
|
valLightRipple
|
|
77298
|
-
(click)="
|
|
77304
|
+
(click)="openOfferings('P2')"
|
|
77299
77305
|
>
|
|
77300
|
-
@if (offeringStack('
|
|
77306
|
+
@if (offeringStack('P2').length) {
|
|
77301
77307
|
<span class="christianity-zone-card-stack" aria-hidden="true">
|
|
77302
|
-
@for (offering of offeringStack('
|
|
77308
|
+
@for (offering of offeringStack('P2'); track offering.instanceId) {
|
|
77303
77309
|
<val-christianity-card
|
|
77304
77310
|
[card]="offering.ready ? offeringRenderCard(offering) : hiddenCardRenderCard()"
|
|
77305
77311
|
[variant]="offering.ready ? 'baby' : 'back'"
|
|
77306
|
-
[style.transform]="zoneStackTransform($index, offeringStack('
|
|
77312
|
+
[style.transform]="zoneStackTransform($index, offeringStack('P2').length)"
|
|
77307
77313
|
></val-christianity-card>
|
|
77308
77314
|
}
|
|
77309
77315
|
</span>
|
|
@@ -77311,89 +77317,358 @@ class ChristianityGameComponent {
|
|
|
77311
77317
|
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
77312
77318
|
}
|
|
77313
77319
|
<span>{{ t('christianityOfferingReserve') }}</span>
|
|
77314
|
-
<strong>{{ readyOfferings(
|
|
77315
|
-
<small>{{ t('christianityOfferingBase') }} {{ totalOfferings(
|
|
77320
|
+
<strong>{{ readyOfferings(opponent()) }}</strong>
|
|
77321
|
+
<small>{{ t('christianityOfferingBase') }} {{ totalOfferings(opponent()) }}</small>
|
|
77316
77322
|
</button>
|
|
77317
77323
|
</div>
|
|
77318
|
-
|
|
77319
|
-
|
|
77320
|
-
|
|
77321
|
-
|
|
77322
|
-
|
|
77323
|
-
|
|
77324
|
-
|
|
77325
|
-
|
|
77324
|
+
<div
|
|
77325
|
+
class="christianity-attack-drop-target"
|
|
77326
|
+
cdkDropList
|
|
77327
|
+
id="christianity-opponent-leader-drop"
|
|
77328
|
+
[cdkDropListConnectedTo]="ownAttackerDropSourceIds()"
|
|
77329
|
+
[cdkDropListEnterPredicate]="canDropOnOpponentLeader"
|
|
77330
|
+
[cdkDropListSortingDisabled]="true"
|
|
77331
|
+
(cdkDropListDropped)="dropOnOpponentLeader($event)"
|
|
77332
|
+
>
|
|
77333
|
+
<button
|
|
77334
|
+
type="button"
|
|
77335
|
+
class="christianity-leader-card christianity-render-card-button"
|
|
77336
|
+
data-testid="christianity-leader-P2"
|
|
77337
|
+
valLightRipple
|
|
77338
|
+
[class.is-target]="isOpponentLeaderTarget()"
|
|
77339
|
+
[class.is-protected-target]="selectedAttacker() && hasOpponentGuards()"
|
|
77340
|
+
[class.is-combat-target]="isCombatLeaderTarget('P2')"
|
|
77341
|
+
(click)="handleOpponentLeader()"
|
|
77342
|
+
>
|
|
77343
|
+
<val-christianity-card [card]="leaderRenderCard(opponent())" variant="board"></val-christianity-card>
|
|
77344
|
+
</button>
|
|
77326
77345
|
</div>
|
|
77327
|
-
|
|
77346
|
+
<span class="christianity-rack-spacer" aria-hidden="true"></span>
|
|
77347
|
+
</section>
|
|
77348
|
+
|
|
77349
|
+
<section
|
|
77350
|
+
class="christianity-battle-zone christianity-battle-zone--opponent"
|
|
77351
|
+
data-testid="christianity-battle-P2"
|
|
77352
|
+
[attr.aria-label]="t('christianityOpponentBattle')"
|
|
77353
|
+
>
|
|
77354
|
+
@for (slot of battleSlots('P2'); track slot.trackId) {
|
|
77355
|
+
@if (slot.card) {
|
|
77356
|
+
<button
|
|
77357
|
+
type="button"
|
|
77358
|
+
class="christianity-card-preview-card christianity-card-preview-card--battle christianity-render-card-button"
|
|
77359
|
+
[attr.data-testid]="battleCardTestId('P2', slot.card)"
|
|
77360
|
+
cdkDropList
|
|
77361
|
+
[id]="opponentTargetDropId(slot.card)"
|
|
77362
|
+
[cdkDropListConnectedTo]="ownAttackerDropSourceIds()"
|
|
77363
|
+
[cdkDropListEnterPredicate]="canDropOnOpponentCharacter"
|
|
77364
|
+
[cdkDropListSortingDisabled]="true"
|
|
77365
|
+
valLightRipple
|
|
77366
|
+
[class.is-target]="isOpponentCharacterTarget(slot.card)"
|
|
77367
|
+
[class.is-combat-target]="isCombatCharacterTarget(slot.card)"
|
|
77368
|
+
(cdkDropListDropped)="dropOnOpponentCharacter($event, slot.card)"
|
|
77369
|
+
(click)="handleOpponentCharacter(slot.card)"
|
|
77370
|
+
>
|
|
77371
|
+
<val-christianity-card
|
|
77372
|
+
[card]="characterRenderCard(slot.card)"
|
|
77373
|
+
variant="board"
|
|
77374
|
+
></val-christianity-card>
|
|
77375
|
+
</button>
|
|
77376
|
+
} @else {
|
|
77377
|
+
<span class="christianity-slot"></span>
|
|
77378
|
+
}
|
|
77379
|
+
}
|
|
77380
|
+
</section>
|
|
77328
77381
|
</section>
|
|
77329
|
-
</section>
|
|
77330
|
-
</section>
|
|
77331
77382
|
|
|
77332
|
-
|
|
77333
|
-
|
|
77334
|
-
|
|
77335
|
-
|
|
77336
|
-
|
|
77337
|
-
|
|
77338
|
-
|
|
77339
|
-
|
|
77340
|
-
|
|
77341
|
-
|
|
77342
|
-
|
|
77343
|
-
|
|
77344
|
-
|
|
77345
|
-
|
|
77346
|
-
|
|
77347
|
-
|
|
77348
|
-
|
|
77349
|
-
|
|
77350
|
-
|
|
77351
|
-
|
|
77352
|
-
|
|
77353
|
-
|
|
77354
|
-
|
|
77355
|
-
|
|
77356
|
-
|
|
77383
|
+
<section
|
|
77384
|
+
class="christianity-shared-zone"
|
|
77385
|
+
data-testid="christianity-shared-zone"
|
|
77386
|
+
[attr.aria-label]="t('christianitySharedZone')"
|
|
77387
|
+
>
|
|
77388
|
+
<button
|
|
77389
|
+
type="button"
|
|
77390
|
+
class="christianity-zone-pile christianity-zone-pile--history"
|
|
77391
|
+
data-testid="christianity-history-zone"
|
|
77392
|
+
[class.is-empty-zone]="!topHistoryCard()"
|
|
77393
|
+
[class.has-new-card]="historyPulse()"
|
|
77394
|
+
valLightRipple
|
|
77395
|
+
(click)="openHistory()"
|
|
77396
|
+
>
|
|
77397
|
+
@if (historyStack().length) {
|
|
77398
|
+
<span class="christianity-zone-card-stack" aria-hidden="true">
|
|
77399
|
+
@for (cardId of historyStack(); track cardId + $index) {
|
|
77400
|
+
<val-christianity-card
|
|
77401
|
+
[card]="definitionToRenderCard(cardDefinition(cardId), { statusText: t('christianityHistory') })"
|
|
77402
|
+
variant="baby"
|
|
77403
|
+
[style.transform]="zoneStackTransform($index, historyStack().length)"
|
|
77404
|
+
></val-christianity-card>
|
|
77405
|
+
}
|
|
77406
|
+
</span>
|
|
77407
|
+
} @else {
|
|
77408
|
+
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
77409
|
+
}
|
|
77410
|
+
<span>{{ t('christianityHistory') }}</span>
|
|
77411
|
+
<strong>{{ game().historyZone.length }}</strong>
|
|
77412
|
+
</button>
|
|
77413
|
+
<button
|
|
77414
|
+
type="button"
|
|
77415
|
+
class="christianity-zone-pile christianity-zone-pile--deck"
|
|
77416
|
+
data-testid="christianity-deck-zone"
|
|
77417
|
+
valLightRipple
|
|
77418
|
+
aria-live="polite"
|
|
77419
|
+
(click)="inspectDeck()"
|
|
77357
77420
|
>
|
|
77421
|
+
<span class="christianity-pile-card-hint christianity-pile-card-hint--deck" aria-hidden="true">
|
|
77422
|
+
<i></i>
|
|
77423
|
+
</span>
|
|
77424
|
+
<span>{{ t('christianityDeck') }}</span>
|
|
77425
|
+
<strong>{{ game().sharedDeck.length }}</strong>
|
|
77426
|
+
</button>
|
|
77427
|
+
<button
|
|
77428
|
+
type="button"
|
|
77429
|
+
class="christianity-zone-card christianity-zone-card--place christianity-render-card-button"
|
|
77430
|
+
data-testid="christianity-place-zone"
|
|
77431
|
+
cdkDropList
|
|
77432
|
+
id="christianity-place-drop"
|
|
77433
|
+
[cdkDropListConnectedTo]="['christianity-hand-source']"
|
|
77434
|
+
[cdkDropListEnterPredicate]="canDropOnPlace"
|
|
77435
|
+
[cdkDropListSortingDisabled]="true"
|
|
77436
|
+
[class.is-empty-zone]="!activePlaceCard()"
|
|
77437
|
+
[class.is-play-target]="canPlaceSelectedPlace() || isDraggingPlace()"
|
|
77438
|
+
valLightRipple
|
|
77439
|
+
(cdkDropListDropped)="dropOnPlace($event)"
|
|
77440
|
+
(click)="playSelectedPlaceOrInspect()"
|
|
77441
|
+
>
|
|
77442
|
+
@if (placeStack().length) {
|
|
77443
|
+
@if (activePlaceCard(); as placeCard) {
|
|
77444
|
+
<div
|
|
77445
|
+
class="christianity-place-backdrop"
|
|
77446
|
+
[style.background-image]="placeBackdropImage(placeCard)"
|
|
77447
|
+
aria-hidden="true"
|
|
77448
|
+
></div>
|
|
77449
|
+
}
|
|
77450
|
+
<span class="christianity-zone-card-stack" aria-hidden="true">
|
|
77451
|
+
@for (cardId of placeStack(); track cardId + $index) {
|
|
77452
|
+
<val-christianity-card
|
|
77453
|
+
[card]="definitionToRenderCard(cardDefinition(cardId), { statusText: t('christianityPlace') })"
|
|
77454
|
+
variant="baby"
|
|
77455
|
+
[style.transform]="zoneStackTransform($index, placeStack().length)"
|
|
77456
|
+
></val-christianity-card>
|
|
77457
|
+
}
|
|
77458
|
+
</span>
|
|
77459
|
+
} @else {
|
|
77460
|
+
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
77461
|
+
}
|
|
77462
|
+
<span>{{ t('christianityPlace') }}</span>
|
|
77463
|
+
<strong>{{ game().placeZone.length }}</strong>
|
|
77464
|
+
@if (canPlaceSelectedPlace() || isDraggingPlace()) {
|
|
77465
|
+
<em>{{ t('christianityPlayHere') }}</em>
|
|
77466
|
+
}
|
|
77467
|
+
</button>
|
|
77468
|
+
</section>
|
|
77469
|
+
|
|
77470
|
+
<section class="christianity-player-side">
|
|
77471
|
+
<section
|
|
77472
|
+
class="christianity-battle-zone"
|
|
77473
|
+
data-testid="christianity-battle-P1"
|
|
77474
|
+
cdkDropList
|
|
77475
|
+
id="christianity-player-battle-source"
|
|
77476
|
+
[cdkDropListConnectedTo]="attackTargetDropIds()"
|
|
77477
|
+
[cdkDropListSortingDisabled]="true"
|
|
77478
|
+
[class.is-placing-card]="canPlaceSelectedCharacter() || isDraggingCharacter()"
|
|
77479
|
+
[attr.aria-label]="t('christianityYourBattle')"
|
|
77480
|
+
>
|
|
77481
|
+
@for (slot of battleSlots('P1'); track slot.trackId) {
|
|
77482
|
+
@if (slot.card) {
|
|
77483
|
+
<button
|
|
77484
|
+
type="button"
|
|
77485
|
+
class="christianity-card-preview-card christianity-card-preview-card--battle christianity-render-card-button"
|
|
77486
|
+
[attr.data-testid]="battleCardTestId('P1', slot.card)"
|
|
77487
|
+
cdkDrag
|
|
77488
|
+
[cdkDragData]="slot.card.instanceId"
|
|
77489
|
+
[cdkDragDisabled]="!canDragAttacker(slot.card)"
|
|
77490
|
+
valLightRipple
|
|
77491
|
+
[class.is-selected]="selectedAttacker()?.instanceId === slot.card.instanceId"
|
|
77492
|
+
[class.is-exhausted]="!slot.card.canAttack"
|
|
77493
|
+
[class.is-ready-attacker]="isOwnTurn() && slot.card.canAttack"
|
|
77494
|
+
[class.is-combat-attacker]="isCombatAttacker(slot.card)"
|
|
77495
|
+
(cdkDragStarted)="startDraggingAttacker(slot.card)"
|
|
77496
|
+
(cdkDragEnded)="endDraggingAttacker()"
|
|
77497
|
+
(click)="selectAttacker(slot.card)"
|
|
77498
|
+
>
|
|
77499
|
+
<val-christianity-card
|
|
77500
|
+
[card]="characterRenderCard(slot.card)"
|
|
77501
|
+
variant="board"
|
|
77502
|
+
></val-christianity-card>
|
|
77503
|
+
<ng-template cdkDragPreview>
|
|
77504
|
+
<div class="christianity-card-drag-preview">
|
|
77505
|
+
<val-christianity-card
|
|
77506
|
+
[card]="characterRenderCard(slot.card)"
|
|
77507
|
+
variant="board"
|
|
77508
|
+
></val-christianity-card>
|
|
77509
|
+
</div>
|
|
77510
|
+
</ng-template>
|
|
77511
|
+
<ng-template cdkDragPlaceholder>
|
|
77512
|
+
<div class="christianity-card-drag-placeholder"></div>
|
|
77513
|
+
</ng-template>
|
|
77514
|
+
</button>
|
|
77515
|
+
} @else {
|
|
77516
|
+
<button
|
|
77517
|
+
type="button"
|
|
77518
|
+
class="christianity-slot"
|
|
77519
|
+
[attr.data-testid]="battleSlotTestId('P1', $index)"
|
|
77520
|
+
cdkDropList
|
|
77521
|
+
[id]="battleSlotDropId($index)"
|
|
77522
|
+
[cdkDropListData]="$index"
|
|
77523
|
+
[cdkDropListConnectedTo]="['christianity-hand-source']"
|
|
77524
|
+
[cdkDropListEnterPredicate]="canDropOnBattleSlot"
|
|
77525
|
+
[cdkDropListSortingDisabled]="true"
|
|
77526
|
+
[class.christianity-slot--play-target]="canPlaceSelectedCharacter() || isDraggingCharacter()"
|
|
77527
|
+
valLightRipple
|
|
77528
|
+
(cdkDropListDropped)="dropOnBattleSlot($event, $index)"
|
|
77529
|
+
(click)="playSelectedCard($index)"
|
|
77530
|
+
>
|
|
77531
|
+
@if (canPlaceSelectedCharacter() || isDraggingCharacter()) {
|
|
77532
|
+
<span>{{ t('christianityPlayHere') }}</span>
|
|
77533
|
+
}
|
|
77534
|
+
</button>
|
|
77535
|
+
}
|
|
77536
|
+
}
|
|
77537
|
+
</section>
|
|
77538
|
+
|
|
77539
|
+
<section class="christianity-player-rack">
|
|
77540
|
+
<div class="christianity-offerings-zone">
|
|
77541
|
+
<div
|
|
77542
|
+
class="christianity-offering-drop-target"
|
|
77543
|
+
cdkDropList
|
|
77544
|
+
id="christianity-offerings-drop"
|
|
77545
|
+
[cdkDropListConnectedTo]="['christianity-hand-source']"
|
|
77546
|
+
[class.is-play-target]="canPlaceSelectedOffering() || isDraggingOffering()"
|
|
77547
|
+
[cdkDropListEnterPredicate]="canDropOnOfferings"
|
|
77548
|
+
[cdkDropListSortingDisabled]="true"
|
|
77549
|
+
(cdkDropListDropped)="dropOnOfferings($event)"
|
|
77550
|
+
>
|
|
77551
|
+
<button
|
|
77552
|
+
type="button"
|
|
77553
|
+
class="christianity-offering-pile"
|
|
77554
|
+
data-testid="christianity-offerings-P1"
|
|
77555
|
+
[class.is-empty-zone]="!topOffering('P1')"
|
|
77556
|
+
valLightRipple
|
|
77557
|
+
(click)="handleOfferingPile('P1')"
|
|
77558
|
+
>
|
|
77559
|
+
@if (offeringStack('P1').length) {
|
|
77560
|
+
<span class="christianity-zone-card-stack" aria-hidden="true">
|
|
77561
|
+
@for (offering of offeringStack('P1'); track offering.instanceId) {
|
|
77562
|
+
<val-christianity-card
|
|
77563
|
+
[card]="offering.ready ? offeringRenderCard(offering) : hiddenCardRenderCard()"
|
|
77564
|
+
[variant]="offering.ready ? 'baby' : 'back'"
|
|
77565
|
+
[style.transform]="zoneStackTransform($index, offeringStack('P1').length)"
|
|
77566
|
+
></val-christianity-card>
|
|
77567
|
+
}
|
|
77568
|
+
</span>
|
|
77569
|
+
} @else {
|
|
77570
|
+
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
77571
|
+
}
|
|
77572
|
+
<span>{{ t('christianityOfferingReserve') }}</span>
|
|
77573
|
+
<strong>{{ readyOfferings(player()) }}</strong>
|
|
77574
|
+
<small>{{ t('christianityOfferingBase') }} {{ totalOfferings(player()) }}</small>
|
|
77575
|
+
</button>
|
|
77576
|
+
</div>
|
|
77577
|
+
</div>
|
|
77358
77578
|
<button
|
|
77359
77579
|
type="button"
|
|
77360
|
-
class="christianity-
|
|
77361
|
-
|
|
77362
|
-
cdkDrag
|
|
77580
|
+
class="christianity-leader-card christianity-render-card-button"
|
|
77581
|
+
data-testid="christianity-leader-P1"
|
|
77363
77582
|
valLightRipple
|
|
77364
|
-
|
|
77365
|
-
[cdkDragDisabled]="!canPlay(card)"
|
|
77366
|
-
[attr.aria-label]="handCardActionLabel(card)"
|
|
77367
|
-
[class.is-selected]="selectedHandCard() === cardId"
|
|
77368
|
-
[class.is-disabled]="!canPlay(card)"
|
|
77369
|
-
(cdkDragStarted)="startDraggingCard(cardId)"
|
|
77370
|
-
(cdkDragEnded)="endDraggingCard()"
|
|
77371
|
-
(click)="selectHandCard(cardId)"
|
|
77583
|
+
(click)="inspectLeader('P1')"
|
|
77372
77584
|
>
|
|
77373
|
-
<val-christianity-card [card]="
|
|
77374
|
-
<ng-template cdkDragPreview>
|
|
77375
|
-
<div class="christianity-card-drag-preview">
|
|
77376
|
-
<val-christianity-card [card]="definitionToRenderCard(card)" variant="baby"></val-christianity-card>
|
|
77377
|
-
</div>
|
|
77378
|
-
</ng-template>
|
|
77379
|
-
<ng-template cdkDragPlaceholder>
|
|
77380
|
-
<div class="christianity-card-drag-placeholder"></div>
|
|
77381
|
-
</ng-template>
|
|
77585
|
+
<val-christianity-card [card]="leaderRenderCard(player())" variant="board"></val-christianity-card>
|
|
77382
77586
|
</button>
|
|
77383
|
-
<
|
|
77384
|
-
|
|
77385
|
-
|
|
77386
|
-
|
|
77387
|
-
|
|
77388
|
-
|
|
77389
|
-
|
|
77390
|
-
|
|
77587
|
+
<div class="christianity-player-command">
|
|
77588
|
+
<div class="christianity-player-badge">
|
|
77589
|
+
<span class="christianity-avatar" [style.background]="player().avatarColor">{{
|
|
77590
|
+
player().avatar
|
|
77591
|
+
}}</span>
|
|
77592
|
+
<strong>{{ player().displayName }}</strong>
|
|
77593
|
+
</div>
|
|
77594
|
+
</div>
|
|
77595
|
+
</section>
|
|
77596
|
+
</section>
|
|
77597
|
+
</section>
|
|
77598
|
+
|
|
77599
|
+
<section class="christianity-hand-shelf">
|
|
77600
|
+
<div class="christianity-hand-meter">
|
|
77601
|
+
<span>{{ t('christianityHand') }}</span>
|
|
77602
|
+
<strong>{{ player().hand?.length ?? 0 }}</strong>
|
|
77603
|
+
</div>
|
|
77604
|
+
<section
|
|
77605
|
+
class="christianity-hand-fan"
|
|
77606
|
+
data-testid="christianity-hand-P1"
|
|
77607
|
+
cdkDropList
|
|
77608
|
+
id="christianity-hand-source"
|
|
77609
|
+
[cdkDropListConnectedTo]="dropTargetIds()"
|
|
77610
|
+
[attr.aria-label]="t('christianityYourHand')"
|
|
77611
|
+
(pointerleave)="clearHoveredHandIndex()"
|
|
77612
|
+
>
|
|
77613
|
+
@for (cardId of player().hand ?? []; track cardId + $index) {
|
|
77614
|
+
@let card = cardDefinition(cardId);
|
|
77615
|
+
<div
|
|
77616
|
+
class="christianity-hand-card-wrap"
|
|
77617
|
+
[class.is-selected]="selectedHandCard() === cardId"
|
|
77618
|
+
[class.is-dragging]="draggingCardId() === cardId"
|
|
77619
|
+
[style.z-index]="handCardZIndex($index)"
|
|
77620
|
+
[style.transform]="fanTransform($index, player().hand?.length ?? 0, false)"
|
|
77621
|
+
(pointerenter)="setHoveredHandIndex($index)"
|
|
77622
|
+
(pointerdown)="setHoveredHandIndex($index)"
|
|
77623
|
+
(pointerup)="releaseHoveredHand($event)"
|
|
77624
|
+
>
|
|
77625
|
+
<button
|
|
77626
|
+
type="button"
|
|
77627
|
+
class="christianity-card-preview-card christianity-card-preview-card--hand christianity-render-card-button"
|
|
77628
|
+
[attr.data-testid]="handCardTestId(cardId, $index)"
|
|
77629
|
+
cdkDrag
|
|
77630
|
+
valLightRipple
|
|
77631
|
+
[cdkDragData]="cardId"
|
|
77632
|
+
[cdkDragDisabled]="!canPlay(card)"
|
|
77633
|
+
[attr.aria-label]="handCardActionLabel(card)"
|
|
77634
|
+
[class.is-selected]="selectedHandCard() === cardId"
|
|
77635
|
+
[class.is-disabled]="!canPlay(card)"
|
|
77636
|
+
(cdkDragStarted)="startDraggingCard(cardId)"
|
|
77637
|
+
(cdkDragEnded)="endDraggingCard()"
|
|
77638
|
+
(click)="selectHandCard(cardId)"
|
|
77639
|
+
>
|
|
77640
|
+
<val-christianity-card [card]="definitionToRenderCard(card)" variant="baby"></val-christianity-card>
|
|
77641
|
+
<ng-template cdkDragPreview>
|
|
77642
|
+
<div class="christianity-card-drag-preview">
|
|
77643
|
+
<val-christianity-card
|
|
77644
|
+
[card]="definitionToRenderCard(card)"
|
|
77645
|
+
variant="baby"
|
|
77646
|
+
></val-christianity-card>
|
|
77647
|
+
</div>
|
|
77648
|
+
</ng-template>
|
|
77649
|
+
<ng-template cdkDragPlaceholder>
|
|
77650
|
+
<div class="christianity-card-drag-placeholder"></div>
|
|
77651
|
+
</ng-template>
|
|
77652
|
+
</button>
|
|
77653
|
+
<button
|
|
77654
|
+
type="button"
|
|
77655
|
+
class="christianity-card-eye"
|
|
77656
|
+
[attr.aria-label]="t('christianityPreviewCard')"
|
|
77657
|
+
(click)="inspectHandCard(cardId, true); $event.stopPropagation()"
|
|
77658
|
+
></button>
|
|
77659
|
+
</div>
|
|
77660
|
+
}
|
|
77661
|
+
</section>
|
|
77391
77662
|
</section>
|
|
77392
|
-
</section>
|
|
77393
77663
|
}
|
|
77394
77664
|
|
|
77395
77665
|
@if (selectedPreview()) {
|
|
77396
|
-
<button
|
|
77666
|
+
<button
|
|
77667
|
+
type="button"
|
|
77668
|
+
class="christianity-preview-backdrop"
|
|
77669
|
+
[attr.aria-label]="t('christianityClosePreview')"
|
|
77670
|
+
(click)="closePreview()"
|
|
77671
|
+
></button>
|
|
77397
77672
|
<aside
|
|
77398
77673
|
class="christianity-floating-card-shell"
|
|
77399
77674
|
[class.is-history-preview]="canNavigatePreview()"
|
|
@@ -77433,7 +77708,11 @@ class ChristianityGameComponent {
|
|
|
77433
77708
|
</button>
|
|
77434
77709
|
}
|
|
77435
77710
|
@if (selectedPreviewNeighborRenderCard(-1); as previousCard) {
|
|
77436
|
-
<val-christianity-card
|
|
77711
|
+
<val-christianity-card
|
|
77712
|
+
class="christianity-preview-ghost christianity-preview-ghost--previous"
|
|
77713
|
+
[card]="previousCard"
|
|
77714
|
+
variant="full"
|
|
77715
|
+
></val-christianity-card>
|
|
77437
77716
|
}
|
|
77438
77717
|
<div
|
|
77439
77718
|
class="christianity-floating-card"
|
|
@@ -77452,7 +77731,11 @@ class ChristianityGameComponent {
|
|
|
77452
77731
|
}
|
|
77453
77732
|
</div>
|
|
77454
77733
|
@if (selectedPreviewNeighborRenderCard(1); as nextCard) {
|
|
77455
|
-
<val-christianity-card
|
|
77734
|
+
<val-christianity-card
|
|
77735
|
+
class="christianity-preview-ghost christianity-preview-ghost--next"
|
|
77736
|
+
[card]="nextCard"
|
|
77737
|
+
variant="full"
|
|
77738
|
+
></val-christianity-card>
|
|
77456
77739
|
}
|
|
77457
77740
|
</div>
|
|
77458
77741
|
<div class="christianity-preview-side">
|
|
@@ -77536,7 +77819,12 @@ class ChristianityGameComponent {
|
|
|
77536
77819
|
}
|
|
77537
77820
|
|
|
77538
77821
|
@if (selectedInfo(); as info) {
|
|
77539
|
-
<button
|
|
77822
|
+
<button
|
|
77823
|
+
type="button"
|
|
77824
|
+
class="christianity-info-backdrop"
|
|
77825
|
+
[attr.aria-label]="t('close')"
|
|
77826
|
+
(click)="closeInfo()"
|
|
77827
|
+
></button>
|
|
77540
77828
|
<aside class="christianity-info-panel" aria-live="polite">
|
|
77541
77829
|
<button type="button" class="christianity-dialog-close christianity-info-close" (click)="closeInfo()">
|
|
77542
77830
|
{{ t('close') }}
|
|
@@ -77561,14 +77849,24 @@ class ChristianityGameComponent {
|
|
|
77561
77849
|
@if (screen() === 'table') {
|
|
77562
77850
|
<section class="christianity-actions" data-testid="christianity-actions" aria-live="polite">
|
|
77563
77851
|
<p class="christianity-sr-only" data-testid="christianity-status">{{ statusText() }}</p>
|
|
77564
|
-
<button
|
|
77852
|
+
<button
|
|
77853
|
+
type="button"
|
|
77854
|
+
data-testid="christianity-primary-action"
|
|
77855
|
+
[disabled]="tutorialPhase() !== 'in_progress' || selectedActionDisabled()"
|
|
77856
|
+
(click)="playSelectedCard()"
|
|
77857
|
+
>
|
|
77565
77858
|
{{ selectedActionLabel() }}
|
|
77566
77859
|
</button>
|
|
77567
77860
|
</section>
|
|
77568
77861
|
}
|
|
77569
77862
|
|
|
77570
77863
|
@if (showHistory()) {
|
|
77571
|
-
<button
|
|
77864
|
+
<button
|
|
77865
|
+
type="button"
|
|
77866
|
+
class="christianity-history-backdrop"
|
|
77867
|
+
[attr.aria-label]="t('christianityCloseHistory')"
|
|
77868
|
+
(click)="closeHistory()"
|
|
77869
|
+
></button>
|
|
77572
77870
|
<section class="christianity-history-drawer" data-testid="christianity-history-drawer">
|
|
77573
77871
|
<header>
|
|
77574
77872
|
<h2>{{ t('christianityHistory') }}</h2>
|
|
@@ -77583,7 +77881,13 @@ class ChristianityGameComponent {
|
|
|
77583
77881
|
<div class="christianity-history-grid" data-testid="christianity-history-grid">
|
|
77584
77882
|
@for (cardId of game().historyZone; track cardId + $index) {
|
|
77585
77883
|
@let card = cardDefinition(cardId);
|
|
77586
|
-
<button
|
|
77884
|
+
<button
|
|
77885
|
+
type="button"
|
|
77886
|
+
class="christianity-gallery-card-button christianity-render-card-button"
|
|
77887
|
+
[attr.data-testid]="historyCardTestId(cardId, $index)"
|
|
77888
|
+
valLightRipple
|
|
77889
|
+
(click)="inspectHistoryCard(cardId)"
|
|
77890
|
+
>
|
|
77587
77891
|
<val-christianity-card [card]="definitionToRenderCard(card)" variant="baby"></val-christianity-card>
|
|
77588
77892
|
</button>
|
|
77589
77893
|
}
|
|
@@ -77595,7 +77899,12 @@ class ChristianityGameComponent {
|
|
|
77595
77899
|
}
|
|
77596
77900
|
|
|
77597
77901
|
@if (showPlace()) {
|
|
77598
|
-
<button
|
|
77902
|
+
<button
|
|
77903
|
+
type="button"
|
|
77904
|
+
class="christianity-history-backdrop"
|
|
77905
|
+
[attr.aria-label]="t('christianityCloseHistory')"
|
|
77906
|
+
(click)="closePlace()"
|
|
77907
|
+
></button>
|
|
77599
77908
|
<section class="christianity-history-drawer christianity-place-drawer" data-testid="christianity-place-drawer">
|
|
77600
77909
|
<header>
|
|
77601
77910
|
<h2>{{ t('christianityPlace') }}</h2>
|
|
@@ -77608,8 +77917,17 @@ class ChristianityGameComponent {
|
|
|
77608
77917
|
</header>
|
|
77609
77918
|
<div class="christianity-history-grid" data-testid="christianity-place-grid">
|
|
77610
77919
|
@for (cardId of game().placeZone; track cardId + $index) {
|
|
77611
|
-
<button
|
|
77612
|
-
|
|
77920
|
+
<button
|
|
77921
|
+
type="button"
|
|
77922
|
+
class="christianity-gallery-card-button christianity-render-card-button"
|
|
77923
|
+
[attr.data-testid]="'christianity-place-card-' + $index"
|
|
77924
|
+
valLightRipple
|
|
77925
|
+
(click)="inspectPlaceCard(cardId)"
|
|
77926
|
+
>
|
|
77927
|
+
<val-christianity-card
|
|
77928
|
+
[card]="definitionToRenderCard(cardDefinition(cardId), { statusText: t('christianityPlace') })"
|
|
77929
|
+
variant="baby"
|
|
77930
|
+
></val-christianity-card>
|
|
77613
77931
|
</button>
|
|
77614
77932
|
}
|
|
77615
77933
|
</div>
|
|
@@ -77617,8 +77935,16 @@ class ChristianityGameComponent {
|
|
|
77617
77935
|
}
|
|
77618
77936
|
|
|
77619
77937
|
@if (showGallery()) {
|
|
77620
|
-
<button
|
|
77621
|
-
|
|
77938
|
+
<button
|
|
77939
|
+
type="button"
|
|
77940
|
+
class="christianity-history-backdrop christianity-gallery-backdrop"
|
|
77941
|
+
[attr.aria-label]="t('christianityCloseGallery')"
|
|
77942
|
+
(click)="closeGallery()"
|
|
77943
|
+
></button>
|
|
77944
|
+
<section
|
|
77945
|
+
class="christianity-history-drawer christianity-gallery-drawer"
|
|
77946
|
+
data-testid="christianity-gallery-drawer"
|
|
77947
|
+
>
|
|
77622
77948
|
<header>
|
|
77623
77949
|
<div>
|
|
77624
77950
|
<h2>{{ t('christianityGallery') }}</h2>
|
|
@@ -77634,7 +77960,12 @@ class ChristianityGameComponent {
|
|
|
77634
77960
|
<div class="christianity-gallery-controls">
|
|
77635
77961
|
<label>
|
|
77636
77962
|
<span>{{ t('christianityGallerySearch') }}</span>
|
|
77637
|
-
<input
|
|
77963
|
+
<input
|
|
77964
|
+
type="search"
|
|
77965
|
+
[value]="gallerySearch()"
|
|
77966
|
+
(input)="setGallerySearch($event)"
|
|
77967
|
+
[placeholder]="t('christianityGallerySearchPlaceholder')"
|
|
77968
|
+
/>
|
|
77638
77969
|
</label>
|
|
77639
77970
|
<label>
|
|
77640
77971
|
<span>{{ t('christianityGalleryFilter') }}</span>
|
|
@@ -77653,7 +77984,12 @@ class ChristianityGameComponent {
|
|
|
77653
77984
|
</div>
|
|
77654
77985
|
<div class="christianity-gallery-grid">
|
|
77655
77986
|
@for (card of galleryCards(); track card.id) {
|
|
77656
|
-
<button
|
|
77987
|
+
<button
|
|
77988
|
+
type="button"
|
|
77989
|
+
class="christianity-gallery-card-button christianity-render-card-button"
|
|
77990
|
+
valLightRipple
|
|
77991
|
+
(click)="inspectGalleryCard(card.id)"
|
|
77992
|
+
>
|
|
77657
77993
|
<val-christianity-card [card]="definitionToRenderCard(card)" variant="baby"></val-christianity-card>
|
|
77658
77994
|
</button>
|
|
77659
77995
|
} @empty {
|
|
@@ -77665,12 +78001,23 @@ class ChristianityGameComponent {
|
|
|
77665
78001
|
|
|
77666
78002
|
@if (offeringsSeat()) {
|
|
77667
78003
|
@let offeringPlayer = game().players[offeringsSeat()!];
|
|
77668
|
-
<button
|
|
77669
|
-
|
|
78004
|
+
<button
|
|
78005
|
+
type="button"
|
|
78006
|
+
class="christianity-history-backdrop"
|
|
78007
|
+
[attr.aria-label]="t('christianityCloseOfferings')"
|
|
78008
|
+
(click)="closeOfferings()"
|
|
78009
|
+
></button>
|
|
78010
|
+
<section
|
|
78011
|
+
class="christianity-history-drawer christianity-offerings-drawer"
|
|
78012
|
+
[attr.data-testid]="offeringsDrawerTestId(offeringsSeat()!)"
|
|
78013
|
+
>
|
|
77670
78014
|
<header>
|
|
77671
78015
|
<h2>{{ t('christianityOfferings') }}</h2>
|
|
77672
78016
|
<div class="christianity-dialog-actions">
|
|
77673
|
-
<span
|
|
78017
|
+
<span
|
|
78018
|
+
>{{ t('christianityOfferingReserve') }} {{ readyOfferings(offeringPlayer) }} ·
|
|
78019
|
+
{{ t('christianityOfferingBase') }} {{ totalOfferings(offeringPlayer) }}</span
|
|
78020
|
+
>
|
|
77674
78021
|
<button type="button" class="christianity-dialog-close" (click)="closeOfferings()">
|
|
77675
78022
|
{{ t('close') }}
|
|
77676
78023
|
</button>
|
|
@@ -77680,14 +78027,25 @@ class ChristianityGameComponent {
|
|
|
77680
78027
|
<span class="christianity-rule-note-icon" aria-hidden="true">i</span>
|
|
77681
78028
|
<p>{{ t('christianityOfferingsRuleBody') }}</p>
|
|
77682
78029
|
</div>
|
|
77683
|
-
|
|
77684
|
-
|
|
77685
|
-
|
|
77686
|
-
<button
|
|
77687
|
-
|
|
78030
|
+
<div class="christianity-offering-list" [attr.data-testid]="offeringListTestId(offeringsSeat()!)">
|
|
78031
|
+
@for (offering of offeringPlayer.offerings; track offering.instanceId) {
|
|
78032
|
+
<article class="christianity-offering-row" [class.is-exhausted]="!offering.ready">
|
|
78033
|
+
<button
|
|
78034
|
+
type="button"
|
|
78035
|
+
class="christianity-offering-card christianity-render-card-button"
|
|
78036
|
+
[attr.data-testid]="offeringCardTestId(offering)"
|
|
78037
|
+
valLightRipple
|
|
78038
|
+
(click)="inspectOffering(offering)"
|
|
78039
|
+
>
|
|
78040
|
+
<val-christianity-card
|
|
78041
|
+
[card]="offering.ready ? offeringRenderCard(offering) : hiddenCardRenderCard()"
|
|
78042
|
+
[variant]="offering.ready ? 'baby' : 'back'"
|
|
78043
|
+
></val-christianity-card>
|
|
77688
78044
|
</button>
|
|
77689
78045
|
<div>
|
|
77690
|
-
<strong>{{
|
|
78046
|
+
<strong>{{
|
|
78047
|
+
offering.ready ? t('christianityOfferingReady') : t('christianityOfferingExhausted')
|
|
78048
|
+
}}</strong>
|
|
77691
78049
|
<p>{{ offeringAbilityText(offering) }}</p>
|
|
77692
78050
|
@if (offering.abilityName) {
|
|
77693
78051
|
<button
|
|
@@ -77796,418 +78154,276 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
77796
78154
|
</section>
|
|
77797
78155
|
</section>
|
|
77798
78156
|
} @else {
|
|
77799
|
-
|
|
77800
|
-
|
|
77801
|
-
|
|
77802
|
-
|
|
77803
|
-
|
|
77804
|
-
|
|
77805
|
-
|
|
77806
|
-
|
|
77807
|
-
|
|
77808
|
-
|
|
77809
|
-
|
|
77810
|
-
|
|
77811
|
-
|
|
77812
|
-
|
|
77813
|
-
<div>
|
|
77814
|
-
<
|
|
77815
|
-
<
|
|
78157
|
+
<section
|
|
78158
|
+
class="christianity-match-strip"
|
|
78159
|
+
data-testid="christianity-match-strip"
|
|
78160
|
+
[attr.aria-label]="t('christianityMatchScore')"
|
|
78161
|
+
>
|
|
78162
|
+
<article class="christianity-match-player">
|
|
78163
|
+
<span class="christianity-avatar" [style.background]="player().avatarColor">{{ player().avatar }}</span>
|
|
78164
|
+
<div>
|
|
78165
|
+
<strong>{{ player().displayName }}</strong>
|
|
78166
|
+
<small
|
|
78167
|
+
>{{ playerLeaderDisplayName(player()) }} · {{ player().leaderHp }}/{{ player().leaderMaxHp }}</small
|
|
78168
|
+
>
|
|
78169
|
+
</div>
|
|
78170
|
+
</article>
|
|
78171
|
+
<div class="christianity-scoreboard">
|
|
78172
|
+
<span>{{ t('christianityMatch') }}</span>
|
|
78173
|
+
<strong>{{ game().matchScore.P1 }}-{{ game().matchScore.P2 }}</strong>
|
|
77816
78174
|
</div>
|
|
77817
|
-
|
|
77818
|
-
|
|
78175
|
+
<article class="christianity-match-player christianity-match-player--opponent">
|
|
78176
|
+
<span class="christianity-avatar" [style.background]="opponent().avatarColor">{{ opponent().avatar }}</span>
|
|
78177
|
+
<div>
|
|
78178
|
+
<strong>{{ opponent().displayName }}</strong>
|
|
78179
|
+
<small
|
|
78180
|
+
>{{ playerLeaderDisplayName(opponent()) }} · {{ opponent().leaderHp }}/{{
|
|
78181
|
+
opponent().leaderMaxHp
|
|
78182
|
+
}}</small
|
|
78183
|
+
>
|
|
78184
|
+
</div>
|
|
78185
|
+
</article>
|
|
78186
|
+
</section>
|
|
77819
78187
|
|
|
77820
|
-
|
|
77821
|
-
|
|
77822
|
-
|
|
77823
|
-
|
|
77824
|
-
|
|
77825
|
-
|
|
77826
|
-
|
|
77827
|
-
|
|
77828
|
-
|
|
77829
|
-
|
|
77830
|
-
|
|
77831
|
-
|
|
77832
|
-
</div>
|
|
77833
|
-
<div class="christianity-turn-actions">
|
|
77834
|
-
<button
|
|
77835
|
-
type="button"
|
|
77836
|
-
class="christianity-end-turn"
|
|
77837
|
-
data-testid="christianity-end-turn"
|
|
77838
|
-
[disabled]="!isOwnTurn() || tutorialPhase() !== 'in_progress' || !!combatAnimation()"
|
|
77839
|
-
(click)="endTurn()"
|
|
77840
|
-
>
|
|
77841
|
-
{{ t('christianityEndTurn') }}
|
|
77842
|
-
</button>
|
|
77843
|
-
<button type="button" class="christianity-options-button" data-testid="christianity-options-button" valLightRipple (click)="toggleOptions()">
|
|
77844
|
-
{{ t('christianityOptions') }}
|
|
77845
|
-
</button>
|
|
77846
|
-
</div>
|
|
77847
|
-
@if (showOptions()) {
|
|
77848
|
-
<div class="christianity-options-menu" data-testid="christianity-options-menu">
|
|
77849
|
-
<button type="button" (click)="restartTutorial()">{{ t('christianityRestart') }}</button>
|
|
77850
|
-
<button type="button" [disabled]="game().status === 'finished'" (click)="resignTutorial()">{{ t('christianityResign') }}</button>
|
|
77851
|
-
<button type="button" (click)="returnToChristianityHome()">{{ t('christianityBackToMenu') }}</button>
|
|
78188
|
+
<section
|
|
78189
|
+
class="christianity-turn-banner"
|
|
78190
|
+
data-testid="christianity-turn-banner"
|
|
78191
|
+
[class.is-own-turn]="isOwnTurn()"
|
|
78192
|
+
[class.is-rival-turn]="!isOwnTurn() && game().status === 'in_progress'"
|
|
78193
|
+
[class.is-finished]="game().status === 'finished'"
|
|
78194
|
+
aria-live="polite"
|
|
78195
|
+
>
|
|
78196
|
+
<div>
|
|
78197
|
+
<span>{{ t('christianityTurn') }} {{ game().turnCount }}</span>
|
|
78198
|
+
<strong>{{ turnBannerTitle() }}</strong>
|
|
78199
|
+
<p>{{ turnBannerBody() }}</p>
|
|
77852
78200
|
</div>
|
|
77853
|
-
|
|
77854
|
-
</section>
|
|
77855
|
-
|
|
77856
|
-
<section class="christianity-hand-shelf christianity-hand-shelf--opponent">
|
|
77857
|
-
<div class="christianity-hand-meter christianity-hand-meter--opponent">
|
|
77858
|
-
<span>{{ t('christianityHand') }}</span>
|
|
77859
|
-
<strong>{{ opponentHandCount() }}</strong>
|
|
77860
|
-
</div>
|
|
77861
|
-
<section class="christianity-hand-fan christianity-hand-fan--opponent" data-testid="christianity-opponent-hand" [attr.aria-label]="t('christianityOpponentHand')">
|
|
77862
|
-
@for (_ of hiddenHandCards(opponentHandCount()); track $index) {
|
|
78201
|
+
<div class="christianity-turn-actions">
|
|
77863
78202
|
<button
|
|
77864
78203
|
type="button"
|
|
77865
|
-
class="christianity-
|
|
78204
|
+
class="christianity-end-turn"
|
|
78205
|
+
data-testid="christianity-end-turn"
|
|
78206
|
+
[disabled]="!isOwnTurn() || tutorialPhase() !== 'in_progress' || !!combatAnimation()"
|
|
78207
|
+
(click)="endTurn()"
|
|
78208
|
+
>
|
|
78209
|
+
{{ t('christianityEndTurn') }}
|
|
78210
|
+
</button>
|
|
78211
|
+
<button
|
|
78212
|
+
type="button"
|
|
78213
|
+
class="christianity-options-button"
|
|
78214
|
+
data-testid="christianity-options-button"
|
|
77866
78215
|
valLightRipple
|
|
77867
|
-
|
|
77868
|
-
[attr.aria-label]="t('christianityHiddenCard')"
|
|
78216
|
+
(click)="toggleOptions()"
|
|
77869
78217
|
>
|
|
77870
|
-
|
|
78218
|
+
{{ t('christianityOptions') }}
|
|
77871
78219
|
</button>
|
|
78220
|
+
</div>
|
|
78221
|
+
@if (showOptions()) {
|
|
78222
|
+
<div class="christianity-options-menu" data-testid="christianity-options-menu">
|
|
78223
|
+
<button type="button" (click)="restartTutorial()">{{ t('christianityRestart') }}</button>
|
|
78224
|
+
<button type="button" [disabled]="game().status === 'finished'" (click)="resignTutorial()">
|
|
78225
|
+
{{ t('christianityResign') }}
|
|
78226
|
+
</button>
|
|
78227
|
+
<button type="button" (click)="returnToChristianityHome()">{{ t('christianityBackToMenu') }}</button>
|
|
78228
|
+
</div>
|
|
77872
78229
|
}
|
|
77873
78230
|
</section>
|
|
77874
|
-
</section>
|
|
77875
78231
|
|
|
77876
|
-
|
|
77877
|
-
|
|
78232
|
+
<section class="christianity-hand-shelf christianity-hand-shelf--opponent">
|
|
78233
|
+
<div class="christianity-hand-meter christianity-hand-meter--opponent">
|
|
78234
|
+
<span>{{ t('christianityHand') }}</span>
|
|
78235
|
+
<strong>{{ opponentHandCount() }}</strong>
|
|
78236
|
+
</div>
|
|
77878
78237
|
<section
|
|
77879
|
-
class="christianity-
|
|
77880
|
-
|
|
77881
|
-
[
|
|
77882
|
-
data-testid="christianity-setup-panel"
|
|
77883
|
-
aria-live="polite"
|
|
78238
|
+
class="christianity-hand-fan christianity-hand-fan--opponent"
|
|
78239
|
+
data-testid="christianity-opponent-hand"
|
|
78240
|
+
[attr.aria-label]="t('christianityOpponentHand')"
|
|
77884
78241
|
>
|
|
77885
|
-
@
|
|
77886
|
-
<div
|
|
77887
|
-
class="christianity-setup-coin"
|
|
77888
|
-
[class.is-rival-won]="tutorialSetup()?.coinWinner === 'P2'"
|
|
77889
|
-
aria-hidden="true"
|
|
77890
|
-
>
|
|
77891
|
-
<span></span>
|
|
77892
|
-
<span></span>
|
|
77893
|
-
</div>
|
|
77894
|
-
}
|
|
77895
|
-
<div>
|
|
77896
|
-
<span>{{ t('christianityMatchSetup') }}</span>
|
|
77897
|
-
<h2>{{ setupTitle() }}</h2>
|
|
77898
|
-
<p>{{ setupBody() }}</p>
|
|
77899
|
-
</div>
|
|
77900
|
-
@if (tutorialPhase() === 'coin') {
|
|
77901
|
-
<button type="button" class="christianity-primary-action" data-testid="christianity-continue-setup" valLightRipple (click)="continueAfterCoin()">
|
|
77902
|
-
{{ t('christianityContinue') }}
|
|
77903
|
-
</button>
|
|
77904
|
-
}
|
|
77905
|
-
@if (tutorialPhase() === 'leader_pick') {
|
|
77906
|
-
@if (tutorialSetup()?.leaderPicker === 'P1' && (tutorialSetup()?.availableLeaders?.length ?? 0) > 1) {
|
|
77907
|
-
<div class="christianity-leader-choice-meter" aria-live="polite">
|
|
77908
|
-
<span>{{ t('christianityLeaderChoiceTimer').replace('{seconds}', leaderChoiceSeconds().toString()) }}</span>
|
|
77909
|
-
<i [style.transform]="'scaleX(' + (leaderChoiceSeconds() / leaderChoiceTotalSeconds) + ')'"></i>
|
|
77910
|
-
</div>
|
|
77911
|
-
<div class="christianity-leader-choice-grid" data-testid="christianity-leader-choice-grid">
|
|
77912
|
-
@for (leaderId of tutorialSetup()?.availableLeaders ?? []; track leaderId) {
|
|
77913
|
-
@let leader = cardDefinition(leaderId);
|
|
77914
|
-
<article class="christianity-leader-choice-option" [class.is-selected]="selectedTutorialLeaderId() === leaderId">
|
|
77915
|
-
<button
|
|
77916
|
-
type="button"
|
|
77917
|
-
class="christianity-leader-choice-card christianity-render-card-button"
|
|
77918
|
-
valLightRipple
|
|
77919
|
-
[attr.aria-pressed]="selectedTutorialLeaderId() === leaderId"
|
|
77920
|
-
(click)="selectTutorialLeader(leaderId)"
|
|
77921
|
-
>
|
|
77922
|
-
<val-christianity-card [card]="definitionToRenderCard(leader)" variant="baby"></val-christianity-card>
|
|
77923
|
-
</button>
|
|
77924
|
-
<div>
|
|
77925
|
-
<span>{{ selectedTutorialLeaderId() === leaderId ? t('christianityLeaderSelected') : t('christianitySelectLeader') }}</span>
|
|
77926
|
-
<button type="button" class="christianity-leader-choice-detail" valLightRipple (click)="inspectLeaderChoice(leaderId)">
|
|
77927
|
-
{{ t('christianityViewDetails') }}
|
|
77928
|
-
</button>
|
|
77929
|
-
</div>
|
|
77930
|
-
</article>
|
|
77931
|
-
}
|
|
77932
|
-
</div>
|
|
77933
|
-
<button type="button" class="christianity-primary-action" data-testid="christianity-confirm-leader" valLightRipple (click)="confirmTutorialLeader()">
|
|
77934
|
-
{{ t('christianityChooseThisLeader') }}
|
|
77935
|
-
</button>
|
|
77936
|
-
} @else {
|
|
77937
|
-
<button type="button" class="christianity-primary-action" data-testid="christianity-continue-setup" valLightRipple (click)="continueAfterCoin()">
|
|
77938
|
-
{{ t('christianityContinue') }}
|
|
77939
|
-
</button>
|
|
77940
|
-
}
|
|
77941
|
-
}
|
|
77942
|
-
</section>
|
|
77943
|
-
}
|
|
77944
|
-
@if (game().status === 'finished') {
|
|
77945
|
-
<section class="christianity-result-panel" data-testid="christianity-result-panel" aria-live="polite">
|
|
77946
|
-
<span>{{ t('christianityGameOver') }}</span>
|
|
77947
|
-
<h2>{{ resultTitle() }}</h2>
|
|
77948
|
-
<p>{{ resultBody() }}</p>
|
|
77949
|
-
<div>
|
|
77950
|
-
<button type="button" class="christianity-primary-action" data-testid="christianity-play-again" valLightRipple (click)="restartTutorial()">
|
|
77951
|
-
{{ t('christianityPlayAgain') }}
|
|
77952
|
-
</button>
|
|
77953
|
-
<button type="button" class="christianity-secondary-action" valLightRipple (click)="returnToChristianityHome()">
|
|
77954
|
-
{{ t('christianityBackToMenu') }}
|
|
77955
|
-
</button>
|
|
77956
|
-
</div>
|
|
77957
|
-
</section>
|
|
77958
|
-
}
|
|
77959
|
-
<div class="christianity-impact-layer">
|
|
77960
|
-
@if (combatTrail(); as trail) {
|
|
77961
|
-
<span
|
|
77962
|
-
class="christianity-combat-trail"
|
|
77963
|
-
aria-hidden="true"
|
|
77964
|
-
[class.is-leader-target]="trail.tone === 'leader'"
|
|
77965
|
-
[class.is-character-target]="trail.tone === 'character'"
|
|
77966
|
-
[style.--christianity-combat-trail-x]="trail.fromX"
|
|
77967
|
-
[style.--christianity-combat-trail-y]="trail.fromY"
|
|
77968
|
-
[style.--christianity-combat-trail-mid-x]="trail.midX"
|
|
77969
|
-
[style.--christianity-combat-trail-mid-y]="trail.midY"
|
|
77970
|
-
[style.--christianity-combat-trail-length]="trail.length"
|
|
77971
|
-
[style.--christianity-combat-trail-angle]="trail.angle"
|
|
77972
|
-
>
|
|
77973
|
-
<span></span>
|
|
77974
|
-
</span>
|
|
77975
|
-
}
|
|
77976
|
-
@for (impact of impactEvents(); track impact.id) {
|
|
77977
|
-
<val-mini-game-score-pop [props]="impactPopProps(impact)" />
|
|
77978
|
-
}
|
|
77979
|
-
@if (combatCallout(); as callout) {
|
|
77980
|
-
<val-mini-game-callout [props]="callout" />
|
|
77981
|
-
}
|
|
77982
|
-
</div>
|
|
77983
|
-
<section class="christianity-player-side christianity-player-side--opponent">
|
|
77984
|
-
<section class="christianity-player-rack christianity-player-rack--opponent">
|
|
77985
|
-
<div class="christianity-offerings-zone">
|
|
77986
|
-
<button type="button" class="christianity-offering-pile" data-testid="christianity-offerings-P2" [class.is-empty-zone]="!topOffering('P2')" valLightRipple (click)="openOfferings('P2')">
|
|
77987
|
-
@if (offeringStack('P2').length) {
|
|
77988
|
-
<span class="christianity-zone-card-stack" aria-hidden="true">
|
|
77989
|
-
@for (offering of offeringStack('P2'); track offering.instanceId) {
|
|
77990
|
-
<val-christianity-card
|
|
77991
|
-
[card]="offering.ready ? offeringRenderCard(offering) : hiddenCardRenderCard()"
|
|
77992
|
-
[variant]="offering.ready ? 'baby' : 'back'"
|
|
77993
|
-
[style.transform]="zoneStackTransform($index, offeringStack('P2').length)"
|
|
77994
|
-
></val-christianity-card>
|
|
77995
|
-
}
|
|
77996
|
-
</span>
|
|
77997
|
-
} @else {
|
|
77998
|
-
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
77999
|
-
}
|
|
78000
|
-
<span>{{ t('christianityOfferingReserve') }}</span>
|
|
78001
|
-
<strong>{{ readyOfferings(opponent()) }}</strong>
|
|
78002
|
-
<small>{{ t('christianityOfferingBase') }} {{ totalOfferings(opponent()) }}</small>
|
|
78003
|
-
</button>
|
|
78004
|
-
</div>
|
|
78005
|
-
<div
|
|
78006
|
-
class="christianity-attack-drop-target"
|
|
78007
|
-
cdkDropList
|
|
78008
|
-
id="christianity-opponent-leader-drop"
|
|
78009
|
-
[cdkDropListConnectedTo]="ownAttackerDropSourceIds()"
|
|
78010
|
-
[cdkDropListEnterPredicate]="canDropOnOpponentLeader"
|
|
78011
|
-
[cdkDropListSortingDisabled]="true"
|
|
78012
|
-
(cdkDropListDropped)="dropOnOpponentLeader($event)"
|
|
78013
|
-
>
|
|
78242
|
+
@for (_ of hiddenHandCards(opponentHandCount()); track $index) {
|
|
78014
78243
|
<button
|
|
78015
78244
|
type="button"
|
|
78016
|
-
class="christianity-
|
|
78017
|
-
data-testid="christianity-leader-P2"
|
|
78245
|
+
class="christianity-hidden-card-button christianity-render-card-button"
|
|
78018
78246
|
valLightRipple
|
|
78019
|
-
[
|
|
78020
|
-
[
|
|
78021
|
-
[class.is-combat-target]="isCombatLeaderTarget('P2')"
|
|
78022
|
-
(click)="handleOpponentLeader()"
|
|
78247
|
+
[style.transform]="fanTransform($index, opponentHandCount(), true)"
|
|
78248
|
+
[attr.aria-label]="t('christianityHiddenCard')"
|
|
78023
78249
|
>
|
|
78024
|
-
|
|
78250
|
+
<val-christianity-card [card]="hiddenCardRenderCard()" variant="back"></val-christianity-card>
|
|
78025
78251
|
</button>
|
|
78026
|
-
|
|
78027
|
-
<span class="christianity-rack-spacer" aria-hidden="true"></span>
|
|
78252
|
+
}
|
|
78028
78253
|
</section>
|
|
78254
|
+
</section>
|
|
78029
78255
|
|
|
78030
|
-
|
|
78031
|
-
|
|
78032
|
-
|
|
78256
|
+
<section class="christianity-table" data-testid="christianity-table" [attr.aria-label]="t('christianityTable')">
|
|
78257
|
+
@if (tutorialPhase() !== 'in_progress' && tutorialPhase() !== 'finished') {
|
|
78258
|
+
<section
|
|
78259
|
+
class="christianity-setup-panel"
|
|
78260
|
+
[class.christianity-setup-panel--coin]="tutorialPhase() === 'coin'"
|
|
78261
|
+
[class.christianity-setup-panel--leader-pick]="tutorialPhase() === 'leader_pick'"
|
|
78262
|
+
data-testid="christianity-setup-panel"
|
|
78263
|
+
aria-live="polite"
|
|
78264
|
+
>
|
|
78265
|
+
@if (tutorialPhase() === 'coin') {
|
|
78266
|
+
<div
|
|
78267
|
+
class="christianity-setup-coin"
|
|
78268
|
+
[class.is-rival-won]="tutorialSetup()?.coinWinner === 'P2'"
|
|
78269
|
+
aria-hidden="true"
|
|
78270
|
+
>
|
|
78271
|
+
<span></span>
|
|
78272
|
+
<span></span>
|
|
78273
|
+
</div>
|
|
78274
|
+
}
|
|
78275
|
+
<div>
|
|
78276
|
+
<span>{{ t('christianityMatchSetup') }}</span>
|
|
78277
|
+
<h2>{{ setupTitle() }}</h2>
|
|
78278
|
+
<p>{{ setupBody() }}</p>
|
|
78279
|
+
</div>
|
|
78280
|
+
@if (tutorialPhase() === 'coin') {
|
|
78033
78281
|
<button
|
|
78034
78282
|
type="button"
|
|
78035
|
-
class="christianity-
|
|
78036
|
-
|
|
78037
|
-
cdkDropList
|
|
78038
|
-
[id]="opponentTargetDropId(slot.card)"
|
|
78039
|
-
[cdkDropListConnectedTo]="ownAttackerDropSourceIds()"
|
|
78040
|
-
[cdkDropListEnterPredicate]="canDropOnOpponentCharacter"
|
|
78041
|
-
[cdkDropListSortingDisabled]="true"
|
|
78283
|
+
class="christianity-primary-action"
|
|
78284
|
+
data-testid="christianity-continue-setup"
|
|
78042
78285
|
valLightRipple
|
|
78043
|
-
|
|
78044
|
-
[class.is-combat-target]="isCombatCharacterTarget(slot.card)"
|
|
78045
|
-
(cdkDropListDropped)="dropOnOpponentCharacter($event, slot.card)"
|
|
78046
|
-
(click)="handleOpponentCharacter(slot.card)"
|
|
78286
|
+
(click)="continueAfterCoin()"
|
|
78047
78287
|
>
|
|
78048
|
-
|
|
78288
|
+
{{ t('christianityContinue') }}
|
|
78049
78289
|
</button>
|
|
78050
|
-
} @else {
|
|
78051
|
-
<span class="christianity-slot"></span>
|
|
78052
78290
|
}
|
|
78053
|
-
|
|
78054
|
-
|
|
78055
|
-
|
|
78056
|
-
|
|
78057
|
-
|
|
78058
|
-
|
|
78059
|
-
|
|
78060
|
-
|
|
78061
|
-
|
|
78062
|
-
|
|
78063
|
-
|
|
78064
|
-
|
|
78065
|
-
|
|
78066
|
-
|
|
78291
|
+
@if (tutorialPhase() === 'leader_pick') {
|
|
78292
|
+
@if (tutorialSetup()?.leaderPicker === 'P1' && (tutorialSetup()?.availableLeaders?.length ?? 0) > 1) {
|
|
78293
|
+
<div class="christianity-leader-choice-meter" aria-live="polite">
|
|
78294
|
+
<span>{{
|
|
78295
|
+
t('christianityLeaderChoiceTimer').replace('{seconds}', leaderChoiceSeconds().toString())
|
|
78296
|
+
}}</span>
|
|
78297
|
+
<i [style.transform]="'scaleX(' + leaderChoiceSeconds() / leaderChoiceTotalSeconds + ')'"></i>
|
|
78298
|
+
</div>
|
|
78299
|
+
<div class="christianity-leader-choice-grid" data-testid="christianity-leader-choice-grid">
|
|
78300
|
+
@for (leaderId of tutorialSetup()?.availableLeaders ?? []; track leaderId) {
|
|
78301
|
+
@let leader = cardDefinition(leaderId);
|
|
78302
|
+
<article
|
|
78303
|
+
class="christianity-leader-choice-option"
|
|
78304
|
+
[class.is-selected]="selectedTutorialLeaderId() === leaderId"
|
|
78305
|
+
>
|
|
78306
|
+
<button
|
|
78307
|
+
type="button"
|
|
78308
|
+
class="christianity-leader-choice-card christianity-render-card-button"
|
|
78309
|
+
valLightRipple
|
|
78310
|
+
[attr.aria-pressed]="selectedTutorialLeaderId() === leaderId"
|
|
78311
|
+
(click)="selectTutorialLeader(leaderId)"
|
|
78312
|
+
>
|
|
78313
|
+
<val-christianity-card
|
|
78314
|
+
[card]="definitionToRenderCard(leader)"
|
|
78315
|
+
variant="baby"
|
|
78316
|
+
></val-christianity-card>
|
|
78317
|
+
</button>
|
|
78318
|
+
<div>
|
|
78319
|
+
<span>{{
|
|
78320
|
+
selectedTutorialLeaderId() === leaderId
|
|
78321
|
+
? t('christianityLeaderSelected')
|
|
78322
|
+
: t('christianitySelectLeader')
|
|
78323
|
+
}}</span>
|
|
78324
|
+
<button
|
|
78325
|
+
type="button"
|
|
78326
|
+
class="christianity-leader-choice-detail"
|
|
78327
|
+
valLightRipple
|
|
78328
|
+
(click)="inspectLeaderChoice(leaderId)"
|
|
78329
|
+
>
|
|
78330
|
+
{{ t('christianityViewDetails') }}
|
|
78331
|
+
</button>
|
|
78332
|
+
</div>
|
|
78333
|
+
</article>
|
|
78334
|
+
}
|
|
78335
|
+
</div>
|
|
78336
|
+
<button
|
|
78337
|
+
type="button"
|
|
78338
|
+
class="christianity-primary-action"
|
|
78339
|
+
data-testid="christianity-confirm-leader"
|
|
78340
|
+
valLightRipple
|
|
78341
|
+
(click)="confirmTutorialLeader()"
|
|
78342
|
+
>
|
|
78343
|
+
{{ t('christianityChooseThisLeader') }}
|
|
78344
|
+
</button>
|
|
78345
|
+
} @else {
|
|
78346
|
+
<button
|
|
78347
|
+
type="button"
|
|
78348
|
+
class="christianity-primary-action"
|
|
78349
|
+
data-testid="christianity-continue-setup"
|
|
78350
|
+
valLightRipple
|
|
78351
|
+
(click)="continueAfterCoin()"
|
|
78352
|
+
>
|
|
78353
|
+
{{ t('christianityContinue') }}
|
|
78354
|
+
</button>
|
|
78067
78355
|
}
|
|
78068
|
-
</span>
|
|
78069
|
-
} @else {
|
|
78070
|
-
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
78071
|
-
}
|
|
78072
|
-
<span>{{ t('christianityHistory') }}</span>
|
|
78073
|
-
<strong>{{ game().historyZone.length }}</strong>
|
|
78074
|
-
</button>
|
|
78075
|
-
<button type="button" class="christianity-zone-pile christianity-zone-pile--deck" data-testid="christianity-deck-zone" valLightRipple aria-live="polite" (click)="inspectDeck()">
|
|
78076
|
-
<span class="christianity-pile-card-hint christianity-pile-card-hint--deck" aria-hidden="true">
|
|
78077
|
-
<i></i>
|
|
78078
|
-
</span>
|
|
78079
|
-
<span>{{ t('christianityDeck') }}</span>
|
|
78080
|
-
<strong>{{ game().sharedDeck.length }}</strong>
|
|
78081
|
-
</button>
|
|
78082
|
-
<button
|
|
78083
|
-
type="button"
|
|
78084
|
-
class="christianity-zone-card christianity-zone-card--place christianity-render-card-button"
|
|
78085
|
-
data-testid="christianity-place-zone"
|
|
78086
|
-
cdkDropList
|
|
78087
|
-
id="christianity-place-drop"
|
|
78088
|
-
[cdkDropListConnectedTo]="['christianity-hand-source']"
|
|
78089
|
-
[cdkDropListEnterPredicate]="canDropOnPlace"
|
|
78090
|
-
[cdkDropListSortingDisabled]="true"
|
|
78091
|
-
[class.is-empty-zone]="!activePlaceCard()"
|
|
78092
|
-
[class.is-play-target]="canPlaceSelectedPlace() || isDraggingPlace()"
|
|
78093
|
-
valLightRipple
|
|
78094
|
-
(cdkDropListDropped)="dropOnPlace($event)"
|
|
78095
|
-
(click)="playSelectedPlaceOrInspect()"
|
|
78096
|
-
>
|
|
78097
|
-
@if (placeStack().length) {
|
|
78098
|
-
@if (activePlaceCard(); as placeCard) {
|
|
78099
|
-
<div class="christianity-place-backdrop" [style.background-image]="placeBackdropImage(placeCard)" aria-hidden="true"></div>
|
|
78100
78356
|
}
|
|
78101
|
-
|
|
78102
|
-
|
|
78103
|
-
|
|
78104
|
-
|
|
78105
|
-
|
|
78106
|
-
|
|
78107
|
-
|
|
78108
|
-
|
|
78109
|
-
</span>
|
|
78110
|
-
} @else {
|
|
78111
|
-
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
78112
|
-
}
|
|
78113
|
-
<span>{{ t('christianityPlace') }}</span>
|
|
78114
|
-
<strong>{{ game().placeZone.length }}</strong>
|
|
78115
|
-
@if (canPlaceSelectedPlace() || isDraggingPlace()) {
|
|
78116
|
-
<em>{{ t('christianityPlayHere') }}</em>
|
|
78117
|
-
}
|
|
78118
|
-
</button>
|
|
78119
|
-
</section>
|
|
78120
|
-
|
|
78121
|
-
<section class="christianity-player-side">
|
|
78122
|
-
<section
|
|
78123
|
-
class="christianity-battle-zone"
|
|
78124
|
-
data-testid="christianity-battle-P1"
|
|
78125
|
-
cdkDropList
|
|
78126
|
-
id="christianity-player-battle-source"
|
|
78127
|
-
[cdkDropListConnectedTo]="attackTargetDropIds()"
|
|
78128
|
-
[cdkDropListSortingDisabled]="true"
|
|
78129
|
-
[class.is-placing-card]="canPlaceSelectedCharacter() || isDraggingCharacter()"
|
|
78130
|
-
[attr.aria-label]="t('christianityYourBattle')"
|
|
78131
|
-
>
|
|
78132
|
-
@for (slot of battleSlots('P1'); track slot.trackId) {
|
|
78133
|
-
@if (slot.card) {
|
|
78357
|
+
</section>
|
|
78358
|
+
}
|
|
78359
|
+
@if (game().status === 'finished') {
|
|
78360
|
+
<section class="christianity-result-panel" data-testid="christianity-result-panel" aria-live="polite">
|
|
78361
|
+
<span>{{ t('christianityGameOver') }}</span>
|
|
78362
|
+
<h2>{{ resultTitle() }}</h2>
|
|
78363
|
+
<p>{{ resultBody() }}</p>
|
|
78364
|
+
<div>
|
|
78134
78365
|
<button
|
|
78135
78366
|
type="button"
|
|
78136
|
-
class="christianity-
|
|
78137
|
-
|
|
78138
|
-
cdkDrag
|
|
78139
|
-
[cdkDragData]="slot.card.instanceId"
|
|
78140
|
-
[cdkDragDisabled]="!canDragAttacker(slot.card)"
|
|
78367
|
+
class="christianity-primary-action"
|
|
78368
|
+
data-testid="christianity-play-again"
|
|
78141
78369
|
valLightRipple
|
|
78142
|
-
|
|
78143
|
-
[class.is-exhausted]="!slot.card.canAttack"
|
|
78144
|
-
[class.is-ready-attacker]="isOwnTurn() && slot.card.canAttack"
|
|
78145
|
-
[class.is-combat-attacker]="isCombatAttacker(slot.card)"
|
|
78146
|
-
(cdkDragStarted)="startDraggingAttacker(slot.card)"
|
|
78147
|
-
(cdkDragEnded)="endDraggingAttacker()"
|
|
78148
|
-
(click)="selectAttacker(slot.card)"
|
|
78370
|
+
(click)="restartTutorial()"
|
|
78149
78371
|
>
|
|
78150
|
-
|
|
78151
|
-
<ng-template cdkDragPreview>
|
|
78152
|
-
<div class="christianity-card-drag-preview">
|
|
78153
|
-
<val-christianity-card [card]="characterRenderCard(slot.card)" variant="board"></val-christianity-card>
|
|
78154
|
-
</div>
|
|
78155
|
-
</ng-template>
|
|
78156
|
-
<ng-template cdkDragPlaceholder>
|
|
78157
|
-
<div class="christianity-card-drag-placeholder"></div>
|
|
78158
|
-
</ng-template>
|
|
78372
|
+
{{ t('christianityPlayAgain') }}
|
|
78159
78373
|
</button>
|
|
78160
|
-
} @else {
|
|
78161
78374
|
<button
|
|
78162
78375
|
type="button"
|
|
78163
|
-
class="christianity-
|
|
78164
|
-
[attr.data-testid]="battleSlotTestId('P1', $index)"
|
|
78165
|
-
cdkDropList
|
|
78166
|
-
[id]="battleSlotDropId($index)"
|
|
78167
|
-
[cdkDropListData]="$index"
|
|
78168
|
-
[cdkDropListConnectedTo]="['christianity-hand-source']"
|
|
78169
|
-
[cdkDropListEnterPredicate]="canDropOnBattleSlot"
|
|
78170
|
-
[cdkDropListSortingDisabled]="true"
|
|
78171
|
-
[class.christianity-slot--play-target]="canPlaceSelectedCharacter() || isDraggingCharacter()"
|
|
78376
|
+
class="christianity-secondary-action"
|
|
78172
78377
|
valLightRipple
|
|
78173
|
-
(
|
|
78174
|
-
(click)="playSelectedCard($index)"
|
|
78378
|
+
(click)="returnToChristianityHome()"
|
|
78175
78379
|
>
|
|
78176
|
-
|
|
78177
|
-
<span>{{ t('christianityPlayHere') }}</span>
|
|
78178
|
-
}
|
|
78380
|
+
{{ t('christianityBackToMenu') }}
|
|
78179
78381
|
</button>
|
|
78180
|
-
|
|
78181
|
-
|
|
78182
|
-
|
|
78183
|
-
|
|
78184
|
-
|
|
78185
|
-
|
|
78186
|
-
|
|
78187
|
-
|
|
78188
|
-
|
|
78189
|
-
|
|
78190
|
-
[
|
|
78191
|
-
[
|
|
78192
|
-
[
|
|
78193
|
-
[
|
|
78194
|
-
|
|
78382
|
+
</div>
|
|
78383
|
+
</section>
|
|
78384
|
+
}
|
|
78385
|
+
<div class="christianity-impact-layer">
|
|
78386
|
+
@if (combatTrail(); as trail) {
|
|
78387
|
+
<span
|
|
78388
|
+
class="christianity-combat-trail"
|
|
78389
|
+
aria-hidden="true"
|
|
78390
|
+
[class.is-leader-target]="trail.tone === 'leader'"
|
|
78391
|
+
[class.is-character-target]="trail.tone === 'character'"
|
|
78392
|
+
[style.--christianity-combat-trail-x]="trail.fromX"
|
|
78393
|
+
[style.--christianity-combat-trail-y]="trail.fromY"
|
|
78394
|
+
[style.--christianity-combat-trail-mid-x]="trail.midX"
|
|
78395
|
+
[style.--christianity-combat-trail-mid-y]="trail.midY"
|
|
78396
|
+
[style.--christianity-combat-trail-length]="trail.length"
|
|
78397
|
+
[style.--christianity-combat-trail-angle]="trail.angle"
|
|
78195
78398
|
>
|
|
78399
|
+
<span></span>
|
|
78400
|
+
</span>
|
|
78401
|
+
}
|
|
78402
|
+
@for (impact of impactEvents(); track impact.id) {
|
|
78403
|
+
<val-mini-game-score-pop [props]="impactPopProps(impact)" />
|
|
78404
|
+
}
|
|
78405
|
+
@if (combatCallout(); as callout) {
|
|
78406
|
+
<val-mini-game-callout [props]="callout" />
|
|
78407
|
+
}
|
|
78408
|
+
</div>
|
|
78409
|
+
<section class="christianity-player-side christianity-player-side--opponent">
|
|
78410
|
+
<section class="christianity-player-rack christianity-player-rack--opponent">
|
|
78411
|
+
<div class="christianity-offerings-zone">
|
|
78196
78412
|
<button
|
|
78197
78413
|
type="button"
|
|
78198
78414
|
class="christianity-offering-pile"
|
|
78199
|
-
data-testid="christianity-offerings-
|
|
78200
|
-
[class.is-empty-zone]="!topOffering('
|
|
78415
|
+
data-testid="christianity-offerings-P2"
|
|
78416
|
+
[class.is-empty-zone]="!topOffering('P2')"
|
|
78201
78417
|
valLightRipple
|
|
78202
|
-
(click)="
|
|
78418
|
+
(click)="openOfferings('P2')"
|
|
78203
78419
|
>
|
|
78204
|
-
@if (offeringStack('
|
|
78420
|
+
@if (offeringStack('P2').length) {
|
|
78205
78421
|
<span class="christianity-zone-card-stack" aria-hidden="true">
|
|
78206
|
-
@for (offering of offeringStack('
|
|
78422
|
+
@for (offering of offeringStack('P2'); track offering.instanceId) {
|
|
78207
78423
|
<val-christianity-card
|
|
78208
78424
|
[card]="offering.ready ? offeringRenderCard(offering) : hiddenCardRenderCard()"
|
|
78209
78425
|
[variant]="offering.ready ? 'baby' : 'back'"
|
|
78210
|
-
[style.transform]="zoneStackTransform($index, offeringStack('
|
|
78426
|
+
[style.transform]="zoneStackTransform($index, offeringStack('P2').length)"
|
|
78211
78427
|
></val-christianity-card>
|
|
78212
78428
|
}
|
|
78213
78429
|
</span>
|
|
@@ -78215,89 +78431,358 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78215
78431
|
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
78216
78432
|
}
|
|
78217
78433
|
<span>{{ t('christianityOfferingReserve') }}</span>
|
|
78218
|
-
<strong>{{ readyOfferings(
|
|
78219
|
-
<small>{{ t('christianityOfferingBase') }} {{ totalOfferings(
|
|
78434
|
+
<strong>{{ readyOfferings(opponent()) }}</strong>
|
|
78435
|
+
<small>{{ t('christianityOfferingBase') }} {{ totalOfferings(opponent()) }}</small>
|
|
78220
78436
|
</button>
|
|
78221
78437
|
</div>
|
|
78222
|
-
|
|
78223
|
-
|
|
78224
|
-
|
|
78225
|
-
|
|
78226
|
-
|
|
78227
|
-
|
|
78228
|
-
|
|
78229
|
-
|
|
78438
|
+
<div
|
|
78439
|
+
class="christianity-attack-drop-target"
|
|
78440
|
+
cdkDropList
|
|
78441
|
+
id="christianity-opponent-leader-drop"
|
|
78442
|
+
[cdkDropListConnectedTo]="ownAttackerDropSourceIds()"
|
|
78443
|
+
[cdkDropListEnterPredicate]="canDropOnOpponentLeader"
|
|
78444
|
+
[cdkDropListSortingDisabled]="true"
|
|
78445
|
+
(cdkDropListDropped)="dropOnOpponentLeader($event)"
|
|
78446
|
+
>
|
|
78447
|
+
<button
|
|
78448
|
+
type="button"
|
|
78449
|
+
class="christianity-leader-card christianity-render-card-button"
|
|
78450
|
+
data-testid="christianity-leader-P2"
|
|
78451
|
+
valLightRipple
|
|
78452
|
+
[class.is-target]="isOpponentLeaderTarget()"
|
|
78453
|
+
[class.is-protected-target]="selectedAttacker() && hasOpponentGuards()"
|
|
78454
|
+
[class.is-combat-target]="isCombatLeaderTarget('P2')"
|
|
78455
|
+
(click)="handleOpponentLeader()"
|
|
78456
|
+
>
|
|
78457
|
+
<val-christianity-card [card]="leaderRenderCard(opponent())" variant="board"></val-christianity-card>
|
|
78458
|
+
</button>
|
|
78230
78459
|
</div>
|
|
78231
|
-
|
|
78460
|
+
<span class="christianity-rack-spacer" aria-hidden="true"></span>
|
|
78461
|
+
</section>
|
|
78462
|
+
|
|
78463
|
+
<section
|
|
78464
|
+
class="christianity-battle-zone christianity-battle-zone--opponent"
|
|
78465
|
+
data-testid="christianity-battle-P2"
|
|
78466
|
+
[attr.aria-label]="t('christianityOpponentBattle')"
|
|
78467
|
+
>
|
|
78468
|
+
@for (slot of battleSlots('P2'); track slot.trackId) {
|
|
78469
|
+
@if (slot.card) {
|
|
78470
|
+
<button
|
|
78471
|
+
type="button"
|
|
78472
|
+
class="christianity-card-preview-card christianity-card-preview-card--battle christianity-render-card-button"
|
|
78473
|
+
[attr.data-testid]="battleCardTestId('P2', slot.card)"
|
|
78474
|
+
cdkDropList
|
|
78475
|
+
[id]="opponentTargetDropId(slot.card)"
|
|
78476
|
+
[cdkDropListConnectedTo]="ownAttackerDropSourceIds()"
|
|
78477
|
+
[cdkDropListEnterPredicate]="canDropOnOpponentCharacter"
|
|
78478
|
+
[cdkDropListSortingDisabled]="true"
|
|
78479
|
+
valLightRipple
|
|
78480
|
+
[class.is-target]="isOpponentCharacterTarget(slot.card)"
|
|
78481
|
+
[class.is-combat-target]="isCombatCharacterTarget(slot.card)"
|
|
78482
|
+
(cdkDropListDropped)="dropOnOpponentCharacter($event, slot.card)"
|
|
78483
|
+
(click)="handleOpponentCharacter(slot.card)"
|
|
78484
|
+
>
|
|
78485
|
+
<val-christianity-card
|
|
78486
|
+
[card]="characterRenderCard(slot.card)"
|
|
78487
|
+
variant="board"
|
|
78488
|
+
></val-christianity-card>
|
|
78489
|
+
</button>
|
|
78490
|
+
} @else {
|
|
78491
|
+
<span class="christianity-slot"></span>
|
|
78492
|
+
}
|
|
78493
|
+
}
|
|
78494
|
+
</section>
|
|
78232
78495
|
</section>
|
|
78233
|
-
</section>
|
|
78234
|
-
</section>
|
|
78235
78496
|
|
|
78236
|
-
|
|
78237
|
-
|
|
78238
|
-
|
|
78239
|
-
|
|
78240
|
-
|
|
78241
|
-
|
|
78242
|
-
|
|
78243
|
-
|
|
78244
|
-
|
|
78245
|
-
|
|
78246
|
-
|
|
78247
|
-
|
|
78248
|
-
|
|
78249
|
-
|
|
78250
|
-
|
|
78251
|
-
|
|
78252
|
-
|
|
78253
|
-
|
|
78254
|
-
|
|
78255
|
-
|
|
78256
|
-
|
|
78257
|
-
|
|
78258
|
-
|
|
78259
|
-
|
|
78260
|
-
|
|
78497
|
+
<section
|
|
78498
|
+
class="christianity-shared-zone"
|
|
78499
|
+
data-testid="christianity-shared-zone"
|
|
78500
|
+
[attr.aria-label]="t('christianitySharedZone')"
|
|
78501
|
+
>
|
|
78502
|
+
<button
|
|
78503
|
+
type="button"
|
|
78504
|
+
class="christianity-zone-pile christianity-zone-pile--history"
|
|
78505
|
+
data-testid="christianity-history-zone"
|
|
78506
|
+
[class.is-empty-zone]="!topHistoryCard()"
|
|
78507
|
+
[class.has-new-card]="historyPulse()"
|
|
78508
|
+
valLightRipple
|
|
78509
|
+
(click)="openHistory()"
|
|
78510
|
+
>
|
|
78511
|
+
@if (historyStack().length) {
|
|
78512
|
+
<span class="christianity-zone-card-stack" aria-hidden="true">
|
|
78513
|
+
@for (cardId of historyStack(); track cardId + $index) {
|
|
78514
|
+
<val-christianity-card
|
|
78515
|
+
[card]="definitionToRenderCard(cardDefinition(cardId), { statusText: t('christianityHistory') })"
|
|
78516
|
+
variant="baby"
|
|
78517
|
+
[style.transform]="zoneStackTransform($index, historyStack().length)"
|
|
78518
|
+
></val-christianity-card>
|
|
78519
|
+
}
|
|
78520
|
+
</span>
|
|
78521
|
+
} @else {
|
|
78522
|
+
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
78523
|
+
}
|
|
78524
|
+
<span>{{ t('christianityHistory') }}</span>
|
|
78525
|
+
<strong>{{ game().historyZone.length }}</strong>
|
|
78526
|
+
</button>
|
|
78527
|
+
<button
|
|
78528
|
+
type="button"
|
|
78529
|
+
class="christianity-zone-pile christianity-zone-pile--deck"
|
|
78530
|
+
data-testid="christianity-deck-zone"
|
|
78531
|
+
valLightRipple
|
|
78532
|
+
aria-live="polite"
|
|
78533
|
+
(click)="inspectDeck()"
|
|
78534
|
+
>
|
|
78535
|
+
<span class="christianity-pile-card-hint christianity-pile-card-hint--deck" aria-hidden="true">
|
|
78536
|
+
<i></i>
|
|
78537
|
+
</span>
|
|
78538
|
+
<span>{{ t('christianityDeck') }}</span>
|
|
78539
|
+
<strong>{{ game().sharedDeck.length }}</strong>
|
|
78540
|
+
</button>
|
|
78541
|
+
<button
|
|
78542
|
+
type="button"
|
|
78543
|
+
class="christianity-zone-card christianity-zone-card--place christianity-render-card-button"
|
|
78544
|
+
data-testid="christianity-place-zone"
|
|
78545
|
+
cdkDropList
|
|
78546
|
+
id="christianity-place-drop"
|
|
78547
|
+
[cdkDropListConnectedTo]="['christianity-hand-source']"
|
|
78548
|
+
[cdkDropListEnterPredicate]="canDropOnPlace"
|
|
78549
|
+
[cdkDropListSortingDisabled]="true"
|
|
78550
|
+
[class.is-empty-zone]="!activePlaceCard()"
|
|
78551
|
+
[class.is-play-target]="canPlaceSelectedPlace() || isDraggingPlace()"
|
|
78552
|
+
valLightRipple
|
|
78553
|
+
(cdkDropListDropped)="dropOnPlace($event)"
|
|
78554
|
+
(click)="playSelectedPlaceOrInspect()"
|
|
78261
78555
|
>
|
|
78556
|
+
@if (placeStack().length) {
|
|
78557
|
+
@if (activePlaceCard(); as placeCard) {
|
|
78558
|
+
<div
|
|
78559
|
+
class="christianity-place-backdrop"
|
|
78560
|
+
[style.background-image]="placeBackdropImage(placeCard)"
|
|
78561
|
+
aria-hidden="true"
|
|
78562
|
+
></div>
|
|
78563
|
+
}
|
|
78564
|
+
<span class="christianity-zone-card-stack" aria-hidden="true">
|
|
78565
|
+
@for (cardId of placeStack(); track cardId + $index) {
|
|
78566
|
+
<val-christianity-card
|
|
78567
|
+
[card]="definitionToRenderCard(cardDefinition(cardId), { statusText: t('christianityPlace') })"
|
|
78568
|
+
variant="baby"
|
|
78569
|
+
[style.transform]="zoneStackTransform($index, placeStack().length)"
|
|
78570
|
+
></val-christianity-card>
|
|
78571
|
+
}
|
|
78572
|
+
</span>
|
|
78573
|
+
} @else {
|
|
78574
|
+
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
78575
|
+
}
|
|
78576
|
+
<span>{{ t('christianityPlace') }}</span>
|
|
78577
|
+
<strong>{{ game().placeZone.length }}</strong>
|
|
78578
|
+
@if (canPlaceSelectedPlace() || isDraggingPlace()) {
|
|
78579
|
+
<em>{{ t('christianityPlayHere') }}</em>
|
|
78580
|
+
}
|
|
78581
|
+
</button>
|
|
78582
|
+
</section>
|
|
78583
|
+
|
|
78584
|
+
<section class="christianity-player-side">
|
|
78585
|
+
<section
|
|
78586
|
+
class="christianity-battle-zone"
|
|
78587
|
+
data-testid="christianity-battle-P1"
|
|
78588
|
+
cdkDropList
|
|
78589
|
+
id="christianity-player-battle-source"
|
|
78590
|
+
[cdkDropListConnectedTo]="attackTargetDropIds()"
|
|
78591
|
+
[cdkDropListSortingDisabled]="true"
|
|
78592
|
+
[class.is-placing-card]="canPlaceSelectedCharacter() || isDraggingCharacter()"
|
|
78593
|
+
[attr.aria-label]="t('christianityYourBattle')"
|
|
78594
|
+
>
|
|
78595
|
+
@for (slot of battleSlots('P1'); track slot.trackId) {
|
|
78596
|
+
@if (slot.card) {
|
|
78597
|
+
<button
|
|
78598
|
+
type="button"
|
|
78599
|
+
class="christianity-card-preview-card christianity-card-preview-card--battle christianity-render-card-button"
|
|
78600
|
+
[attr.data-testid]="battleCardTestId('P1', slot.card)"
|
|
78601
|
+
cdkDrag
|
|
78602
|
+
[cdkDragData]="slot.card.instanceId"
|
|
78603
|
+
[cdkDragDisabled]="!canDragAttacker(slot.card)"
|
|
78604
|
+
valLightRipple
|
|
78605
|
+
[class.is-selected]="selectedAttacker()?.instanceId === slot.card.instanceId"
|
|
78606
|
+
[class.is-exhausted]="!slot.card.canAttack"
|
|
78607
|
+
[class.is-ready-attacker]="isOwnTurn() && slot.card.canAttack"
|
|
78608
|
+
[class.is-combat-attacker]="isCombatAttacker(slot.card)"
|
|
78609
|
+
(cdkDragStarted)="startDraggingAttacker(slot.card)"
|
|
78610
|
+
(cdkDragEnded)="endDraggingAttacker()"
|
|
78611
|
+
(click)="selectAttacker(slot.card)"
|
|
78612
|
+
>
|
|
78613
|
+
<val-christianity-card
|
|
78614
|
+
[card]="characterRenderCard(slot.card)"
|
|
78615
|
+
variant="board"
|
|
78616
|
+
></val-christianity-card>
|
|
78617
|
+
<ng-template cdkDragPreview>
|
|
78618
|
+
<div class="christianity-card-drag-preview">
|
|
78619
|
+
<val-christianity-card
|
|
78620
|
+
[card]="characterRenderCard(slot.card)"
|
|
78621
|
+
variant="board"
|
|
78622
|
+
></val-christianity-card>
|
|
78623
|
+
</div>
|
|
78624
|
+
</ng-template>
|
|
78625
|
+
<ng-template cdkDragPlaceholder>
|
|
78626
|
+
<div class="christianity-card-drag-placeholder"></div>
|
|
78627
|
+
</ng-template>
|
|
78628
|
+
</button>
|
|
78629
|
+
} @else {
|
|
78630
|
+
<button
|
|
78631
|
+
type="button"
|
|
78632
|
+
class="christianity-slot"
|
|
78633
|
+
[attr.data-testid]="battleSlotTestId('P1', $index)"
|
|
78634
|
+
cdkDropList
|
|
78635
|
+
[id]="battleSlotDropId($index)"
|
|
78636
|
+
[cdkDropListData]="$index"
|
|
78637
|
+
[cdkDropListConnectedTo]="['christianity-hand-source']"
|
|
78638
|
+
[cdkDropListEnterPredicate]="canDropOnBattleSlot"
|
|
78639
|
+
[cdkDropListSortingDisabled]="true"
|
|
78640
|
+
[class.christianity-slot--play-target]="canPlaceSelectedCharacter() || isDraggingCharacter()"
|
|
78641
|
+
valLightRipple
|
|
78642
|
+
(cdkDropListDropped)="dropOnBattleSlot($event, $index)"
|
|
78643
|
+
(click)="playSelectedCard($index)"
|
|
78644
|
+
>
|
|
78645
|
+
@if (canPlaceSelectedCharacter() || isDraggingCharacter()) {
|
|
78646
|
+
<span>{{ t('christianityPlayHere') }}</span>
|
|
78647
|
+
}
|
|
78648
|
+
</button>
|
|
78649
|
+
}
|
|
78650
|
+
}
|
|
78651
|
+
</section>
|
|
78652
|
+
|
|
78653
|
+
<section class="christianity-player-rack">
|
|
78654
|
+
<div class="christianity-offerings-zone">
|
|
78655
|
+
<div
|
|
78656
|
+
class="christianity-offering-drop-target"
|
|
78657
|
+
cdkDropList
|
|
78658
|
+
id="christianity-offerings-drop"
|
|
78659
|
+
[cdkDropListConnectedTo]="['christianity-hand-source']"
|
|
78660
|
+
[class.is-play-target]="canPlaceSelectedOffering() || isDraggingOffering()"
|
|
78661
|
+
[cdkDropListEnterPredicate]="canDropOnOfferings"
|
|
78662
|
+
[cdkDropListSortingDisabled]="true"
|
|
78663
|
+
(cdkDropListDropped)="dropOnOfferings($event)"
|
|
78664
|
+
>
|
|
78665
|
+
<button
|
|
78666
|
+
type="button"
|
|
78667
|
+
class="christianity-offering-pile"
|
|
78668
|
+
data-testid="christianity-offerings-P1"
|
|
78669
|
+
[class.is-empty-zone]="!topOffering('P1')"
|
|
78670
|
+
valLightRipple
|
|
78671
|
+
(click)="handleOfferingPile('P1')"
|
|
78672
|
+
>
|
|
78673
|
+
@if (offeringStack('P1').length) {
|
|
78674
|
+
<span class="christianity-zone-card-stack" aria-hidden="true">
|
|
78675
|
+
@for (offering of offeringStack('P1'); track offering.instanceId) {
|
|
78676
|
+
<val-christianity-card
|
|
78677
|
+
[card]="offering.ready ? offeringRenderCard(offering) : hiddenCardRenderCard()"
|
|
78678
|
+
[variant]="offering.ready ? 'baby' : 'back'"
|
|
78679
|
+
[style.transform]="zoneStackTransform($index, offeringStack('P1').length)"
|
|
78680
|
+
></val-christianity-card>
|
|
78681
|
+
}
|
|
78682
|
+
</span>
|
|
78683
|
+
} @else {
|
|
78684
|
+
<span class="christianity-empty-card-slot" aria-hidden="true"></span>
|
|
78685
|
+
}
|
|
78686
|
+
<span>{{ t('christianityOfferingReserve') }}</span>
|
|
78687
|
+
<strong>{{ readyOfferings(player()) }}</strong>
|
|
78688
|
+
<small>{{ t('christianityOfferingBase') }} {{ totalOfferings(player()) }}</small>
|
|
78689
|
+
</button>
|
|
78690
|
+
</div>
|
|
78691
|
+
</div>
|
|
78262
78692
|
<button
|
|
78263
78693
|
type="button"
|
|
78264
|
-
class="christianity-
|
|
78265
|
-
|
|
78266
|
-
cdkDrag
|
|
78694
|
+
class="christianity-leader-card christianity-render-card-button"
|
|
78695
|
+
data-testid="christianity-leader-P1"
|
|
78267
78696
|
valLightRipple
|
|
78268
|
-
|
|
78269
|
-
[cdkDragDisabled]="!canPlay(card)"
|
|
78270
|
-
[attr.aria-label]="handCardActionLabel(card)"
|
|
78271
|
-
[class.is-selected]="selectedHandCard() === cardId"
|
|
78272
|
-
[class.is-disabled]="!canPlay(card)"
|
|
78273
|
-
(cdkDragStarted)="startDraggingCard(cardId)"
|
|
78274
|
-
(cdkDragEnded)="endDraggingCard()"
|
|
78275
|
-
(click)="selectHandCard(cardId)"
|
|
78697
|
+
(click)="inspectLeader('P1')"
|
|
78276
78698
|
>
|
|
78277
|
-
<val-christianity-card [card]="
|
|
78278
|
-
<ng-template cdkDragPreview>
|
|
78279
|
-
<div class="christianity-card-drag-preview">
|
|
78280
|
-
<val-christianity-card [card]="definitionToRenderCard(card)" variant="baby"></val-christianity-card>
|
|
78281
|
-
</div>
|
|
78282
|
-
</ng-template>
|
|
78283
|
-
<ng-template cdkDragPlaceholder>
|
|
78284
|
-
<div class="christianity-card-drag-placeholder"></div>
|
|
78285
|
-
</ng-template>
|
|
78699
|
+
<val-christianity-card [card]="leaderRenderCard(player())" variant="board"></val-christianity-card>
|
|
78286
78700
|
</button>
|
|
78287
|
-
<
|
|
78288
|
-
|
|
78289
|
-
|
|
78290
|
-
|
|
78291
|
-
|
|
78292
|
-
|
|
78293
|
-
|
|
78294
|
-
|
|
78701
|
+
<div class="christianity-player-command">
|
|
78702
|
+
<div class="christianity-player-badge">
|
|
78703
|
+
<span class="christianity-avatar" [style.background]="player().avatarColor">{{
|
|
78704
|
+
player().avatar
|
|
78705
|
+
}}</span>
|
|
78706
|
+
<strong>{{ player().displayName }}</strong>
|
|
78707
|
+
</div>
|
|
78708
|
+
</div>
|
|
78709
|
+
</section>
|
|
78710
|
+
</section>
|
|
78711
|
+
</section>
|
|
78712
|
+
|
|
78713
|
+
<section class="christianity-hand-shelf">
|
|
78714
|
+
<div class="christianity-hand-meter">
|
|
78715
|
+
<span>{{ t('christianityHand') }}</span>
|
|
78716
|
+
<strong>{{ player().hand?.length ?? 0 }}</strong>
|
|
78717
|
+
</div>
|
|
78718
|
+
<section
|
|
78719
|
+
class="christianity-hand-fan"
|
|
78720
|
+
data-testid="christianity-hand-P1"
|
|
78721
|
+
cdkDropList
|
|
78722
|
+
id="christianity-hand-source"
|
|
78723
|
+
[cdkDropListConnectedTo]="dropTargetIds()"
|
|
78724
|
+
[attr.aria-label]="t('christianityYourHand')"
|
|
78725
|
+
(pointerleave)="clearHoveredHandIndex()"
|
|
78726
|
+
>
|
|
78727
|
+
@for (cardId of player().hand ?? []; track cardId + $index) {
|
|
78728
|
+
@let card = cardDefinition(cardId);
|
|
78729
|
+
<div
|
|
78730
|
+
class="christianity-hand-card-wrap"
|
|
78731
|
+
[class.is-selected]="selectedHandCard() === cardId"
|
|
78732
|
+
[class.is-dragging]="draggingCardId() === cardId"
|
|
78733
|
+
[style.z-index]="handCardZIndex($index)"
|
|
78734
|
+
[style.transform]="fanTransform($index, player().hand?.length ?? 0, false)"
|
|
78735
|
+
(pointerenter)="setHoveredHandIndex($index)"
|
|
78736
|
+
(pointerdown)="setHoveredHandIndex($index)"
|
|
78737
|
+
(pointerup)="releaseHoveredHand($event)"
|
|
78738
|
+
>
|
|
78739
|
+
<button
|
|
78740
|
+
type="button"
|
|
78741
|
+
class="christianity-card-preview-card christianity-card-preview-card--hand christianity-render-card-button"
|
|
78742
|
+
[attr.data-testid]="handCardTestId(cardId, $index)"
|
|
78743
|
+
cdkDrag
|
|
78744
|
+
valLightRipple
|
|
78745
|
+
[cdkDragData]="cardId"
|
|
78746
|
+
[cdkDragDisabled]="!canPlay(card)"
|
|
78747
|
+
[attr.aria-label]="handCardActionLabel(card)"
|
|
78748
|
+
[class.is-selected]="selectedHandCard() === cardId"
|
|
78749
|
+
[class.is-disabled]="!canPlay(card)"
|
|
78750
|
+
(cdkDragStarted)="startDraggingCard(cardId)"
|
|
78751
|
+
(cdkDragEnded)="endDraggingCard()"
|
|
78752
|
+
(click)="selectHandCard(cardId)"
|
|
78753
|
+
>
|
|
78754
|
+
<val-christianity-card [card]="definitionToRenderCard(card)" variant="baby"></val-christianity-card>
|
|
78755
|
+
<ng-template cdkDragPreview>
|
|
78756
|
+
<div class="christianity-card-drag-preview">
|
|
78757
|
+
<val-christianity-card
|
|
78758
|
+
[card]="definitionToRenderCard(card)"
|
|
78759
|
+
variant="baby"
|
|
78760
|
+
></val-christianity-card>
|
|
78761
|
+
</div>
|
|
78762
|
+
</ng-template>
|
|
78763
|
+
<ng-template cdkDragPlaceholder>
|
|
78764
|
+
<div class="christianity-card-drag-placeholder"></div>
|
|
78765
|
+
</ng-template>
|
|
78766
|
+
</button>
|
|
78767
|
+
<button
|
|
78768
|
+
type="button"
|
|
78769
|
+
class="christianity-card-eye"
|
|
78770
|
+
[attr.aria-label]="t('christianityPreviewCard')"
|
|
78771
|
+
(click)="inspectHandCard(cardId, true); $event.stopPropagation()"
|
|
78772
|
+
></button>
|
|
78773
|
+
</div>
|
|
78774
|
+
}
|
|
78775
|
+
</section>
|
|
78295
78776
|
</section>
|
|
78296
|
-
</section>
|
|
78297
78777
|
}
|
|
78298
78778
|
|
|
78299
78779
|
@if (selectedPreview()) {
|
|
78300
|
-
<button
|
|
78780
|
+
<button
|
|
78781
|
+
type="button"
|
|
78782
|
+
class="christianity-preview-backdrop"
|
|
78783
|
+
[attr.aria-label]="t('christianityClosePreview')"
|
|
78784
|
+
(click)="closePreview()"
|
|
78785
|
+
></button>
|
|
78301
78786
|
<aside
|
|
78302
78787
|
class="christianity-floating-card-shell"
|
|
78303
78788
|
[class.is-history-preview]="canNavigatePreview()"
|
|
@@ -78337,7 +78822,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78337
78822
|
</button>
|
|
78338
78823
|
}
|
|
78339
78824
|
@if (selectedPreviewNeighborRenderCard(-1); as previousCard) {
|
|
78340
|
-
<val-christianity-card
|
|
78825
|
+
<val-christianity-card
|
|
78826
|
+
class="christianity-preview-ghost christianity-preview-ghost--previous"
|
|
78827
|
+
[card]="previousCard"
|
|
78828
|
+
variant="full"
|
|
78829
|
+
></val-christianity-card>
|
|
78341
78830
|
}
|
|
78342
78831
|
<div
|
|
78343
78832
|
class="christianity-floating-card"
|
|
@@ -78356,7 +78845,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78356
78845
|
}
|
|
78357
78846
|
</div>
|
|
78358
78847
|
@if (selectedPreviewNeighborRenderCard(1); as nextCard) {
|
|
78359
|
-
<val-christianity-card
|
|
78848
|
+
<val-christianity-card
|
|
78849
|
+
class="christianity-preview-ghost christianity-preview-ghost--next"
|
|
78850
|
+
[card]="nextCard"
|
|
78851
|
+
variant="full"
|
|
78852
|
+
></val-christianity-card>
|
|
78360
78853
|
}
|
|
78361
78854
|
</div>
|
|
78362
78855
|
<div class="christianity-preview-side">
|
|
@@ -78440,7 +78933,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78440
78933
|
}
|
|
78441
78934
|
|
|
78442
78935
|
@if (selectedInfo(); as info) {
|
|
78443
|
-
<button
|
|
78936
|
+
<button
|
|
78937
|
+
type="button"
|
|
78938
|
+
class="christianity-info-backdrop"
|
|
78939
|
+
[attr.aria-label]="t('close')"
|
|
78940
|
+
(click)="closeInfo()"
|
|
78941
|
+
></button>
|
|
78444
78942
|
<aside class="christianity-info-panel" aria-live="polite">
|
|
78445
78943
|
<button type="button" class="christianity-dialog-close christianity-info-close" (click)="closeInfo()">
|
|
78446
78944
|
{{ t('close') }}
|
|
@@ -78465,14 +78963,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78465
78963
|
@if (screen() === 'table') {
|
|
78466
78964
|
<section class="christianity-actions" data-testid="christianity-actions" aria-live="polite">
|
|
78467
78965
|
<p class="christianity-sr-only" data-testid="christianity-status">{{ statusText() }}</p>
|
|
78468
|
-
<button
|
|
78966
|
+
<button
|
|
78967
|
+
type="button"
|
|
78968
|
+
data-testid="christianity-primary-action"
|
|
78969
|
+
[disabled]="tutorialPhase() !== 'in_progress' || selectedActionDisabled()"
|
|
78970
|
+
(click)="playSelectedCard()"
|
|
78971
|
+
>
|
|
78469
78972
|
{{ selectedActionLabel() }}
|
|
78470
78973
|
</button>
|
|
78471
78974
|
</section>
|
|
78472
78975
|
}
|
|
78473
78976
|
|
|
78474
78977
|
@if (showHistory()) {
|
|
78475
|
-
<button
|
|
78978
|
+
<button
|
|
78979
|
+
type="button"
|
|
78980
|
+
class="christianity-history-backdrop"
|
|
78981
|
+
[attr.aria-label]="t('christianityCloseHistory')"
|
|
78982
|
+
(click)="closeHistory()"
|
|
78983
|
+
></button>
|
|
78476
78984
|
<section class="christianity-history-drawer" data-testid="christianity-history-drawer">
|
|
78477
78985
|
<header>
|
|
78478
78986
|
<h2>{{ t('christianityHistory') }}</h2>
|
|
@@ -78487,7 +78995,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78487
78995
|
<div class="christianity-history-grid" data-testid="christianity-history-grid">
|
|
78488
78996
|
@for (cardId of game().historyZone; track cardId + $index) {
|
|
78489
78997
|
@let card = cardDefinition(cardId);
|
|
78490
|
-
<button
|
|
78998
|
+
<button
|
|
78999
|
+
type="button"
|
|
79000
|
+
class="christianity-gallery-card-button christianity-render-card-button"
|
|
79001
|
+
[attr.data-testid]="historyCardTestId(cardId, $index)"
|
|
79002
|
+
valLightRipple
|
|
79003
|
+
(click)="inspectHistoryCard(cardId)"
|
|
79004
|
+
>
|
|
78491
79005
|
<val-christianity-card [card]="definitionToRenderCard(card)" variant="baby"></val-christianity-card>
|
|
78492
79006
|
</button>
|
|
78493
79007
|
}
|
|
@@ -78499,7 +79013,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78499
79013
|
}
|
|
78500
79014
|
|
|
78501
79015
|
@if (showPlace()) {
|
|
78502
|
-
<button
|
|
79016
|
+
<button
|
|
79017
|
+
type="button"
|
|
79018
|
+
class="christianity-history-backdrop"
|
|
79019
|
+
[attr.aria-label]="t('christianityCloseHistory')"
|
|
79020
|
+
(click)="closePlace()"
|
|
79021
|
+
></button>
|
|
78503
79022
|
<section class="christianity-history-drawer christianity-place-drawer" data-testid="christianity-place-drawer">
|
|
78504
79023
|
<header>
|
|
78505
79024
|
<h2>{{ t('christianityPlace') }}</h2>
|
|
@@ -78512,8 +79031,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78512
79031
|
</header>
|
|
78513
79032
|
<div class="christianity-history-grid" data-testid="christianity-place-grid">
|
|
78514
79033
|
@for (cardId of game().placeZone; track cardId + $index) {
|
|
78515
|
-
<button
|
|
78516
|
-
|
|
79034
|
+
<button
|
|
79035
|
+
type="button"
|
|
79036
|
+
class="christianity-gallery-card-button christianity-render-card-button"
|
|
79037
|
+
[attr.data-testid]="'christianity-place-card-' + $index"
|
|
79038
|
+
valLightRipple
|
|
79039
|
+
(click)="inspectPlaceCard(cardId)"
|
|
79040
|
+
>
|
|
79041
|
+
<val-christianity-card
|
|
79042
|
+
[card]="definitionToRenderCard(cardDefinition(cardId), { statusText: t('christianityPlace') })"
|
|
79043
|
+
variant="baby"
|
|
79044
|
+
></val-christianity-card>
|
|
78517
79045
|
</button>
|
|
78518
79046
|
}
|
|
78519
79047
|
</div>
|
|
@@ -78521,8 +79049,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78521
79049
|
}
|
|
78522
79050
|
|
|
78523
79051
|
@if (showGallery()) {
|
|
78524
|
-
<button
|
|
78525
|
-
|
|
79052
|
+
<button
|
|
79053
|
+
type="button"
|
|
79054
|
+
class="christianity-history-backdrop christianity-gallery-backdrop"
|
|
79055
|
+
[attr.aria-label]="t('christianityCloseGallery')"
|
|
79056
|
+
(click)="closeGallery()"
|
|
79057
|
+
></button>
|
|
79058
|
+
<section
|
|
79059
|
+
class="christianity-history-drawer christianity-gallery-drawer"
|
|
79060
|
+
data-testid="christianity-gallery-drawer"
|
|
79061
|
+
>
|
|
78526
79062
|
<header>
|
|
78527
79063
|
<div>
|
|
78528
79064
|
<h2>{{ t('christianityGallery') }}</h2>
|
|
@@ -78538,7 +79074,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78538
79074
|
<div class="christianity-gallery-controls">
|
|
78539
79075
|
<label>
|
|
78540
79076
|
<span>{{ t('christianityGallerySearch') }}</span>
|
|
78541
|
-
<input
|
|
79077
|
+
<input
|
|
79078
|
+
type="search"
|
|
79079
|
+
[value]="gallerySearch()"
|
|
79080
|
+
(input)="setGallerySearch($event)"
|
|
79081
|
+
[placeholder]="t('christianityGallerySearchPlaceholder')"
|
|
79082
|
+
/>
|
|
78542
79083
|
</label>
|
|
78543
79084
|
<label>
|
|
78544
79085
|
<span>{{ t('christianityGalleryFilter') }}</span>
|
|
@@ -78557,7 +79098,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78557
79098
|
</div>
|
|
78558
79099
|
<div class="christianity-gallery-grid">
|
|
78559
79100
|
@for (card of galleryCards(); track card.id) {
|
|
78560
|
-
<button
|
|
79101
|
+
<button
|
|
79102
|
+
type="button"
|
|
79103
|
+
class="christianity-gallery-card-button christianity-render-card-button"
|
|
79104
|
+
valLightRipple
|
|
79105
|
+
(click)="inspectGalleryCard(card.id)"
|
|
79106
|
+
>
|
|
78561
79107
|
<val-christianity-card [card]="definitionToRenderCard(card)" variant="baby"></val-christianity-card>
|
|
78562
79108
|
</button>
|
|
78563
79109
|
} @empty {
|
|
@@ -78569,12 +79115,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78569
79115
|
|
|
78570
79116
|
@if (offeringsSeat()) {
|
|
78571
79117
|
@let offeringPlayer = game().players[offeringsSeat()!];
|
|
78572
|
-
<button
|
|
78573
|
-
|
|
79118
|
+
<button
|
|
79119
|
+
type="button"
|
|
79120
|
+
class="christianity-history-backdrop"
|
|
79121
|
+
[attr.aria-label]="t('christianityCloseOfferings')"
|
|
79122
|
+
(click)="closeOfferings()"
|
|
79123
|
+
></button>
|
|
79124
|
+
<section
|
|
79125
|
+
class="christianity-history-drawer christianity-offerings-drawer"
|
|
79126
|
+
[attr.data-testid]="offeringsDrawerTestId(offeringsSeat()!)"
|
|
79127
|
+
>
|
|
78574
79128
|
<header>
|
|
78575
79129
|
<h2>{{ t('christianityOfferings') }}</h2>
|
|
78576
79130
|
<div class="christianity-dialog-actions">
|
|
78577
|
-
<span
|
|
79131
|
+
<span
|
|
79132
|
+
>{{ t('christianityOfferingReserve') }} {{ readyOfferings(offeringPlayer) }} ·
|
|
79133
|
+
{{ t('christianityOfferingBase') }} {{ totalOfferings(offeringPlayer) }}</span
|
|
79134
|
+
>
|
|
78578
79135
|
<button type="button" class="christianity-dialog-close" (click)="closeOfferings()">
|
|
78579
79136
|
{{ t('close') }}
|
|
78580
79137
|
</button>
|
|
@@ -78584,14 +79141,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
78584
79141
|
<span class="christianity-rule-note-icon" aria-hidden="true">i</span>
|
|
78585
79142
|
<p>{{ t('christianityOfferingsRuleBody') }}</p>
|
|
78586
79143
|
</div>
|
|
78587
|
-
|
|
78588
|
-
|
|
78589
|
-
|
|
78590
|
-
<button
|
|
78591
|
-
|
|
79144
|
+
<div class="christianity-offering-list" [attr.data-testid]="offeringListTestId(offeringsSeat()!)">
|
|
79145
|
+
@for (offering of offeringPlayer.offerings; track offering.instanceId) {
|
|
79146
|
+
<article class="christianity-offering-row" [class.is-exhausted]="!offering.ready">
|
|
79147
|
+
<button
|
|
79148
|
+
type="button"
|
|
79149
|
+
class="christianity-offering-card christianity-render-card-button"
|
|
79150
|
+
[attr.data-testid]="offeringCardTestId(offering)"
|
|
79151
|
+
valLightRipple
|
|
79152
|
+
(click)="inspectOffering(offering)"
|
|
79153
|
+
>
|
|
79154
|
+
<val-christianity-card
|
|
79155
|
+
[card]="offering.ready ? offeringRenderCard(offering) : hiddenCardRenderCard()"
|
|
79156
|
+
[variant]="offering.ready ? 'baby' : 'back'"
|
|
79157
|
+
></val-christianity-card>
|
|
78592
79158
|
</button>
|
|
78593
79159
|
<div>
|
|
78594
|
-
<strong>{{
|
|
79160
|
+
<strong>{{
|
|
79161
|
+
offering.ready ? t('christianityOfferingReady') : t('christianityOfferingExhausted')
|
|
79162
|
+
}}</strong>
|
|
78595
79163
|
<p>{{ offeringAbilityText(offering) }}</p>
|
|
78596
79164
|
@if (offering.abilityName) {
|
|
78597
79165
|
<button
|