Skip to content

Commit d9b9ec0

Browse files
committed
Add timeout amount feature
1 parent d23fc22 commit d9b9ec0

File tree

11 files changed

+163
-14
lines changed

11 files changed

+163
-14
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "spectra-frontend",
3-
"version": "0.3.0",
3+
"version": "0.3.1",
44
"author": {
55
"name": "Purple Shark UG (haftungsbeschränkt)",
66
"url": "https://valospectra.com"
@@ -59,4 +59,4 @@
5959
"typescript-eslint": "^8.33.1"
6060
},
6161
"packageManager": "yarn@4.7.0"
62-
}
62+
}

public/langs/de.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"kills": "Elims",
3-
"deaths": "Tode",
4-
"assists": "Assists",
2+
"playercard.kills": "Elims",
3+
"playercard.deaths": "Tode",
4+
"playercard.assists": "Assists",
55
"endround.round_win": "RUNDE GEWONNEN",
66
"endround.win": "{{team}} GEWINNEN",
77
"endround.attacker": "ANGREIFER",
@@ -16,6 +16,10 @@
1616
"team.attacker": "ANGREIFER",
1717
"team.defender": "VERTEIDIGER",
1818
"scoreboard.spent": "DIESE RUNDE AUSGEGEBEN",
19+
"scoreboard.kills": "Elims",
20+
"scoreboard.deaths": "Tode",
21+
"scoreboard.assists": "Assists",
1922
"timeout.technical_pause": "TECHNISCHE PAUSE",
20-
"timeout.tactical_timeout": "{{teamName}} TAKTISCHE PAUSE"
23+
"timeout.tactical_timeout": "{{teamName}} TAKTISCHE PAUSE",
24+
"timeout.amount": "PAUSEN"
2125
}

public/langs/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@
2020
"scoreboard.deaths": "Deaths",
2121
"scoreboard.assists": "Assists",
2222
"timeout.technical_pause": "TECHNICAL PAUSE",
23-
"timeout.tactical_timeout": "{{teamName}} Tactical Timeout"
23+
"timeout.tactical_timeout": "{{teamName}} Tactical Timeout",
24+
"timeout.amount": "TIMEOUTS"
2425
}

src/app/components/common/timeout/timeout.component.css

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,53 @@
1+
.gradient-left-attacker {
2+
background:
3+
linear-gradient(
4+
to right,
5+
rgba(var(--attacker-color-rgb), 0.75) 0%,
6+
rgba(var(--attacker-color-rgb), 0) 90%
7+
),
8+
rgba(15, 25, 35, 1);
9+
}
10+
11+
.gradient-right-attacker {
12+
background:
13+
linear-gradient(
14+
to left,
15+
rgba(var(--attacker-color-rgb), 0.75) 0%,
16+
rgba(var(--attacker-color-rgb), 0) 90%
17+
),
18+
rgba(15, 25, 35, 1);
19+
}
20+
21+
.gradient-left-defender {
22+
background:
23+
linear-gradient(
24+
to right,
25+
rgba(var(--defender-color-rgb), 0.75) 0%,
26+
rgba(var(--defender-color-rgb), 0) 90%
27+
),
28+
rgba(15, 25, 35, 1);
29+
}
30+
31+
.gradient-right-defender {
32+
background:
33+
linear-gradient(
34+
to left,
35+
rgba(var(--defender-color-rgb), 0.75) 0%,
36+
rgba(var(--defender-color-rgb), 0) 90%
37+
),
38+
rgba(15, 25, 35, 1);
39+
}
40+
41+
.gradient-tech-pause {
42+
background:
43+
linear-gradient(
44+
to top,
45+
rgba(var(--attacker-color-rgb), 0.75) 0%,
46+
rgba(var(--attacker-color-rgb), 0) 90%
47+
),
48+
rgba(15, 25, 35, 1);
49+
}
50+
151
.timer-transition {
252
transition: width 1s linear;
353
}
@@ -18,3 +68,14 @@
1868
animation: swish reverse;
1969
will-change: width;
2070
}
71+
72+
.timeout-pulse {
73+
opacity: 0.7;
74+
animation: to-pulse 3s infinite;
75+
}
76+
77+
@keyframes to-pulse {
78+
40% {
79+
opacity: 0.25;
80+
}
81+
}

