Skip to content

Commit 5b0d155

Browse files
authored
Merge branch 'main' into publiclobbymodal
2 parents 28dca64 + 7942990 commit 5b0d155

File tree

6 files changed

+56
-9
lines changed

6 files changed

+56
-9
lines changed

resources/lang/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
"infinite_gold": "Infinite gold",
168168
"infinite_troops": "Infinite troops",
169169
"compact_map": "Compact Map",
170+
"crowded": "Crowded",
170171
"max_timer": "Game length (minutes)",
171172
"max_timer_placeholder": "Mins",
172173
"max_timer_invalid": "Please enter a valid max timer value (1-120 minutes)",
@@ -428,6 +429,7 @@
428429
"public_game_modifier": {
429430
"random_spawn": "Random Spawn",
430431
"compact_map": "Compact Map",
432+
"crowded": "Crowded",
431433
"starting_gold": "5M Starting Gold"
432434
},
433435
"select_lang": {

src/client/PublicLobby.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ export class PublicLobby extends LitElement {
333333
if (publicGameModifiers.isCompact) {
334334
labels.push(translateText("public_game_modifier.compact_map"));
335335
}
336+
if (publicGameModifiers.isCrowded) {
337+
labels.push(translateText("public_game_modifier.crowded"));
338+
}
336339
if (publicGameModifiers.startingGold) {
337340
labels.push(translateText("public_game_modifier.starting_gold"));
338341
}

src/core/Schemas.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ export const GameConfigSchema = z.object({
194194
.object({
195195
isCompact: z.boolean(),
196196
isRandomSpawn: z.boolean(),
197+
isCrowded: z.boolean(),
197198
startingGold: z.number().int().min(0).optional(),
198199
})
199200
.optional(),

src/core/game/Game.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ export enum GameMapSize {
211211
export interface PublicGameModifiers {
212212
isCompact: boolean;
213213
isRandomSpawn: boolean;
214+
isCrowded: boolean;
214215
startingGold?: number;
215216
}
216217

src/server/MapPlaylist.ts

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export class MapPlaylist {
9797

9898
const modifiers = this.getRandomPublicGameModifiers();
9999
const { startingGold } = modifiers;
100-
let { isCompact, isRandomSpawn } = modifiers;
100+
let { isCompact, isRandomSpawn, isCrowded } = modifiers;
101101

102102
// Duos, Trios, and Quads should not get random spawn (as it defeats the purpose)
103103
if (
@@ -108,24 +108,43 @@ export class MapPlaylist {
108108
isRandomSpawn = false;
109109
}
110110

111-
// Maps with smallest player count < 50 don't support compact map in team games
112-
// The smallest player count is the 3rd number in the player counts array
111+
// Maps with smallest player count (third number of calculateMapPlayerCounts) < 50 don't support compact map in team games
112+
// (not enough players after 75% player reduction for compact maps)
113113
if (
114114
mode === GameMode.Team &&
115115
!(await this.supportsCompactMapForTeams(map))
116116
) {
117117
isCompact = false;
118118
}
119119

120+
// Crowded modifier: if the map's biggest player count (first number of calculateMapPlayerCounts) is 60 or lower (small maps),
121+
// set player count to 125 (or 60 if compact map is also enabled)
122+
let crowdedMaxPlayers: number | undefined;
123+
if (isCrowded) {
124+
crowdedMaxPlayers = await this.getCrowdedMaxPlayers(map, isCompact);
125+
if (crowdedMaxPlayers === undefined) {
126+
isCrowded = false;
127+
} else {
128+
crowdedMaxPlayers = this.adjustForTeams(crowdedMaxPlayers, playerTeams);
129+
}
130+
}
131+
120132
// Create the default public game config (from your GameManager)
121133
return {
122134
donateGold: mode === GameMode.Team,
123135
donateTroops: mode === GameMode.Team,
124136
gameMap: map,
125-
maxPlayers: await this.lobbyMaxPlayers(map, mode, playerTeams, isCompact),
137+
maxPlayers:
138+
crowdedMaxPlayers ??
139+
(await this.lobbyMaxPlayers(map, mode, playerTeams, isCompact)),
126140
gameType: GameType.Public,
127141
gameMapSize: isCompact ? GameMapSize.Compact : GameMapSize.Normal,
128-
publicGameModifiers: { isCompact, isRandomSpawn, startingGold },
142+
publicGameModifiers: {
143+
isCompact,
144+
isRandomSpawn,
145+
isCrowded,
146+
startingGold,
147+
},
129148
startingGold,
130149
difficulty:
131150
playerTeams === HumansVsNations ? Difficulty.Medium : Difficulty.Easy,
@@ -209,18 +228,31 @@ export class MapPlaylist {
209228
return {
210229
isRandomSpawn: Math.random() < 0.1, // 10% chance
211230
isCompact: Math.random() < 0.05, // 5% chance
231+
isCrowded: Math.random() < 0.05, // 5% chance
212232
startingGold: Math.random() < 0.05 ? 5_000_000 : undefined, // 5% chance
213233
};
214234
}
215235

236+
// Maps with smallest player count (third number of calculateMapPlayerCounts) < 50 don't support compact map in team games
237+
// (not enough players after 75% player reduction for compact maps)
216238
private async supportsCompactMapForTeams(map: GameMapType): Promise<boolean> {
217-
// Maps with smallest player count < 50 don't support compact map in team games
218-
// The smallest player count is the 3rd number in the player counts array
219239
const landTiles = await getMapLandTiles(map);
220240
const [, , smallest] = this.calculateMapPlayerCounts(landTiles);
221241
return smallest >= 50;
222242
}
223243

244+
private async getCrowdedMaxPlayers(
245+
map: GameMapType,
246+
isCompact: boolean,
247+
): Promise<number | undefined> {
248+
const landTiles = await getMapLandTiles(map);
249+
const [firstPlayerCount] = this.calculateMapPlayerCounts(landTiles);
250+
if (firstPlayerCount <= 60) {
251+
return isCompact ? 60 : 125;
252+
}
253+
return undefined;
254+
}
255+
224256
private async lobbyMaxPlayers(
225257
map: GameMapType,
226258
mode: GameMode,
@@ -236,7 +268,15 @@ export class MapPlaylist {
236268
if (isCompactMap) {
237269
p = Math.max(3, Math.floor(p * 0.25));
238270
}
239-
if (numPlayerTeams === undefined) return p;
271+
return this.adjustForTeams(p, numPlayerTeams);
272+
}
273+
274+
private adjustForTeams(
275+
playerCount: number,
276+
numPlayerTeams: TeamCountConfig | undefined,
277+
): number {
278+
if (numPlayerTeams === undefined) return playerCount;
279+
let p = playerCount;
240280
switch (numPlayerTeams) {
241281
case Duos:
242282
p -= p % 2;

tests/util/TestServerConfig.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export class TestServerConfig implements ServerConfig {
8080
throw new Error("Method not implemented.");
8181
}
8282
getRandomPublicGameModifiers(): PublicGameModifiers {
83-
return { isCompact: false, isRandomSpawn: false };
83+
return { isCompact: false, isRandomSpawn: false, isCrowded: false };
8484
}
8585
async supportsCompactMapForTeams(): Promise<boolean> {
8686
throw new Error("Method not implemented.");

0 commit comments

Comments
 (0)