Index: binaries/data/mods/public/maps/scripts/TriggerHelper.js =================================================================== --- binaries/data/mods/public/maps/scripts/TriggerHelper.js +++ binaries/data/mods/public/maps/scripts/TriggerHelper.js @@ -121,7 +121,11 @@ for (let i = 0; i < count; ++i) { - let ent = Engine.AddEntity(template); + const upgradedTemplate = GetUpgradedTemplate(owner, template); + if (upgradedTemplate !== template) + warn(`tried to spawn template '${template}' but upgraded template ${upgradedTemplate} will be spawned instead. You might want to create a template that is not affected by this promotion.`); + + let ent = Engine.AddEntity(upgradedTemplate); let cmpEntPosition = Engine.QueryInterface(ent, IID_Position); if (!cmpEntPosition) { Index: binaries/data/mods/public/simulation/components/Trainer.js =================================================================== --- binaries/data/mods/public/simulation/components/Trainer.js +++ binaries/data/mods/public/simulation/components/Trainer.js @@ -554,7 +554,7 @@ return entMap; } - token = this.GetUpgradedTemplate(token); + token = GetUpgradedTemplate(cmpPlayer.GetPlayerID(), token); entMap.set(rawToken, token); updateAllQueuedTemplate(rawToken, token); return entMap; @@ -563,32 +563,6 @@ this.CalculateTrainCostMultiplier(); }; -/* - * Returns the upgraded template name if necessary. - */ -Trainer.prototype.GetUpgradedTemplate = function(templateName) -{ - const cmpPlayer = QueryOwnerInterface(this.entity); - if (!cmpPlayer) - return templateName; - - const cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); - let template = cmpTemplateManager.GetTemplate(templateName); - while (template && template.Promotion !== undefined) - { - const requiredXp = ApplyValueModificationsToTemplate( - "Promotion/RequiredXp", - +template.Promotion.RequiredXp, - cmpPlayer.GetPlayerID(), - template); - if (requiredXp > 0) - break; - templateName = template.Promotion.Entity; - template = cmpTemplateManager.GetTemplate(templateName); - } - return templateName; -}; - Trainer.prototype.CalculateTrainCostMultiplier = function() { for (const res of Resources.GetCodes().concat(["time"])) Index: binaries/data/mods/public/simulation/components/tests/test_Trainer.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_Trainer.js +++ binaries/data/mods/public/simulation/components/tests/test_Trainer.js @@ -55,9 +55,19 @@ "GetCiv": () => "iber" }); +let GetUpgradedTemplate = (_, template) => template === "units/iber/cavalry_javelineer_b" ? "units/iber/cavalry_javelineer_a" : template; +Engine.RegisterGlobal("GetUpgradedTemplate", GetUpgradedTemplate); cmpTrainer.CalculateEntitiesMap(); TS_ASSERT_UNEVAL_EQUALS( cmpTrainer.GetEntitiesList(), + ["units/iber/cavalry_javelineer_a", "units/iber/infantry_swordsman_b", "units/iber/support_female_citizen"] +); + +GetUpgradedTemplate = (_, template) => template; +Engine.RegisterGlobal("GetUpgradedTemplate", GetUpgradedTemplate); +cmpTrainer.CalculateEntitiesMap(); +TS_ASSERT_UNEVAL_EQUALS( + cmpTrainer.GetEntitiesList(), ["units/iber/cavalry_javelineer_b", "units/iber/infantry_swordsman_b", "units/iber/support_female_citizen"] ); Index: binaries/data/mods/public/simulation/helpers/Transform.js =================================================================== --- binaries/data/mods/public/simulation/helpers/Transform.js +++ binaries/data/mods/public/simulation/helpers/Transform.js @@ -294,5 +294,30 @@ } } +/** + * @param {number} playerId - the player id to check technologies for. + * @param {string} templateName - the original template name. + * @returns the upgraded template name if it exists else the original template. + */ +function GetUpgradedTemplate(playerId, templateName) +{ + const cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); + let template = cmpTemplateManager.GetTemplate(templateName); + while (template && template.Promotion !== undefined) + { + const requiredXp = ApplyValueModificationsToTemplate( + "Promotion/RequiredXp", + +template.Promotion.RequiredXp, + playerId, + template); + if (requiredXp > 0) + break; + templateName = template.Promotion.Entity; + template = cmpTemplateManager.GetTemplate(templateName); + } + return templateName; +}; + +Engine.RegisterGlobal("GetUpgradedTemplate", GetUpgradedTemplate); Engine.RegisterGlobal("ChangeEntityTemplate", ChangeEntityTemplate); Engine.RegisterGlobal("ObstructionsBlockingTemplateChange", ObstructionsBlockingTemplateChange); Index: binaries/data/mods/public/simulation/helpers/tests/test_Transform.js =================================================================== --- binaries/data/mods/public/simulation/helpers/tests/test_Transform.js +++ binaries/data/mods/public/simulation/helpers/tests/test_Transform.js @@ -0,0 +1,41 @@ +Engine.LoadHelperScript("Transform.js"); + +const template1 = "template_a"; +const template2 = "template_b"; +const template3 = "template_c"; +const template4 = "template_d"; +const affectedClasses = "CitizenSoldier"; +const playerId1 = 1; +const playerId2 = 2; + +AddMock(SYSTEM_ENTITY, IID_TemplateManager, { + "GetTemplate": function (template) { + if (template === template1 || template === template4) + return {}; + + return { + "Identity": { + "Classes": { "_string": template === template3 ? "" : affectedClasses } + }, + "Promotion": { + "Entity": template4, + "RequiredXp": "1000" + } + }; + }, +}); + +let applyValueModificationsToTemplate = function(_, current_value, playerID, template) +{ + return playerID === playerId1 && template.Identity.Classes._string === affectedClasses ? 0 : current_value; +} + +Engine.RegisterGlobal("ApplyValueModificationsToTemplate", applyValueModificationsToTemplate); + +TS_ASSERT_EQUALS(GetUpgradedTemplate(playerId1, template1), template1); +TS_ASSERT_EQUALS(GetUpgradedTemplate(playerId1, template2), template4); +TS_ASSERT_EQUALS(GetUpgradedTemplate(playerId1, template3), template3); + +TS_ASSERT_EQUALS(GetUpgradedTemplate(playerId2, template1), template1); +TS_ASSERT_EQUALS(GetUpgradedTemplate(playerId2, template2), template2); +TS_ASSERT_EQUALS(GetUpgradedTemplate(playerId2, template3), template3);