mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 10:53:31 +00:00
Starting gold input in millions with decimal support ✨ (#3349)
## Description: **Starting gold input: use millions** Changes the starting gold input in singleplayer and host lobby modals to accept values in millions (e.g. enter `5` for 5M gold). Supports decimals like `6.6` for 6.6M. The value is multiplied by 1,000,000 before being sent to the game config. - Label updated to "Starting Gold (Millions)" - Input uses float parsing with min 0.1, matching gold multiplier behavior - JoinLobbyModal shows clean values without unnecessary decimals (e.g. "5M" not "5.00M") Previous <img width="215" height="139" alt="image" src="https://github.com/user-attachments/assets/00ce5b6d-f74d-4aee-92f5-c9be1a0a6d3d" /> <img width="292" height="74" alt="image" src="https://github.com/user-attachments/assets/4de936a3-22bd-4ffc-8dbe-0d5066f28186" /> Now <img width="216" height="151" alt="image" src="https://github.com/user-attachments/assets/489de13e-65b5-4b02-a654-5f6f74b165d1" /> <img width="292" height="72" alt="image" src="https://github.com/user-attachments/assets/51723d5a-55ab-4b7b-bbce-011a586eeb44" /> ## 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: FloPinguin
This commit is contained in:
@@ -201,8 +201,8 @@
|
||||
"options_changed_no_achievements": "Custom settings – achievements disabled",
|
||||
"gold_multiplier": "Gold multiplier",
|
||||
"gold_multiplier_placeholder": "2.0x",
|
||||
"starting_gold": "Starting gold",
|
||||
"starting_gold_placeholder": "5000000"
|
||||
"starting_gold": "Starting Gold (Millions)",
|
||||
"starting_gold_placeholder": "5"
|
||||
},
|
||||
"token_login_modal": {
|
||||
"title": "Logging in...",
|
||||
|
||||
@@ -195,18 +195,18 @@ export class HostLobbyModal extends BaseModal {
|
||||
.labelKey=${"single_modal.starting_gold"}
|
||||
.checked=${this.startingGold}
|
||||
.inputId=${"starting-gold-value"}
|
||||
.inputMin=${0}
|
||||
.inputMax=${1000000000}
|
||||
.inputStep=${100000}
|
||||
.inputMin=${0.1}
|
||||
.inputMax=${1000}
|
||||
.inputStep=${"any"}
|
||||
.inputValue=${this.startingGoldValue}
|
||||
.inputAriaLabel=${translateText("single_modal.starting_gold")}
|
||||
.inputPlaceholder=${translateText(
|
||||
"single_modal.starting_gold_placeholder",
|
||||
)}
|
||||
.defaultInputValue=${5000000}
|
||||
.minValidOnEnable=${0}
|
||||
.defaultInputValue=${5}
|
||||
.minValidOnEnable=${0.1}
|
||||
.onToggle=${this.handleStartingGoldToggle}
|
||||
.onInput=${this.handleStartingGoldValueChanges}
|
||||
.onChange=${this.handleStartingGoldValueChanges}
|
||||
.onKeyDown=${this.handleStartingGoldValueKeyDown}
|
||||
></toggle-input-card>`,
|
||||
];
|
||||
@@ -650,12 +650,17 @@ export class HostLobbyModal extends BaseModal {
|
||||
|
||||
private handleStartingGoldValueChanges = (e: Event) => {
|
||||
const input = e.target as HTMLInputElement;
|
||||
const value = parseBoundedIntegerFromInput(input, {
|
||||
min: 0,
|
||||
max: 1000000000,
|
||||
const value = parseBoundedFloatFromInput(input, {
|
||||
min: 0.1,
|
||||
max: 1000,
|
||||
});
|
||||
|
||||
this.startingGoldValue = value;
|
||||
if (value === undefined) {
|
||||
this.startingGoldValue = undefined;
|
||||
input.value = "";
|
||||
} else {
|
||||
this.startingGoldValue = value;
|
||||
}
|
||||
this.putGameConfig();
|
||||
};
|
||||
|
||||
@@ -787,7 +792,9 @@ export class HostLobbyModal extends BaseModal {
|
||||
? this.goldMultiplierValue
|
||||
: undefined,
|
||||
startingGold:
|
||||
this.startingGold === true ? this.startingGoldValue : undefined,
|
||||
this.startingGold === true && this.startingGoldValue !== undefined
|
||||
? Math.round(this.startingGoldValue * 1_000_000)
|
||||
: undefined,
|
||||
} satisfies Partial<GameConfig>,
|
||||
},
|
||||
bubbles: true,
|
||||
|
||||
@@ -432,9 +432,10 @@ export class JoinLobbyModal extends BaseModal {
|
||||
(m) => html`
|
||||
<lobby-config-item
|
||||
.label=${translateText(m.labelKey)}
|
||||
.value=${m.value !== undefined
|
||||
.value=${m.formattedValue ??
|
||||
(m.value !== undefined
|
||||
? renderNumber(m.value)
|
||||
: translateText("common.enabled")}
|
||||
: translateText("common.enabled"))}
|
||||
></lobby-config-item>
|
||||
`,
|
||||
)}
|
||||
|
||||
@@ -210,18 +210,18 @@ export class SinglePlayerModal extends BaseModal {
|
||||
.labelKey=${"single_modal.starting_gold"}
|
||||
.checked=${this.startingGold}
|
||||
.inputId=${"starting-gold-value"}
|
||||
.inputMin=${0}
|
||||
.inputMax=${1000000000}
|
||||
.inputStep=${100000}
|
||||
.inputMin=${0.1}
|
||||
.inputMax=${1000}
|
||||
.inputStep=${"any"}
|
||||
.inputValue=${this.startingGoldValue}
|
||||
.inputAriaLabel=${translateText("single_modal.starting_gold")}
|
||||
.inputPlaceholder=${translateText(
|
||||
"single_modal.starting_gold_placeholder",
|
||||
)}
|
||||
.defaultInputValue=${5000000}
|
||||
.minValidOnEnable=${0}
|
||||
.defaultInputValue=${5}
|
||||
.minValidOnEnable=${0.1}
|
||||
.onToggle=${this.handleStartingGoldToggle}
|
||||
.onInput=${this.handleStartingGoldValueChanges}
|
||||
.onChange=${this.handleStartingGoldValueChanges}
|
||||
.onKeyDown=${this.handleStartingGoldValueKeyDown}
|
||||
></toggle-input-card>`,
|
||||
];
|
||||
@@ -591,12 +591,17 @@ export class SinglePlayerModal extends BaseModal {
|
||||
|
||||
private handleStartingGoldValueChanges = (e: Event) => {
|
||||
const input = e.target as HTMLInputElement;
|
||||
const value = parseBoundedIntegerFromInput(input, {
|
||||
min: 0,
|
||||
max: 1000000000,
|
||||
const value = parseBoundedFloatFromInput(input, {
|
||||
min: 0.1,
|
||||
max: 1000,
|
||||
});
|
||||
|
||||
this.startingGoldValue = value;
|
||||
if (value === undefined) {
|
||||
this.startingGoldValue = undefined;
|
||||
input.value = "";
|
||||
} else {
|
||||
this.startingGoldValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
private handleGameModeSelection(value: GameMode) {
|
||||
@@ -685,7 +690,11 @@ export class SinglePlayerModal extends BaseModal {
|
||||
? { goldMultiplier: this.goldMultiplierValue }
|
||||
: {}),
|
||||
...(this.startingGold && this.startingGoldValue !== undefined
|
||||
? { startingGold: this.startingGoldValue }
|
||||
? {
|
||||
startingGold: Math.round(
|
||||
this.startingGoldValue * 1_000_000,
|
||||
),
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
lobbyCreatedAt: Date.now(), // ms; server should be authoritative in MP
|
||||
|
||||
+7
-1
@@ -115,6 +115,8 @@ export interface ModifierInfo {
|
||||
badgeParams?: Record<string, string | number>;
|
||||
/** The raw value if applicable (e.g. startingGold amount) */
|
||||
value?: number;
|
||||
/** Pre-formatted display string (used instead of renderNumber when provided) */
|
||||
formattedValue?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,13 +152,17 @@ export function getActiveModifiers(
|
||||
});
|
||||
}
|
||||
if (modifiers.startingGold) {
|
||||
const millions = parseFloat(
|
||||
(modifiers.startingGold / 1_000_000).toPrecision(12),
|
||||
);
|
||||
result.push({
|
||||
labelKey: "host_modal.starting_gold",
|
||||
badgeKey: "public_game_modifier.starting_gold",
|
||||
badgeParams: {
|
||||
amount: Math.round(modifiers.startingGold / 1_000_000),
|
||||
amount: millions,
|
||||
},
|
||||
value: modifiers.startingGold,
|
||||
formattedValue: `${millions}M`,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user