Use a slider for population cap

To allow Unlimited / Infinity the slider can't be linear.

Refs: #2593
This commit is contained in:
phosit 2025-12-31 12:20:11 +01:00
parent e79f8ea327
commit 38eb999ff9
No known key found for this signature in database
GPG key ID: C9430B600671C268
10 changed files with 58 additions and 54 deletions

View file

@ -35,8 +35,9 @@ GameSettings.prototype.Attributes.Population = class Population extends GameSett
if (this.getLegacySetting(attribs, "PopulationCapType") !== undefined)
this.setPopCapType(this.getLegacySetting(attribs, "PopulationCapType"));
if (this.getLegacySetting(attribs, "PopulationCap") !== undefined)
this.setPopCap(this.getLegacySetting(attribs, "PopulationCap"));
const cap = this.getLegacySetting(attribs, "PopulationCap");
if (cap !== undefined)
this.setPopCap(cap ?? Infinity);
}
onMapChange()
@ -64,7 +65,9 @@ GameSettings.prototype.Attributes.Population = class Population extends GameSett
setPopCapType(capType)
{
this.capType = capType;
const oldFactor = this.currentData?.Factor;
this.currentData = g_Settings.PopulationCapacities.find(type => type.Name == capType);
this.setPopCap(this.currentData.Options.Default);
this.setPopCap(10 * Math.round(
(this.cap && oldFactor ? (this.cap / oldFactor) : 1) * this.currentData.Factor / 10));
}
};

View file

