mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-04 13:12:31 +00:00
Max timer (#1289)
## 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  ## 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:
@@ -44,6 +44,8 @@ export class HostLobbyModal extends LitElement {
|
||||
@state() private donateGold: boolean = false;
|
||||
@state() private infiniteTroops: boolean = false;
|
||||
@state() private donateTroops: boolean = false;
|
||||
@state() private maxTimer: boolean = false;
|
||||
@state() private maxTimerValue: number | undefined = undefined;
|
||||
@state() private instantBuild: boolean = false;
|
||||
@state() private compactMap: boolean = false;
|
||||
@state() private lobbyId = "";
|
||||
@@ -442,6 +444,42 @@ export class HostLobbyModal extends LitElement {
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label
|
||||
for="max-timer"
|
||||
class="option-card ${this.maxTimer ? "selected" : ""}"
|
||||
>
|
||||
<div class="checkbox-icon"></div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="max-timer"
|
||||
@change=${(e: Event) => {
|
||||
const checked = (e.target as HTMLInputElement).checked;
|
||||
if (!checked) {
|
||||
this.maxTimerValue = undefined;
|
||||
}
|
||||
this.maxTimer = checked;
|
||||
this.putGameConfig();
|
||||
}}
|
||||
.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("host_modal.max_timer")}
|
||||
</div>
|
||||
</label>
|
||||
<hr style="width: 100%; border-top: 1px solid #444; margin: 16px 0;" />
|
||||
|
||||
<!-- Individual disables for structures/weapons -->
|
||||
@@ -630,6 +668,25 @@ export class HostLobbyModal extends LitElement {
|
||||
this.putGameConfig();
|
||||
}
|
||||
|
||||
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;
|
||||
this.putGameConfig();
|
||||
}
|
||||
|
||||
private async handleDisableNPCsChange(e: Event) {
|
||||
this.disableNPCs = Boolean((e.target as HTMLInputElement).checked);
|
||||
console.log(`updating disable npcs to ${this.disableNPCs}`);
|
||||
@@ -671,6 +728,8 @@ export class HostLobbyModal extends LitElement {
|
||||
gameMode: this.gameMode,
|
||||
disabledUnits: this.disabledUnits,
|
||||
playerTeams: this.teamCount,
|
||||
maxTimerValue:
|
||||
this.maxTimer === true ? this.maxTimerValue : undefined,
|
||||
} satisfies Partial<GameConfig>),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -57,10 +57,19 @@ export class GameRightSidebar extends LitElement implements Layer {
|
||||
if (updates) {
|
||||
this.hasWinner = this.hasWinner || updates[GameUpdateType.Win].length > 0;
|
||||
}
|
||||
if (this.game.inSpawnPhase()) {
|
||||
this.timer = 0;
|
||||
} else if (!this.hasWinner && this.game.ticks() % 10 === 0) {
|
||||
this.timer++;
|
||||
const maxTimerValue = this.game.config().gameConfig().maxTimerValue;
|
||||
if (maxTimerValue !== undefined) {
|
||||
if (this.game.inSpawnPhase()) {
|
||||
this.timer = maxTimerValue * 60;
|
||||
} else if (!this.hasWinner && this.game.ticks() % 10 === 0) {
|
||||
this.timer = Math.max(0, this.timer - 1);
|
||||
}
|
||||
} else {
|
||||
if (this.game.inSpawnPhase()) {
|
||||
this.timer = 0;
|
||||
} else if (!this.hasWinner && this.game.ticks() % 10 === 0) {
|
||||
this.timer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +149,10 @@ export class GameRightSidebar extends LitElement implements Layer {
|
||||
<div class="flex justify-center items-center mt-2">
|
||||
<div
|
||||
class="w-[70px] h-8 lg:w-24 lg:h-10 border border-slate-400 p-0.5 text-xs md:text-sm lg:text-base flex items-center justify-center text-white px-1"
|
||||
style="${this.game.config().gameConfig().maxTimerValue !==
|
||||
undefined && this.timer < 60
|
||||
? "color: #ff8080;"
|
||||
: ""}"
|
||||
>
|
||||
${this.secondsToHms(this.timer)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user