## Description:

Adds a max timer setting
The timer starts at max timer and goes down, becoming red if reaching <
1 min
The player with the biggest territory wins at the end of the timer


![image](https://github.com/user-attachments/assets/888099fc-95ae-4303-8c80-c850e58d36e2)

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I understand that submitting code with bugs that could have been
caught through manual testing blocks releases and new features for all
contributors

## Please put your Discord username so you can be contacted if a bug or
regression is found:

Vivacious Box

---------

Co-authored-by: Loymdayddaud <145969603+TheGiraffe3@users.noreply.github.com>
This commit is contained in:
Vivacious Box
2025-10-17 17:09:10 -07:00
committed by GitHub
co-authored by Loymdayddaud
parent 75ca2fb349
commit f161c94ff4
10 changed files with 235 additions and 6 deletions
+54
View File
@@ -40,6 +40,8 @@ export class SinglePlayerModal extends LitElement {
@state() private infiniteGold: boolean = false;
@state() private infiniteTroops: boolean = false;
@state() private compactMap: boolean = false;
@state() private maxTimer: boolean = false;
@state() private maxTimerValue: number | undefined = undefined;
@state() private instantBuild: boolean = false;
@state() private useRandomMap: boolean = false;
@state() private gameMode: GameMode = GameMode.FFA;
@@ -315,6 +317,39 @@ export class SinglePlayerModal extends LitElement {
${translateText("single_modal.compact_map")}
</div>
</label>
<label
for="end-timer"
class="option-card ${this.maxTimer ? "selected" : ""}"
>
<div class="checkbox-icon"></div>
<input
type="checkbox"
id="end-timer"
@change=${(e: Event) => {
const checked = (e.target as HTMLInputElement).checked;
if (!checked) {
this.maxTimerValue = undefined;
}
this.maxTimer = checked;
}}
.checked=${this.maxTimer}
/>
${this.maxTimer === false
? ""
: html`<input
type="number"
id="end-timer-value"
min="0"
max="120"
.value=${String(this.maxTimerValue ?? "")}
style="width: 60px; color: black; text-align: right; border-radius: 8px;"
@input=${this.handleMaxTimerValueChanges}
@keydown=${this.handleMaxTimerValueKeyDown}
/>`}
<div class="option-card-title">
${translateText("single_modal.max_timer")}
</div>
</label>
</div>
<hr
@@ -395,6 +430,24 @@ export class SinglePlayerModal extends LitElement {
this.compactMap = Boolean((e.target as HTMLInputElement).checked);
}
private handleMaxTimerValueKeyDown(e: KeyboardEvent) {
if (["-", "+", "e"].includes(e.key)) {
e.preventDefault();
}
}
private handleMaxTimerValueChanges(e: Event) {
(e.target as HTMLInputElement).value = (
e.target as HTMLInputElement
).value.replace(/[e+-]/gi, "");
const value = parseInt((e.target as HTMLInputElement).value);
if (isNaN(value) || value < 0 || value > 120) {
return;
}
this.maxTimerValue = value;
}
private handleDisableNPCsChange(e: Event) {
this.disableNPCs = Boolean((e.target as HTMLInputElement).checked);
}
@@ -482,6 +535,7 @@ export class SinglePlayerModal extends LitElement {
playerTeams: this.teamCount,
difficulty: this.selectedDifficulty,
disableNPCs: this.disableNPCs,
maxTimerValue: this.maxTimer ? this.maxTimerValue : undefined,
bots: this.bots,
infiniteGold: this.infiniteGold,
donateGold: true,