mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:10:42 +00:00
Add time limit modifier for public games ⏱️
Adds a "time limit" modifier (10/20/30 min) to the public special-game modifier pool, alongside existing modifiers like starting gold and water nukes. Reuses the existing maxTimerValue config field, which WinCheckExecution already enforces (territory leader wins when the timer expires). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1128,6 +1128,8 @@
|
||||
"sams_disabled_label": "SAMs",
|
||||
"starting_gold": "{amount}M Starting Gold",
|
||||
"starting_gold_label": "Starting Gold",
|
||||
"time_limit": "{amount}min Time Limit",
|
||||
"time_limit_label": "Time Limit",
|
||||
"water_nukes": "Water Nukes",
|
||||
"water_nukes_label": "Water Nukes"
|
||||
},
|
||||
|
||||
@@ -220,6 +220,17 @@ export function getActiveModifiers(
|
||||
badgeKey: "public_game_modifier.water_nukes",
|
||||
});
|
||||
}
|
||||
if (modifiers.maxTimerValue) {
|
||||
result.push({
|
||||
labelKey: "public_game_modifier.time_limit_label",
|
||||
badgeKey: "public_game_modifier.time_limit",
|
||||
badgeParams: {
|
||||
amount: modifiers.maxTimerValue,
|
||||
},
|
||||
value: modifiers.maxTimerValue,
|
||||
formattedValue: `${modifiers.maxTimerValue} min`,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -264,6 +264,7 @@ export const GameConfigSchema = z.object({
|
||||
isSAMsDisabled: z.boolean().optional(),
|
||||
isPeaceTime: z.boolean().optional(),
|
||||
isWaterNukes: z.boolean().optional(),
|
||||
maxTimerValue: z.number().int().min(1).optional(),
|
||||
})
|
||||
.optional(),
|
||||
nations: z
|
||||
|
||||
@@ -143,6 +143,7 @@ export interface PublicGameModifiers {
|
||||
isSAMsDisabled?: boolean;
|
||||
isPeaceTime?: boolean;
|
||||
isWaterNukes?: boolean;
|
||||
maxTimerValue?: number;
|
||||
}
|
||||
|
||||
export interface UnitInfo {
|
||||
|
||||
@@ -75,7 +75,10 @@ type ModifierKey =
|
||||
| "isNukesDisabled"
|
||||
| "isSAMsDisabled"
|
||||
| "isPeaceTime"
|
||||
| "isWaterNukes";
|
||||
| "isWaterNukes"
|
||||
| "timeLimit10M"
|
||||
| "timeLimit20M"
|
||||
| "timeLimit30M";
|
||||
|
||||
// Each entry represents one "ticket" in the pool. More tickets = higher chance of selection.
|
||||
// Weights are roughly informed by the community "favorite modifier" poll.
|
||||
@@ -94,6 +97,9 @@ const SPECIAL_MODIFIER_POOL: ModifierKey[] = [
|
||||
...Array<ModifierKey>(1).fill("isSAMsDisabled"),
|
||||
...Array<ModifierKey>(1).fill("isPeaceTime"),
|
||||
...Array<ModifierKey>(4).fill("isWaterNukes"),
|
||||
...Array<ModifierKey>(2).fill("timeLimit10M"),
|
||||
...Array<ModifierKey>(2).fill("timeLimit20M"),
|
||||
...Array<ModifierKey>(1).fill("timeLimit30M"),
|
||||
];
|
||||
|
||||
// Maps where water nukes have a higher chance on top of the normal pool
|
||||
@@ -122,6 +128,9 @@ const MUTUALLY_EXCLUSIVE_MODIFIERS: [ModifierKey, ModifierKey][] = [
|
||||
["isHardNations", "startingGold25M"],
|
||||
["isNukesDisabled", "isSAMsDisabled"],
|
||||
["isNukesDisabled", "isWaterNukes"],
|
||||
["timeLimit10M", "timeLimit20M"],
|
||||
["timeLimit10M", "timeLimit30M"],
|
||||
["timeLimit20M", "timeLimit30M"],
|
||||
];
|
||||
|
||||
export class MapPlaylist {
|
||||
@@ -263,6 +272,7 @@ export class MapPlaylist {
|
||||
isSAMsDisabled,
|
||||
isPeaceTime,
|
||||
isWaterNukes,
|
||||
maxTimerValue,
|
||||
} = poolResult;
|
||||
if (boostWaterNukes) {
|
||||
isWaterNukes = true;
|
||||
@@ -290,7 +300,8 @@ export class MapPlaylist {
|
||||
!isNukesDisabled &&
|
||||
!isSAMsDisabled &&
|
||||
!isPeaceTime &&
|
||||
!isWaterNukes
|
||||
!isWaterNukes &&
|
||||
maxTimerValue === undefined
|
||||
) {
|
||||
excludedModifiers.push("isCrowded");
|
||||
const fallback = this.getRandomSpecialGameModifiers(
|
||||
@@ -308,6 +319,7 @@ export class MapPlaylist {
|
||||
isSAMsDisabled,
|
||||
isPeaceTime,
|
||||
isWaterNukes,
|
||||
maxTimerValue,
|
||||
} = fallback);
|
||||
({ isHardNations } = fallback);
|
||||
}
|
||||
@@ -368,6 +380,7 @@ export class MapPlaylist {
|
||||
isSAMsDisabled,
|
||||
isPeaceTime,
|
||||
isWaterNukes,
|
||||
maxTimerValue,
|
||||
},
|
||||
startingGold,
|
||||
goldMultiplier,
|
||||
@@ -378,7 +391,7 @@ export class MapPlaylist {
|
||||
: Difficulty.Medium,
|
||||
infiniteGold: false,
|
||||
infiniteTroops: false,
|
||||
maxTimerValue: undefined,
|
||||
maxTimerValue,
|
||||
instantBuild: false,
|
||||
randomSpawn: isRandomSpawn ? true : false,
|
||||
nations,
|
||||
@@ -573,6 +586,13 @@ export class MapPlaylist {
|
||||
isSAMsDisabled: selected.has("isSAMsDisabled") || undefined,
|
||||
isPeaceTime: selected.has("isPeaceTime") || undefined,
|
||||
isWaterNukes: selected.has("isWaterNukes") || undefined,
|
||||
maxTimerValue: selected.has("timeLimit10M")
|
||||
? 10
|
||||
: selected.has("timeLimit20M")
|
||||
? 20
|
||||
: selected.has("timeLimit30M")
|
||||
? 30
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user