Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/ProductionQueue.js
Show First 20 Lines • Show All 257 Lines • ▼ Show 20 Lines | if (this.queue.length < MAX_QUEUE_SIZE) | ||||
{ | { | ||||
if (!Number.isInteger(count) || count <= 0) | if (!Number.isInteger(count) || count <= 0) | ||||
{ | { | ||||
error("Invalid batch count " + count); | error("Invalid batch count " + count); | ||||
return; | return; | ||||
} | } | ||||
// Find the template data so we can determine the build costs | // Find the template data so we can determine the build costs | ||||
var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); | let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); | ||||
var template = cmpTemplateManager.GetTemplate(templateName); | let template = cmpTemplateManager.GetTemplate(templateName); | ||||
if (!template) | if (!template) | ||||
return; | return; | ||||
if (template.Promotion) | if (template.Promotion && !ApplyValueModificationsToTemplate("Promotion/RequiredXp", +template.Promotion.RequiredXp, cmpPlayer.GetPlayerID(), template)) | ||||
wraitii: I think == 0 is more understandable here. | |||||
{ | |||||
var requiredXp = ApplyValueModificationsToTemplate("Promotion/RequiredXp", +template.Promotion.RequiredXp, cmpPlayer.GetPlayerID(), template); | |||||
if (requiredXp == 0) | |||||
{ | { | ||||
this.AddBatch(template.Promotion.Entity, type, count, metadata); | this.AddBatch(template.Promotion.Entity, type, count, metadata); | ||||
Not Done Inline ActionsInline merge ifs. if (template.Promotion && ApplyValueModificationsToTemplate("Promotion/RequiredXp", +template.Promotion.RequiredXp, cmpPlayer.GetPlayerID(), template) == 0) { this.AddBatch(template.Promotion.Entity, type, count, metadata); return; } Stan: Inline merge ifs.
```lang=js
if (template.Promotion && ApplyValueModificationsToTemplate… | |||||
return; | return; | ||||
} | } | ||||
} | |||||
// Apply a time discount to larger batches. | // Apply a time discount to larger batches. | ||||
var timeMult = this.GetBatchTime(count); | let timeMult = this.GetBatchTime(count); | ||||
// We need the costs after tech modifications | // We need the costs after tech modifications | ||||
// Obviously we don't have the entities yet, so we must use template data | // Obviously we don't have the entities yet, so we must use template data | ||||
var costs = {}; | let costs = {}; | ||||
var totalCosts = {}; | let totalCosts = {}; | ||||
var buildTime = ApplyValueModificationsToTemplate("Cost/BuildTime", +template.Cost.BuildTime, cmpPlayer.GetPlayerID(), template); | let buildTime = ApplyValueModificationsToTemplate("Cost/BuildTime", +template.Cost.BuildTime, cmpPlayer.GetPlayerID(), template); | ||||
var time = timeMult * buildTime; | let time = timeMult * buildTime; | ||||
for (let res in template.Cost.Resources) | for (let res in template.Cost.Resources) | ||||
{ | { | ||||
costs[res] = ApplyValueModificationsToTemplate("Cost/Resources/"+res, +template.Cost.Resources[res], cmpPlayer.GetPlayerID(), template); | costs[res] = ApplyValueModificationsToTemplate("Cost/Resources/"+res, +template.Cost.Resources[res], cmpPlayer.GetPlayerID(), template); | ||||
totalCosts[res] = Math.floor(count * costs[res]); | totalCosts[res] = Math.floor(count * costs[res]); | ||||
} | } | ||||
var population = ApplyValueModificationsToTemplate("Cost/Population", +template.Cost.Population, cmpPlayer.GetPlayerID(), template); | |||||
// TrySubtractResources should report error to player (they ran out of resources) | // TrySubtractResources should report error to player (they ran out of resources) | ||||
Not Done Inline ActionsCompute it in the object line 321 directly, this way it's not computed if we early return. Stan: Compute it in the object line 321 directly, this way it's not computed if we early return. | |||||
if (!cmpPlayer.TrySubtractResources(totalCosts)) | if (!cmpPlayer.TrySubtractResources(totalCosts)) | ||||
return; | return; | ||||
// Update entity count in the EntityLimits component | // Update entity count in the EntityLimits component | ||||
if (template.TrainingRestrictions) | if (template.TrainingRestrictions) | ||||
{ | { | ||||
var unitCategory = template.TrainingRestrictions.Category; | let unitCategory = template.TrainingRestrictions.Category; | ||||
var cmpPlayerEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits); | let cmpPlayerEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits); | ||||
// Do not train more units than can | |||||
Not Done Inline ActionsComments start with Capitals. Stan: Comments start with Capitals. | |||||
Not Done Inline ActionsI don't think the formulation is right. Stan: I don't think the formulation is right. | |||||
if (cmpPlayerEntityLimits.GetCounts()[unitCategory] + count > cmpPlayerEntityLimits.GetLimits()[unitCategory]) | |||||
Not Done Inline ActionsWhy add this here? wraitii: Why add this here? | |||||
return; | |||||
cmpPlayerEntityLimits.ChangeCount(unitCategory, count); | cmpPlayerEntityLimits.ChangeCount(unitCategory, count); | ||||
} | } | ||||
this.queue.push({ | this.queue.push({ | ||||
"id": this.nextID++, | "id": this.nextID++, | ||||
"player": cmpPlayer.GetPlayerID(), | "player": cmpPlayer.GetPlayerID(), | ||||
"unitTemplate": templateName, | "unitTemplate": templateName, | ||||
"count": count, | "count": count, | ||||
"metadata": metadata, | "metadata": metadata, | ||||
"resources": costs, | "resources": costs, | ||||
"population": population, | "population": ApplyValueModificationsToTemplate("Cost/Population", +template.Cost.Population, cmpPlayer.GetPlayerID(), template), | ||||
"productionStarted": false, | "productionStarted": false, | ||||
"timeTotal": time*1000, | "timeTotal": time*1000, | ||||
"timeRemaining": time*1000, | "timeRemaining": time*1000, | ||||
}); | }); | ||||
// Call the related trigger event | // Call the related trigger event | ||||
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); | let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); | ||||
cmpTrigger.CallEvent("TrainingQueued", { "playerid": cmpPlayer.GetPlayerID(), "unitTemplate": templateName, "count": count, "metadata": metadata, "trainerEntity": this.entity }); | cmpTrigger.CallEvent("TrainingQueued", { "playerid": cmpPlayer.GetPlayerID(), "unitTemplate": templateName, "count": count, "metadata": metadata, "trainerEntity": this.entity }); | ||||
} | } | ||||
else if (type == "technology") | else if (type == "technology") | ||||
{ | { | ||||
if (!TechnologyTemplates.Has(templateName)) | if (!TechnologyTemplates.Has(templateName)) | ||||
return; | return; | ||||
if (!this.GetTechnologiesList().some(tech => | if (!this.GetTechnologiesList().some(tech => | ||||
Show All 15 Lines | else if (type == "technology") | ||||
cost[res] = Math.floor((techCostMultiplier[res] || 1) * template.cost[res]); | cost[res] = Math.floor((techCostMultiplier[res] || 1) * template.cost[res]); | ||||
// TrySubtractResources should report error to player (they ran out of resources) | // TrySubtractResources should report error to player (they ran out of resources) | ||||
if (!cmpPlayer.TrySubtractResources(cost)) | if (!cmpPlayer.TrySubtractResources(cost)) | ||||
return; | return; | ||||
// Tell the technology manager that we have started researching this so that people can't research the same | // Tell the technology manager that we have started researching this so that people can't research the same | ||||
// thing twice. | // thing twice. | ||||
var cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager); | let cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager); | ||||
cmpTechnologyManager.QueuedResearch(templateName, this.entity); | cmpTechnologyManager.QueuedResearch(templateName, this.entity); | ||||
if (this.queue.length == 0) | if (this.queue.length == 0) | ||||
cmpTechnologyManager.StartedResearch(templateName, false); | cmpTechnologyManager.StartedResearch(templateName, false); | ||||
this.queue.push({ | this.queue.push({ | ||||
"id": this.nextID++, | "id": this.nextID++, | ||||
"player": cmpPlayer.GetPlayerID(), | "player": cmpPlayer.GetPlayerID(), | ||||
"count": 1, | "count": 1, | ||||
"technologyTemplate": templateName, | "technologyTemplate": templateName, | ||||
"resources": cost, | "resources": cost, | ||||
"productionStarted": false, | "productionStarted": false, | ||||
"timeTotal": time*1000, | "timeTotal": time*1000, | ||||
"timeRemaining": time*1000, | "timeRemaining": time*1000, | ||||
}); | }); | ||||
// Call the related trigger event | // Call the related trigger event | ||||
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); | let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); | ||||
cmpTrigger.CallEvent("ResearchQueued", { "playerid": cmpPlayer.GetPlayerID(), "technologyTemplate": templateName, "researcherEntity": this.entity }); | cmpTrigger.CallEvent("ResearchQueued", { "playerid": cmpPlayer.GetPlayerID(), "technologyTemplate": templateName, "researcherEntity": this.entity }); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
warn("Tried to add invalid item of type \"" + type + "\" and template \"" + templateName + "\" to a production queue"); | warn("Tried to add invalid item of type \"" + type + "\" and template \"" + templateName + "\" to a production queue"); | ||||
return; | return; | ||||
} | } | ||||
Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); | Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); | ||||
// If this is the first item in the queue, start the timer | // If this is the first item in the queue, start the timer | ||||
if (!this.timer) | if (!this.timer) | ||||
{ | { | ||||
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | ||||
this.timer = cmpTimer.SetTimeout(this.entity, IID_ProductionQueue, "ProgressTimeout", g_ProgressInterval, {}); | this.timer = cmpTimer.SetTimeout(this.entity, IID_ProductionQueue, "ProgressTimeout", g_ProgressInterval, {}); | ||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
var notification = { "players": [cmpPlayer.GetPlayerID()], "message": markForTranslation("The production queue is full."), "translateMessage": true }; | let notification = { "players": [cmpPlayer.GetPlayerID()], "message": markForTranslation("The production queue is full."), "translateMessage": true }; | ||||
var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); | let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); | ||||
cmpGUIInterface.PushNotification(notification); | cmpGUIInterface.PushNotification(notification); | ||||
} | } | ||||
}; | }; | ||||
/* | /* | ||||
* Removes an existing batch of units from the production queue. | * Removes an existing batch of units from the production queue. | ||||
* Refunds resource costs and population reservations. | * Refunds resource costs and population reservations. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* This function creates the entities and places them in world if possible | * This function creates the entities and places them in world if possible | ||||
* and returns the number of successfully created entities. | * and returns the number of successfully created entities. | ||||
* (some of these entities may be garrisoned directly if autogarrison, the others are spawned). | * (some of these entities may be garrisoned directly if autogarrison, the others are spawned). | ||||
*/ | */ | ||||
ProductionQueue.prototype.SpawnUnits = function(templateName, count, metadata) | ProductionQueue.prototype.SpawnUnits = function(templateName, count, metadata) | ||||
{ | { | ||||
var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint); | let cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint); | ||||
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | ||||
var cmpRallyPoint = Engine.QueryInterface(this.entity, IID_RallyPoint); | let cmpRallyPoint = Engine.QueryInterface(this.entity, IID_RallyPoint); | ||||
var createdEnts = []; | let createdEnts = []; | ||||
var spawnedEnts = []; | let spawnedEnts = []; | ||||
if (this.entityCache.length == 0) | |||||
{ | |||||
// We need entities to test spawning, but we don't want to waste resources, | // We need entities to test spawning, but we don't want to waste resources, | ||||
// so only create them once and use as needed | // so only create them once and use as needed | ||||
for (var i = 0; i < count; ++i) | if (this.entityCache.length == 0) | ||||
{ | for (let i = 0; i < count; ++i) | ||||
Not Done Inline ActionsInline ? Stan: Inline ? | |||||
var ent = Engine.AddEntity(templateName); | this.entityCache.push(Engine.AddEntity(templateName)); | ||||
this.entityCache.push(ent); | |||||
// Decrement entity count in the EntityLimits component | |||||
// since it will be increased by EntityLimits.OnGlobalOwnershipChanged function, | |||||
// i.e. we replace a 'trained' entity to an 'alive' one | |||||
var cmpTrainingRestrictions = Engine.QueryInterface(ent, IID_TrainingRestrictions); | |||||
if (cmpTrainingRestrictions) | |||||
{ | |||||
var unitCategory = cmpTrainingRestrictions.GetCategory(); | |||||
var cmpPlayerEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits); | |||||
cmpPlayerEntityLimits.ChangeCount(unitCategory, -1); | |||||
} | |||||
} | |||||
} | |||||
let cmpAutoGarrison; | let cmpAutoGarrison; | ||||
if (cmpRallyPoint) | if (cmpRallyPoint) | ||||
{ | { | ||||
let data = cmpRallyPoint.GetData()[0]; | let data = cmpRallyPoint.GetData()[0]; | ||||
if (data && data.target && data.target == this.entity && data.command == "garrison") | if (data && data.target && data.target == this.entity && data.command == "garrison") | ||||
cmpAutoGarrison = Engine.QueryInterface(this.entity, IID_GarrisonHolder); | cmpAutoGarrison = Engine.QueryInterface(this.entity, IID_GarrisonHolder); | ||||
} | } | ||||
Show All 18 Lines | if (garrisoned) | ||||
if (cmpUnitAI) | if (cmpUnitAI) | ||||
cmpUnitAI.Autogarrison(this.entity); | cmpUnitAI.Autogarrison(this.entity); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
let pos = cmpFootprint.PickSpawnPoint(ent); | let pos = cmpFootprint.PickSpawnPoint(ent); | ||||
if (pos.y < 0) | if (pos.y < 0) | ||||
break; | break; | ||||
Not Done Inline ActionsRemove tab. Stan: Remove tab. | |||||
let cmpNewPosition = Engine.QueryInterface(ent, IID_Position); | let cmpNewPosition = Engine.QueryInterface(ent, IID_Position); | ||||
cmpNewPosition.JumpTo(pos.x, pos.z); | cmpNewPosition.JumpTo(pos.x, pos.z); | ||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | ||||
if (cmpPosition) | if (cmpPosition) | ||||
cmpNewPosition.SetYRotation(cmpPosition.GetPosition().horizAngleTo(pos)); | cmpNewPosition.SetYRotation(cmpPosition.GetPosition().horizAngleTo(pos)); | ||||
spawnedEnts.push(ent); | spawnedEnts.push(ent); | ||||
} | } | ||||
// Decrement entity count in the EntityLimits component | |||||
// since it will be increased by EntityLimits.OnGlobalOwnershipChanged function, | |||||
// i.e. we replace a 'trained' entity to an 'alive' one | |||||
// Must be after spawn check so EntityLimits decremetns only if unit spawns | |||||
Not Done Inline ActionsExplain the why not the what here, so replace wraitii: Explain the why not the what here, so replace
`Do not move it before spawn check` by something… | |||||
let cmpTrainingRestrictions = Engine.QueryInterface(ent, IID_TrainingRestrictions); | |||||
if (cmpTrainingRestrictions) | |||||
{ | |||||
let unitCategory = cmpTrainingRestrictions.GetCategory(); | |||||
let cmpPlayerEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits); | |||||
cmpPlayerEntityLimits.ChangeCount(unitCategory, -1); | |||||
} | |||||
cmpNewOwnership.SetOwner(cmpOwnership.GetOwner()); | cmpNewOwnership.SetOwner(cmpOwnership.GetOwner()); | ||||
let cmpPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker); | let cmpPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker); | ||||
if (cmpPlayerStatisticsTracker) | if (cmpPlayerStatisticsTracker) | ||||
cmpPlayerStatisticsTracker.IncreaseTrainedUnitsCounter(ent); | cmpPlayerStatisticsTracker.IncreaseTrainedUnitsCounter(ent); | ||||
// Play a sound, but only for the first in the batch (to avoid nasty phasing effects) | // Play a sound, but only for the first in the batch (to avoid nasty phasing effects) | ||||
if (createdEnts.length == 0) | if (createdEnts.length == 0) | ||||
PlaySound("trained", ent); | PlaySound("trained", ent); | ||||
this.entityCache.shift(); | this.entityCache.shift(); | ||||
createdEnts.push(ent); | createdEnts.push(ent); | ||||
} | } | ||||
if (spawnedEnts.length > 0 && !cmpAutoGarrison) | if (spawnedEnts.length > 0 && !cmpAutoGarrison) | ||||
{ | { | ||||
// If a rally point is set, walk towards it (in formation) using a suitable command based on where the | // If a rally point is set, walk towards it (in formation) using a suitable command based on where the | ||||
// rally point is placed. | // rally point is placed. | ||||
if (cmpRallyPoint) | if (cmpRallyPoint) | ||||
{ | { | ||||
var rallyPos = cmpRallyPoint.GetPositions()[0]; | let rallyPos = cmpRallyPoint.GetPositions()[0]; | ||||
if (rallyPos) | if (rallyPos) | ||||
{ | { | ||||
var commands = GetRallyPointCommands(cmpRallyPoint, spawnedEnts); | let commands = GetRallyPointCommands(cmpRallyPoint, spawnedEnts); | ||||
for (var com of commands) | for (let com of commands) | ||||
ProcessCommand(cmpOwnership.GetOwner(), com); | ProcessCommand(cmpOwnership.GetOwner(), com); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (createdEnts.length > 0) | if (createdEnts.length > 0) | ||||
Engine.PostMessage(this.entity, MT_TrainingFinished, { | Engine.PostMessage(this.entity, MT_TrainingFinished, { | ||||
"entities": createdEnts, | "entities": createdEnts, | ||||
▲ Show 20 Lines • Show All 179 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
I think == 0 is more understandable here.