mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
Prioritize least busy buildings and enforce max training queue limit
getTotalQueueTime(queue) calculates total remaining queue time of a production building. getBuildingsSortedByQueueTime(entities), sorts building selection by their queued training time.
This commit is contained in:
parent
32e5520507
commit
a6460189ed
1 changed files with 34 additions and 8 deletions
|
|
@ -1596,6 +1596,30 @@ function updateDefaultBatchSize()
|
|||
g_BatchSize = getDefaultBatchTrainingSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the total remaining production queue time of a building.
|
||||
*/
|
||||
function getTotalQueueTime(queue)
|
||||
{
|
||||
return queue.reduce((sum, item) => sum + (item.timeRemaining ?? item.timeTotal ?? 0), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given production building selection sorted by their current
|
||||
* queued training time, from lowest to highest.
|
||||
*/
|
||||
function getBuildingsSortedByQueueTime(entities)
|
||||
{
|
||||
return entities.map(entity =>
|
||||
{
|
||||
const queue = GetEntityState(entity)?.production?.queue || [];
|
||||
return {
|
||||
"entity": entity,
|
||||
"totalQueueTime": getTotalQueueTime(queue)
|
||||
};
|
||||
}).sort((a, b) => a.totalQueueTime - b.totalQueueTime).map(building => building.entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the unit shown at position to the training queue for all entities in the selection.
|
||||
* @param {number} position - The position of the template to train.
|
||||
|
|
@ -1628,6 +1652,7 @@ function addTrainingToQueue(selection, trainEntType, playerState)
|
|||
if (!decrement)
|
||||
template = GetTemplateData(trainEntType);
|
||||
|
||||
const sortedBuildings = getBuildingsSortedByQueueTime(appropriateBuildings);
|
||||
// Batch training only possible if we can train at least 2 units.
|
||||
if (Engine.HotkeyIsPressed("session.batchtrain") && (canBeAddedCount == undefined || canBeAddedCount > 1))
|
||||
{
|
||||
|
|
@ -1638,8 +1663,8 @@ function addTrainingToQueue(selection, trainEntType, playerState)
|
|||
// If the order changed, we have a new selection and we should create a new batch.
|
||||
// If we're already creating a batch of this unit (in the same structure(s)), then just extend it
|
||||
// (if training limits allow).
|
||||
if (g_BatchTrainingEntities.length == selection.length &&
|
||||
g_BatchTrainingEntities.every((ent, i) => ent == selection[i]) &&
|
||||
if (g_BatchTrainingEntities.length == sortedBuildings.length &&
|
||||
g_BatchTrainingEntities.every((ent, i) => ent == sortedBuildings[i]) &&
|
||||
g_BatchTrainingType == trainEntType)
|
||||
{
|
||||
if (decrement)
|
||||
|
|
@ -1649,7 +1674,7 @@ function addTrainingToQueue(selection, trainEntType, playerState)
|
|||
inputState = INPUT_NORMAL;
|
||||
}
|
||||
else if (canBeAddedCount == undefined ||
|
||||
canBeAddedCount > g_NumberOfBatches * getBatchTrainingSize() * appropriateBuildings.length)
|
||||
canBeAddedCount > g_NumberOfBatches * getBatchTrainingSize() * sortedBuildings.length)
|
||||
{
|
||||
if (Engine.GuiInterfaceCall("GetNeededResources", {
|
||||
"cost": multiplyEntityCosts(template, (g_NumberOfBatches + 1) * getBatchTrainingSize())
|
||||
|
|
@ -1671,14 +1696,14 @@ function addTrainingToQueue(selection, trainEntType, playerState)
|
|||
return;
|
||||
|
||||
inputState = INPUT_BATCHTRAINING;
|
||||
g_BatchTrainingEntities = selection;
|
||||
g_BatchTrainingEntities = sortedBuildings;
|
||||
g_BatchTrainingType = trainEntType;
|
||||
g_BatchTrainingEntityAllowedCount = canBeAddedCount;
|
||||
g_NumberOfBatches = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
let buildingsForTraining = appropriateBuildings;
|
||||
let buildingsForTraining = sortedBuildings;
|
||||
if (canBeAddedCount !== undefined)
|
||||
buildingsForTraining = buildingsForTraining.slice(0, canBeAddedCount);
|
||||
Engine.PostNetworkCommand({
|
||||
|
|
@ -1734,6 +1759,7 @@ function flushTrainingBatch()
|
|||
{
|
||||
const batchedSize = g_NumberOfBatches * getBatchTrainingSize();
|
||||
const appropriateBuildings = getBuildingsWhichCanTrainEntity(g_BatchTrainingEntities, g_BatchTrainingType);
|
||||
const sortedBuildings = getBuildingsSortedByQueueTime(appropriateBuildings);
|
||||
// If training limits don't allow us to train batchedSize in each appropriate structure.
|
||||
if (g_BatchTrainingEntityAllowedCount !== undefined &&
|
||||
g_BatchTrainingEntityAllowedCount < batchedSize * appropriateBuildings.length)
|
||||
|
|
@ -1742,7 +1768,7 @@ function flushTrainingBatch()
|
|||
const buildingsCountToTrainFullBatch = Math.floor(g_BatchTrainingEntityAllowedCount / batchedSize);
|
||||
Engine.PostNetworkCommand({
|
||||
"type": "train",
|
||||
"entities": appropriateBuildings.slice(0, buildingsCountToTrainFullBatch),
|
||||
"entities": sortedBuildings.slice(0, buildingsCountToTrainFullBatch),
|
||||
"template": g_BatchTrainingType,
|
||||
"count": batchedSize,
|
||||
"pushFront": Engine.HotkeyIsPressed("session.pushorderfront")
|
||||
|
|
@ -1753,7 +1779,7 @@ function flushTrainingBatch()
|
|||
if (remainer)
|
||||
Engine.PostNetworkCommand({
|
||||
"type": "train",
|
||||
"entities": [appropriateBuildings[buildingsCountToTrainFullBatch]],
|
||||
"entities": [sortedBuildings[buildingsCountToTrainFullBatch]],
|
||||
"template": g_BatchTrainingType,
|
||||
"count": remainer,
|
||||
"pushFront": Engine.HotkeyIsPressed("session.pushorderfront")
|
||||
|
|
@ -1762,7 +1788,7 @@ function flushTrainingBatch()
|
|||
else
|
||||
Engine.PostNetworkCommand({
|
||||
"type": "train",
|
||||
"entities": appropriateBuildings,
|
||||
"entities": sortedBuildings,
|
||||
"template": g_BatchTrainingType,
|
||||
"count": batchedSize,
|
||||
"pushFront": Engine.HotkeyIsPressed("session.pushorderfront")
|
||||
|
|
|
|||
Loading…
Reference in a new issue