@ -382,9 +382,9 @@ function getGameDescription(initAttributes, mapCache)
"value":
initAttributes.settings.PlayerData?.some(pData => pData?.PopulationLimit !== undefined) ?
translateWithContext("population capacity", "Per Player") :
initAttributes.settings.PopulationCap < 10000 ?
initAttributes.settings.PopulationCap :
translateWithContext("population capacity", "Unlimited")
initAttributes.settings.PopulationCap === Infinity ?
translateWithContext("population capacity", "Unlimited") :
initAttributes.settings.PopulationCap
});
titles.push({

View file

@ -358,7 +358,7 @@ function translatePopulationCapacity(popCap, popCapType)
if (!popCapTypeData)
return translateWithContext("population capacity", "Unknown");
return popCap >= 10000 ?
return popCap === Infinity ?
translateWithContext("population capacity", "Unlimited") :
sprintf(translate("%(populationCapacity)s (%(populationCapacityType)s)"), {
"populationCapacity": popCap,

View file

@ -20,6 +20,7 @@ class GameSettingsGuiData
Serialize()
{
const ret = {
"linearPopulationCapacity": this.linearPopulationCapacity,
"mapFilter": this.mapFilter.filter
};
if (Object.keys(this.lockSettings).length)
@ -30,6 +31,7 @@ class GameSettingsGuiData
Deserialize(data)
{
this.mapFilter.filter = data.mapFilter;
this.linearPopulationCapacity = data.linearPopulationCapacity;
this.lockSettings = data?.lockSettings || {};
}
}

View file

@ -2,7 +2,7 @@ const CAPTYPE_PLAYER_POPULATION = "player";
const CAPTYPE_TEAM_POPULATION = "team";
const CAPTYPE_WORLD_POPULATION = "world";
GameSettingControls.PopulationCap = class PopulationCap extends GameSettingControlDropdown
GameSettingControls.PopulationCap = class PopulationCap extends GameSettingControlSlider
{
constructor(...args)
{
@ -15,38 +15,52 @@ GameSettingControls.PopulationCap = class PopulationCap extends GameSettingContr
this.render();
}
round(value)
{
return Math.round(value / 10) * 10;
}
linearToLogarythmic(value)
{
return this.round((1 / (1 - value) + 28 * value / (1 + 5 * value)) *
g_GameSettings.population.currentData.Factor / 6);
}
render()
{
this.setEnabled(g_GameSettings.map.type != "scenario" && !g_GameSettings.population.perPlayer);
this.title.caption = g_GameSettings.population.currentData.CapTitle;
if (g_GameSettings.population.perPlayer)
this.label.caption = this.PerPlayerCaption;
if (!this.enabled)
return;
else
this.setTooltip(0);
this.dropdown.list_data = g_GameSettings.population.currentData.Options.List;
this.dropdown.list = this.dropdown.list_data.map(population =>
population < 10000 ? population : translate("Unlimited")
);
this.setSelectedValue(g_GameSettings.population.cap);
const linear = this.gameSettingsController.guiData.linearPopulationCapacity ?? 0.5;
const display = g_GameSettings.population.cap === Infinity ? translate("Unlimited") :
g_GameSettings.population.cap;
this.setSelectedValue(linear, display);
}
onHoverChange()
onValueChange(value)
{
this.gameSettingsController.guiData.linearPopulationCapacity = value;
const popCap = this.linearToLogarythmic(value);
g_GameSettings.population.setPopCap(popCap);
this.setTooltip(popCap);
this.gameSettingsController.setNetworkInitAttributes();
}
setTooltip(popCap)
{
if (this.dropdown.hovered == -1)
return;
let tooltip = g_GameSettings.population.currentData.CapTooltip;
if (this.canTotalPopExceedRecommendedMax())
if (this.canTotalPopExceedRecommendedMax(popCap))
tooltip = setStringTags(this.WarningTooltip, this.WarningTags);
this.dropdown.tooltip = tooltip;
this.slider.tooltip = tooltip;
}
canTotalPopExceedRecommendedMax()
canTotalPopExceedRecommendedMax(popCap)
{
const popCap = g_GameSettings.population.currentData.Options.List[this.dropdown.hovered];
const nbPlayers = g_GameSettings.playerCount.nbPlayers;
const nbTeams = g_GameSettings.playerTeam.values.reduce((teamList, team) =>
{
@ -86,3 +100,6 @@ GameSettingControls.PopulationCap.prototype.WarningTags = {
* It means a 4v4 with 150 population can still run nicely, but more than that might "lag".
*/
GameSettingControls.PopulationCap.prototype.PopulationCapacityRecommendation = 1200;
GameSettingControls.PopulationCap.prototype.MinValue = 0;
GameSettingControls.PopulationCap.prototype.MaxValue = 1;

View file

@ -95,21 +95,11 @@ function initMapNameFilter(filters)
*/
function initPopCapFilter(filters)
{
var populationFilter = Engine.GetGUIObjectByName("populationFilter");
const populationFilter = Engine.GetGUIObjectByName("populationFilter");
const popCapSet = new Set(g_Replays.map(replay => replay.attribs.settings.PopulationCap));
const popCapOptions = [...popCapSet.values()].sort((a, b) => b - a);
// Merge the pop cap options of all pop cap types into one single list.
const popCapOptions = g_PopulationCapacities.Options
.map(item => item.List)
.flat()
.reduce((list, cap) =>
{
if (!list.includes(cap))
list.push(cap);
return list;
}, [])
.sort((a, b) => a > b);
populationFilter.list = [translateWithContext("population capacity", "Any")].concat(popCapOptions.map(cap => cap >= 10000 ? "Unlimited" : cap));
populationFilter.list = [translateWithContext("population capacity", "Any")].concat(popCapOptions.map(cap => cap === Infinity ? "Unlimited" : cap));
populationFilter.list_data = [""].concat(popCapOptions);
if (filters?.popCap)

View file

@ -174,8 +174,7 @@ function sanitizeInitAttributes(attribs)
if (!attribs.settings.PlayerData)
attribs.settings.PlayerData = [];
if (!attribs.settings.PopulationCap)
attribs.settings.PopulationCap = 300;
attribs.settings.PopulationCap ??= Infinity;
if (!attribs.settings.PopulationCapType)
attribs.settings.PopulationCapType =

View file

@ -18,7 +18,9 @@ class CounterPopulation
rebuild(playerState, getAllyStatTooltip)
{
this.count.caption = sprintf(translate(this.CounterCaption), playerState);
const state = Object.fromEntries(Object.entries(playerState).map(([key, value]) =>
[key, value === Infinity ? translateWithContext("In other places refered as 'Unlimited', here is to litle space.", "∞") : value]));
this.count.caption = sprintf(translate(this.CounterCaption), state);
let total = 0;
for (const resCode of g_ResourceData.GetCodes())
total += playerState.resourceGatherers[resCode];

View file

@ -9,10 +9,7 @@
"Tooltip": "Locked population cap for all players.",
"CapTooltip": "Choose the player population cap.",
"Default": true,
"Options": {
"List": [50, 100, 150, 200, 250, 300, 10000],
"Default": 300
}
"Factor": 300
},
{
"Name": "team",
@ -20,10 +17,7 @@
"CapTitle": "Team Population Cap",
"Tooltip": "Distributes a team's total population cap evenly over all its living members. Enables the setting 'Locked teams'.",
"CapTooltip": "Choose the team population cap.",
"Options": {
"List": [100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 700, 800, 1000, 10000],
"Default": 400
}
"Factor": 400
},
{
"Name": "world",
@ -31,10 +25,7 @@
"CapTitle": "World Population Cap",
"Tooltip": "Distributes the total population cap evenly over all living players.",
"CapTooltip": "Choose the world population cap.",
"Options": {
"List": [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1600, 2000, 2400, 10000],
"Default": 600
}
"Factor": 600
}
]
}

View file

@ -65,7 +65,7 @@ function InitGame(settings)
}
{
const popCap = settings.PopulationCap || 300;
const popCap = settings.PopulationCap ?? Infinity;
const cmpPopulationCapManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PopulationCapManager);
const nonGaiaPlayers = settings.PlayerData.slice(1);
if (nonGaiaPlayers.some(player => player.PopulationLimit))