mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-15 10:43:04 +00:00
Add Nations Vs Players Game Mode (#2233)
## Description: Fixes: #676 This PR adds Players Vs Nations as a game mode in the menu. For this change I have added two mutually exclusive option for this mode: 1. Match number of nations to number of players who have joined 2. Set the number of nations to a fixed value ### Screenshots: #### Options in Single player mode <img width="1025" height="790" alt="image" src="https://github.com/user-attachments/assets/c0685ea5-94f5-43c7-a9e5-390835fc94e9" /> <img width="1005" height="795" alt="image" src="https://github.com/user-attachments/assets/dddba015-a424-40dd-a0fe-2571fd7b0fba" /> #### Options in lobby mode <img width="1015" height="888" alt="image" src="https://github.com/user-attachments/assets/45bc865b-c6a8-4b6a-9062-4eb499c1ea36" /> #### Example gameplay (1 Human Vs 90 Nations) <img width="1888" height="912" alt="image" src="https://github.com/user-attachments/assets/38faec75-171f-4358-a3be-93630cca1587" /> ## 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 ## Please put your Discord username so you can be contacted if a bug or regression is found: saphereye --------- Co-authored-by: Evan <evanpelle@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
GameMapSize,
|
||||
GameMapType,
|
||||
GameMode,
|
||||
HumansVsNations,
|
||||
Quads,
|
||||
Trios,
|
||||
UnitType,
|
||||
@@ -284,7 +285,18 @@ export class HostLobbyModal extends LitElement {
|
||||
${translateText("host_modal.team_count")}
|
||||
</div>
|
||||
<div class="option-cards">
|
||||
${[2, 3, 4, 5, 6, 7, Quads, Trios, Duos].map(
|
||||
${[
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
Quads,
|
||||
Trios,
|
||||
Duos,
|
||||
HumansVsNations,
|
||||
].map(
|
||||
(o) => html`
|
||||
<div
|
||||
class="option-card ${this.teamCount === o
|
||||
@@ -294,7 +306,9 @@ export class HostLobbyModal extends LitElement {
|
||||
>
|
||||
<div class="option-card-title">
|
||||
${typeof o === "string"
|
||||
? translateText(`public_lobby.teams_${o}`)
|
||||
? o === HumansVsNations
|
||||
? translateText("public_lobby.teams_hvn")
|
||||
: translateText(`public_lobby.teams_${o}`)
|
||||
: translateText("public_lobby.teams", {
|
||||
num: o,
|
||||
})}
|
||||
@@ -313,42 +327,53 @@ export class HostLobbyModal extends LitElement {
|
||||
${translateText("host_modal.options_title")}
|
||||
</div>
|
||||
<div class="option-cards">
|
||||
<label for="bots-count" class="option-card">
|
||||
<input
|
||||
type="range"
|
||||
id="bots-count"
|
||||
min="0"
|
||||
max="400"
|
||||
step="1"
|
||||
@input=${this.handleBotsChange}
|
||||
@change=${this.handleBotsChange}
|
||||
.value="${String(this.bots)}"
|
||||
/>
|
||||
<div class="option-card-title">
|
||||
<span>${translateText("host_modal.bots")}</span>${
|
||||
this.bots === 0
|
||||
? translateText("host_modal.bots_disabled")
|
||||
: this.bots
|
||||
}
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label
|
||||
for="disable-npcs"
|
||||
class="option-card ${this.disableNPCs ? "selected" : ""}"
|
||||
>
|
||||
<div class="checkbox-icon"></div>
|
||||
<label for="bots-count" class="option-card">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="disable-npcs"
|
||||
@change=${this.handleDisableNPCsChange}
|
||||
.checked=${this.disableNPCs}
|
||||
type="range"
|
||||
id="bots-count"
|
||||
min="0"
|
||||
max="400"
|
||||
step="1"
|
||||
@input=${this.handleBotsChange}
|
||||
@change=${this.handleBotsChange}
|
||||
.value="${String(this.bots)}"
|
||||
/>
|
||||
<div class="option-card-title">
|
||||
${translateText("host_modal.disable_nations")}
|
||||
<span>${translateText("host_modal.bots")}</span>${
|
||||
this.bots === 0
|
||||
? translateText("host_modal.bots_disabled")
|
||||
: this.bots
|
||||
}
|
||||
</div>
|
||||
</label>
|
||||
|
||||
${
|
||||
!(
|
||||
this.gameMode === GameMode.Team &&
|
||||
this.teamCount === HumansVsNations
|
||||
)
|
||||
? html`
|
||||
<label
|
||||
for="disable-npcs"
|
||||
class="option-card ${this.disableNPCs
|
||||
? "selected"
|
||||
: ""}"
|
||||
>
|
||||
<div class="checkbox-icon"></div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="disable-npcs"
|
||||
@change=${this.handleDisableNPCsChange}
|
||||
.checked=${this.disableNPCs}
|
||||
/>
|
||||
<div class="option-card-title">
|
||||
${translateText("host_modal.disable_nations")}
|
||||
</div>
|
||||
</label>
|
||||
`
|
||||
: ""
|
||||
}
|
||||
|
||||
<label
|
||||
for="instant-build"
|
||||
class="option-card ${this.instantBuild ? "selected" : ""}"
|
||||
@@ -718,7 +743,6 @@ export class HostLobbyModal extends LitElement {
|
||||
? GameMapSize.Compact
|
||||
: GameMapSize.Normal,
|
||||
difficulty: this.selectedDifficulty,
|
||||
disableNPCs: this.disableNPCs,
|
||||
bots: this.bots,
|
||||
infiniteGold: this.infiniteGold,
|
||||
donateGold: this.donateGold,
|
||||
@@ -728,6 +752,14 @@ export class HostLobbyModal extends LitElement {
|
||||
gameMode: this.gameMode,
|
||||
disabledUnits: this.disabledUnits,
|
||||
playerTeams: this.teamCount,
|
||||
...(this.gameMode === GameMode.Team &&
|
||||
this.teamCount === HumansVsNations
|
||||
? {
|
||||
disableNPCs: false,
|
||||
}
|
||||
: {
|
||||
disableNPCs: this.disableNPCs,
|
||||
}),
|
||||
maxTimerValue:
|
||||
this.maxTimer === true ? this.maxTimerValue : undefined,
|
||||
} satisfies Partial<GameConfig>),
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
GameMapType,
|
||||
GameMode,
|
||||
GameType,
|
||||
HumansVsNations,
|
||||
Quads,
|
||||
Trios,
|
||||
UnitType,
|
||||
@@ -195,7 +196,18 @@ export class SinglePlayerModal extends LitElement {
|
||||
${translateText("host_modal.team_count")}
|
||||
</div>
|
||||
<div class="option-cards">
|
||||
${[2, 3, 4, 5, 6, 7, Quads, Trios, Duos].map(
|
||||
${[
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
Quads,
|
||||
Trios,
|
||||
Duos,
|
||||
HumansVsNations,
|
||||
].map(
|
||||
(o) => html`
|
||||
<div
|
||||
class="option-card ${this.teamCount === o
|
||||
@@ -205,7 +217,9 @@ export class SinglePlayerModal extends LitElement {
|
||||
>
|
||||
<div class="option-card-title">
|
||||
${typeof o === "string"
|
||||
? translateText(`public_lobby.teams_${o}`)
|
||||
? o === HumansVsNations
|
||||
? translateText("public_lobby.teams_hvn")
|
||||
: translateText(`public_lobby.teams_${o}`)
|
||||
: translateText(`public_lobby.teams`, { num: o })}
|
||||
</div>
|
||||
</div>
|
||||
@@ -240,21 +254,29 @@ export class SinglePlayerModal extends LitElement {
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label
|
||||
for="singleplayer-modal-disable-npcs"
|
||||
class="option-card ${this.disableNPCs ? "selected" : ""}"
|
||||
>
|
||||
<div class="checkbox-icon"></div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="singleplayer-modal-disable-npcs"
|
||||
@change=${this.handleDisableNPCsChange}
|
||||
.checked=${this.disableNPCs}
|
||||
/>
|
||||
<div class="option-card-title">
|
||||
${translateText("single_modal.disable_nations")}
|
||||
</div>
|
||||
</label>
|
||||
${!(
|
||||
this.gameMode === GameMode.Team &&
|
||||
this.teamCount === HumansVsNations
|
||||
)
|
||||
? html`
|
||||
<label
|
||||
for="singleplayer-modal-disable-npcs"
|
||||
class="option-card ${this.disableNPCs ? "selected" : ""}"
|
||||
>
|
||||
<div class="checkbox-icon"></div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="singleplayer-modal-disable-npcs"
|
||||
@change=${this.handleDisableNPCsChange}
|
||||
.checked=${this.disableNPCs}
|
||||
/>
|
||||
<div class="option-card-title">
|
||||
${translateText("single_modal.disable_nations")}
|
||||
</div>
|
||||
</label>
|
||||
`
|
||||
: ""}
|
||||
|
||||
<label
|
||||
for="singleplayer-modal-instant-build"
|
||||
class="option-card ${this.instantBuild ? "selected" : ""}"
|
||||
@@ -534,7 +556,6 @@ export class SinglePlayerModal extends LitElement {
|
||||
gameMode: this.gameMode,
|
||||
playerTeams: this.teamCount,
|
||||
difficulty: this.selectedDifficulty,
|
||||
disableNPCs: this.disableNPCs,
|
||||
maxTimerValue: this.maxTimer ? this.maxTimerValue : undefined,
|
||||
bots: this.bots,
|
||||
infiniteGold: this.infiniteGold,
|
||||
@@ -545,6 +566,14 @@ export class SinglePlayerModal extends LitElement {
|
||||
disabledUnits: this.disabledUnits
|
||||
.map((u) => Object.values(UnitType).find((ut) => ut === u))
|
||||
.filter((ut): ut is UnitType => ut !== undefined),
|
||||
...(this.gameMode === GameMode.Team &&
|
||||
this.teamCount === HumansVsNations
|
||||
? {
|
||||
disableNPCs: false,
|
||||
}
|
||||
: {
|
||||
disableNPCs: this.disableNPCs,
|
||||
}),
|
||||
},
|
||||
},
|
||||
} satisfies JoinLobbyEvent,
|
||||
|
||||
Reference in New Issue
Block a user