src/app/components/common/timeout/timeout.component.html

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,58 @@
11
<div
2-
class="vw-875 vh-200 animate-duration-300 relative top-0 overflow-hidden"
2+
class="vw-750 vh-200 animate-duration-300 animate-style-keep relative top-0 overflow-hidden"
33
[class.hidden]="hide"
44
[class.animate-swish]="inAnimation"
55
[class.animate-swish-out]="outAnimation"
66
>
77
<div
8-
class="vw-875 vh-200 relative top-0 left-0 flex flex-col items-center justify-center overflow-hidden"
8+
class="vw-750 vh-200 relative top-0 left-0 flex flex-col items-center justify-center overflow-hidden"
99
>
10-
<img class="absolute top-0 left-0 -z-1 h-full w-full" [src]="tournamentBackgroundUrl()" />
10+
@if (tournamentBackgroundUrl()) {
11+
<img class="absolute top-0 left-0 -z-1 h-full w-full" [src]="tournamentBackgroundUrl()" />
12+
} @else if (!timeoutInfo().techPause) {
13+
<div
14+
class="absolute top-0 left-0 -z-1 h-full w-full rounded-lg"
15+
[class]="timeoutTeamBackgroundClass()"
16+
></div>
17+
} @else {
18+
<div class="gradient-tech-pause absolute top-0 left-0 -z-1 h-full w-full rounded-lg"></div>
19+
}
1120

1221
@if (timeoutInfo().techPause) {
1322
<p class="font-unbounded text-5xl font-bold text-white uppercase">
1423
{{ TranslateKeys.Timeout_Techpause | translate }}
1524
</p>
1625
} @else {
17-
<img class="max-vh-120 max-vw-400" [src]="timeoutTeam().teamUrl" />
26+
<div class="-mt-2 flex h-2/3 w-1/2 flex-row content-center items-center justify-around">
27+
<div class="w-1/2">
28+
<img class="max-vh-120 max-vw-400" [src]="timeoutTeam().teamUrl" />
29+
</div>
30+
<div class="flex w-1/2 flex-col gap-2 text-center">
31+
<p class="font-unbounded text-2xl font-bold text-white">
32+
{{ TranslateKeys.Timeout_Amount | translate }}
33+
</p>
34+
<div class="flex flex-row justify-center gap-2">
35+
@for (i of numSequence(activeTimeoutCounter()); track $index) {
36+
@if ($index === activeTimeoutCounter() - 1) {
37+
<img class="vw-25 vh-25 timeout-pulse" src="assets/misc/ultimate-pip.svg" />
38+
} @else {
39+
<img class="vw-25 vh-25" src="assets/misc/ultimate-pip-full.svg" />
40+
}
41+
}
42+
@for (i of numSequence(maxTimeouts() - activeTimeoutCounter()); track $index) {
43+
<img class="vw-25 vh-25" src="assets/misc/ultimate-pip.svg" />
44+
}
45+
</div>
46+
</div>
47+
</div>
1848
<p class="font-unbounded text-2xl font-bold text-white">
1949
{{ TranslateKeys.Timeout_Tactical | translate: { teamName: timeoutTeam().teamName } }}
2050
</p>
21-
<div class="vh-23 absolute bottom-0 flex w-full items-center justify-center bg-white/20">
51+
<div
52+
class="vh-22 absolute bottom-0 flex w-full items-center justify-center rounded-b-lg bg-white/20"
53+
>
2254
<div
23-
class="timer-transition absolute left-0 h-full bg-white/35"
55+
class="timer-transition absolute left-0 h-full rounded-tr-lg rounded-br-lg rounded-bl-lg bg-white/35"
2456
[style.width]="timerWidth()"
2557
></div>
2658
<p class="font-montserrat z-2 text-lg font-bold text-white text-shadow-2xs">

src/app/components/common/timeout/timeout.component.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ export class TimeoutComponent {
1616
tournamentBackgroundUrl = computed(() => {
1717
const backdrop = this.dataModel.tournamentInfo().backdropUrl;
1818
if (backdrop && backdrop !== "") return backdrop;
19-
else return "assets/misc/backdrop.webp";
19+
else return false;
20+
});
21+
22+
readonly timeoutTeamBackgroundClass = computed(() => {
23+
return `gradient-${this.timeoutInfo().leftTeam ? "left" : "right"}-${this.timeoutTeam().isAttacking ? "attacker" : "defender"}`;
2024
});
2125

2226
tournamentIconUrl = computed(() => {
@@ -37,6 +41,23 @@ export class TimeoutComponent {
3741
//only needed to have some control over our own update timing so the out-animation goes smoothly
3842
timeoutInfo = signal(Object.assign({}, this.dataModel.timeoutState()));
3943

44+
maxTimeouts = computed(() => {
45+
return this.dataModel.timeoutCounter().max;
46+
});
47+
48+
timeoutCounterLeft = computed(() => {
49+
return this.dataModel.timeoutCounter().left;
50+
});
51+
52+
timeoutCounterRight = computed(() => {
53+
return this.dataModel.timeoutCounter().right;
54+
});
55+
56+
activeTimeoutCounter = computed(() => {
57+
if (this.timeoutInfo().leftTeam) return this.timeoutCounterLeft();
58+
else return this.timeoutCounterRight();
59+
});
60+
4061
shouldHide = computed(() => {
4162
return (
4263
!this.dataModel.timeoutState().techPause &&
@@ -74,4 +95,8 @@ export class TimeoutComponent {
7495
this.timeoutInfo.set(Object.assign({}, this.dataModel.timeoutState()));
7596
}
7697
});
98+
99+
numSequence(n: number): number[] {
100+
return Array(n);
101+
}
77102
}

src/app/overlays/testing-agent-select/testing-agent-select.component.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ export class TestingAgentSelectComponent implements OnInit {
6565
backdropUrl: "",
6666
},
6767
timeoutDuration: 60,
68+
timeoutCounter: {
69+
max: 2,
70+
left: 2,
71+
right: 2,
72+
},
6873
sponsorInfo: {
6974
enabled: true,
7075
duration: 5000,

src/app/overlays/testing/testing.component.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ export class TestingComponent implements OnInit {
6969
backdropUrl: "",
7070
},
7171
timeoutDuration: 60,
72+
timeoutCounter: {
73+
max: 2,
74+
left: 2,
75+
right: 2,
76+
},
7277
sponsorInfo: {
7378
enabled: true,
7479
duration: 5000,

src/app/services/Types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export interface IToolsData {
9090
seedingInfo: ISeedingInfo;
9191
tournamentInfo: ITournamentInfo;
9292
timeoutDuration: number;
93+
timeoutCounter: ITimeoutInfo;
9394
sponsorInfo: ISponsorInfo;
9495
watermarkInfo: IWatermarkInfo;
9596
playercamsInfo: IPlayercamsInfo;
@@ -115,6 +116,12 @@ export interface ITournamentInfo {
115116
enabled: boolean;
116117
}
117118

119+
export interface ITimeoutInfo {
120+
max: number;
121+
left: number;
122+
right: number;
123+
}
124+
118125
export interface ISponsorInfo {
119126
enabled: boolean;
120127
duration: number;

src/app/services/dataModel.service.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ export class DataModelService {
9595
public readonly timeoutState = computed(() => this.match().timeoutState, {
9696
equal: () => false,
9797
});
98+
public readonly timeoutCounter = computed(() => this.match().tools.timeoutCounter, {
99+
equal: () => false,
100+
});
98101
public readonly spikeState = computed(() => this.match().spikeState, {
99102
equal: isEqual,
100103
});
@@ -169,6 +172,11 @@ const initialMatchData: IMatchData = {
169172
backdropUrl: "",
170173
},
171174
timeoutDuration: 60,
175+
timeoutCounter: {
176+
max: 2,
177+
left: 2,
178+
right: 2,
179+
},
172180
sponsorInfo: {
173181
enabled: false,
174182
duration: 5000,

0 commit comments

Comments
 (0)