Index: binaries/data/mods/public/globalscripts/Templates.js =================================================================== --- binaries/data/mods/public/globalscripts/Templates.js +++ binaries/data/mods/public/globalscripts/Templates.js @@ -305,9 +305,6 @@ for (let resCode in template.Cost.Resources) ret.cost[resCode] = getEntityValue("Cost/Resources/" + resCode); - if (template.Cost.Population) - ret.cost.population = getEntityValue("Cost/Population"); - if (template.Cost.BuildTime) ret.cost.time = getEntityValue("Cost/BuildTime"); } @@ -413,9 +410,10 @@ "time": getEntityValue("Pack/Time"), }; - if (template.Population && template.Population.Bonus) + if (template.Population) ret.population = { - "bonus": getEntityValue("Population/Bonus") + "bonus": getEntityValue("Population/Bonus"), + "cost": getEntityValue("Population/Cost") }; if (template.Health) Index: binaries/data/mods/public/gui/common/tooltips.js =================================================================== --- binaries/data/mods/public/gui/common/tooltips.js +++ binaries/data/mods/public/gui/common/tooltips.js @@ -684,9 +684,13 @@ function multiplyEntityCosts(template, trainNum) { let totalCosts = {}; - for (let r of getCostTypes()) - if (template.cost[r]) - totalCosts[r] = Math.floor(template.cost[r] * trainNum); + if (template.cost) + for (let r of getCostTypes()) + if (template.cost[r]) + totalCosts[r] = Math.floor(template.cost[r] * trainNum); + + if (template.population && template.population.cost) + totalCosts.population = Math.floor(template.population.cost * trainNum); return totalCosts; } @@ -696,10 +700,11 @@ */ function getEntityCostComponentsTooltipString(template, entity, buildingsCountToTrainFullBatch = 1, fullBatchSize = 1, remainderBatch = 0) { - if (!template.cost) + if (!template.cost && !template.population) return []; + let totalCosts = multiplyEntityCosts(template, buildingsCountToTrainFullBatch * fullBatchSize + remainderBatch); - if (template.cost.time) + if (template.cost && template.cost.time) totalCosts.time = Math.ceil(template.cost.time * (entity ? Engine.GuiInterfaceCall("GetBatchTime", { "entity": entity, "batchSize": buildingsCountToTrainFullBatch > 0 ? fullBatchSize : remainderBatch @@ -899,7 +904,7 @@ sprintf(translate("Towers: %(costs)s"), { "costs": towerCosts.join(" ") }); } - if (template.cost) + if (template.cost || template.population) { let costs = getEntityCostComponentsTooltipString(template, entity, buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch).join(" "); if (costs) Index: binaries/data/mods/public/simulation/ai/petra/headquarters.js =================================================================== --- binaries/data/mods/public/simulation/ai/petra/headquarters.js +++ binaries/data/mods/public/simulation/ai/petra/headquarters.js @@ -2632,7 +2632,7 @@ { if (!item.unitTemplate) continue; - let unitPop = gameState.getTemplate(item.unitTemplate).get("Cost/Population"); + let unitPop = gameState.getTemplate(item.unitTemplate).get("Population/Cost"); if (unitPop) pop += item.count * unitPop; } Index: binaries/data/mods/public/simulation/components/AIInterface.js =================================================================== --- binaries/data/mods/public/simulation/components/AIInterface.js +++ binaries/data/mods/public/simulation/components/AIInterface.js @@ -255,7 +255,7 @@ let oldValue = +item == item ? +item : item; let newValue = ApplyValueModificationsToTemplate(valName, oldValue, msg.player, template); // Apply the same roundings as in the components - if (valName === "Player/MaxPopulation" || valName === "Cost/Population" || + if (valName === "Player/MaxPopulation" || valName === "Population/Cost" || valName === "Population/Bonus") newValue = Math.round(newValue); // TODO in some cases, we can have two opposite changes which bring us to the old value, @@ -304,7 +304,7 @@ let oldValue = +item == item ? +item : item; let newValue = ApplyValueModificationsToEntity(valName, oldValue, ent); // Apply the same roundings as in the components - if (valName === "Player/MaxPopulation" || valName === "Cost/Population" || + if (valName === "Player/MaxPopulation" || valName === "Population/Cost" || valName === "Population/Bonus") newValue = Math.round(newValue); // TODO in some cases, we can have two opposite changes which bring us to the old value, Index: binaries/data/mods/public/simulation/components/Cost.js =================================================================== --- binaries/data/mods/public/simulation/components/Cost.js +++ binaries/data/mods/public/simulation/components/Cost.js @@ -3,7 +3,6 @@ Cost.prototype.Schema = "Specifies the construction/training costs of this entity." + "" + - "1" + "20.0" + "" + "50" + @@ -12,9 +11,6 @@ "25" + "" + "" + - "" + - "" + - "" + "" + "" + "" + @@ -24,15 +20,8 @@ Cost.prototype.Init = function() { - this.populationCost = +this.template.Population; }; -Cost.prototype.GetPopCost = function() -{ - return this.populationCost; -}; - - Cost.prototype.GetBuildTime = function() { return ApplyValueModificationsToEntity("Cost/BuildTime", +this.template.BuildTime, this.entity); @@ -60,27 +49,4 @@ return costs; }; - -Cost.prototype.OnValueModification = function(msg) -{ - if (msg.component != "Cost") - return; - - // Foundations shouldn't have a pop cost. - var cmpFoundation = Engine.QueryInterface(this.entity, IID_Foundation); - if (cmpFoundation) - return; - - // update the population costs - var newPopCost = Math.round(ApplyValueModificationsToEntity("Cost/Population", +this.template.Population, this.entity)); - var popCostDifference = newPopCost - this.populationCost; - this.populationCost = newPopCost; - - var cmpPlayer = QueryOwnerInterface(this.entity); - if (!cmpPlayer) - return; - if (popCostDifference) - cmpPlayer.AddPopulation(popCostDifference); -}; - Engine.RegisterComponentType(IID_Cost, "Cost", Cost); Index: binaries/data/mods/public/simulation/components/GuiInterface.js =================================================================== --- binaries/data/mods/public/simulation/components/GuiInterface.js +++ binaries/data/mods/public/simulation/components/GuiInterface.js @@ -319,7 +319,8 @@ let cmpPopulation = Engine.QueryInterface(ent, IID_Population); if (cmpPopulation) ret.population = { - "bonus": cmpPopulation.GetPopBonus() + "bonus": cmpPopulation.Bonus(), + "cost": cmpPopulation.Cost() }; let cmpUpgrade = Engine.QueryInterface(ent, IID_Upgrade); @@ -1229,7 +1230,6 @@ * 'wood': ..., * 'stone': ..., * 'metal': ..., - * 'population': ..., * } * } * @@ -1381,7 +1381,7 @@ let result = { "pieces": [], - "cost": { "population": 0, "time": 0 } + "cost": { "time": 0 } }; for (let res of Resources.GetCodes()) result.cost[res] = 0; @@ -1658,7 +1658,7 @@ // copied over, so we need to fetch it from the template instead). // TODO: We should really use a Cost object or at least some utility functions for this, this is mindless // boilerplate that's probably duplicated in tons of places. - for (let res of Resources.GetCodes().concat(["population", "time"])) + for (let res of Resources.GetCodes().concat(["time"])) result.cost[res] += tplData.cost[res]; } Index: binaries/data/mods/public/simulation/components/Player.js =================================================================== --- binaries/data/mods/public/simulation/components/Player.js +++ binaries/data/mods/public/simulation/components/Player.js @@ -783,13 +783,8 @@ if (msg.from != this.playerID && msg.to != this.playerID) return; - let cmpCost = Engine.QueryInterface(msg.entity, IID_Cost); - if (msg.from == this.playerID) { - if (cmpCost) - this.popUsed -= cmpCost.GetPopCost(); - let panelIndex = this.panelEntities.indexOf(msg.entity); if (panelIndex >= 0) this.panelEntities.splice(panelIndex, 1); @@ -800,9 +795,6 @@ } if (msg.to == this.playerID) { - if (cmpCost) - this.popUsed += cmpCost.GetPopCost(); - let cmpIdentity = Engine.QueryInterface(msg.entity, IID_Identity); if (!cmpIdentity) return; Index: binaries/data/mods/public/simulation/components/Population.js =================================================================== --- binaries/data/mods/public/simulation/components/Population.js +++ binaries/data/mods/public/simulation/components/Population.js @@ -1,30 +1,46 @@ function Population() {} Population.prototype.Schema = - "Specifies the Population cap increase generated by this entity." + + "Specifies the Population properties of this entity." + "" + + "1" + "15" + "" + - "" + - "" + - ""; + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; Population.prototype.Init = function() { - this.bonus = +this.template.Bonus; }; /** * @return {number} - The population space provided by this entity. */ -Population.prototype.GetPopBonus = function() +Population.prototype.Bonus = function() { return this.bonus; }; +/** + * @return {number} - The population space taken by this entity. + */ +Population.prototype.Cost = function() +{ + return this.cost; +}; + Population.prototype.RecalculateValues = function() { - this.bonus = Math.round(ApplyValueModificationsToEntity("Population/Bonus", +this.template.Bonus, this.entity)); + this.bonus = Math.round(ApplyValueModificationsToEntity("Population/Bonus", +(this.template.Bonus || 0), this.entity)); + this.cost = Math.round(ApplyValueModificationsToEntity("Population/Cost", +(this.template.Cost || 0), this.entity)); }; Population.prototype.OnOwnershipChanged = function(msg) @@ -33,14 +49,20 @@ { let cmpPlayer = QueryPlayerIDInterface(msg.from); if (cmpPlayer) + { + cmpPlayer.AddPopulation(-this.cost); cmpPlayer.AddPopulationBonuses(-this.bonus); + } } if (msg.to != INVALID_PLAYER) { this.RecalculateValues(); let cmpPlayer = QueryPlayerIDInterface(msg.to); if (cmpPlayer) + { + cmpPlayer.AddPopulation(this.cost); cmpPlayer.AddPopulationBonuses(this.bonus); + } } }; @@ -49,19 +71,27 @@ if (msg.component != "Population") return; + let cmpPlayer = QueryOwnerInterface(this.entity); + if (!cmpPlayer) + return; + + let oldPopCost = this.cost; + this.cost = Math.round(ApplyValueModificationsToEntity("Population/Cost", +(this.template.Cost || 0), this.entity)); + + let popCostDifference = this.cost - oldPopCost; + if (popCostDifference) + cmpPlayer.AddPopulation(popCostDifference); + // Foundations shouldn't give a pop bonus. if (Engine.QueryInterface(this.entity, IID_Foundation)) return; let oldPopBonus = this.bonus; - this.RecalculateValues(); - let popDifference = this.bonus - oldPopBonus; + this.bonus = Math.round(ApplyValueModificationsToEntity("Population/Bonus", +(this.template.Bonus || 0), this.entity)); - if (!popDifference) - return; - let cmpPlayer = QueryOwnerInterface(this.entity); - if (cmpPlayer) - cmpPlayer.AddPopulationBonuses(popDifference); + let popBonusDifference = this.bonus - oldPopBonus; + if (popBonusDifference) + cmpPlayer.AddPopulationBonuses(popBonusDifference); }; Engine.RegisterComponentType(IID_Population, "Population", Population); Index: binaries/data/mods/public/simulation/components/ProductionQueue.js =================================================================== --- binaries/data/mods/public/simulation/components/ProductionQueue.js +++ binaries/data/mods/public/simulation/components/ProductionQueue.js @@ -419,8 +419,8 @@ "metadata": metadata, "resources": costs, "population": ApplyValueModificationsToTemplate( - "Cost/Population", - +template.Cost.Population, + "Population/Cost", + +template.Population.Cost, player, template), "productionStarted": false, @@ -788,8 +788,8 @@ // If something change population cost. let template = cmpTemplateManager.GetTemplate(item.unitTemplate); item.population = ApplyValueModificationsToTemplate( - "Cost/Population", - +template.Cost.Population, + "Population/Cost", + +template.Population.Cost, item.player, template); Index: binaries/data/mods/public/simulation/components/tests/test_Population.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_Population.js +++ binaries/data/mods/public/simulation/components/tests/test_Population.js @@ -7,9 +7,10 @@ const player = 1; const entity = 11; let entPopBonus = 5; +let entPopCost = 1; Engine.RegisterGlobal("ApplyValueModificationsToEntity", - (valueName, currentValue, entity) => currentValue + (valueName, currentValue, ent) => currentValue ); AddMock(SYSTEM_ENTITY, IID_PlayerManager, { @@ -17,12 +18,14 @@ }); let cmpPopulation = ConstructComponent(entity, "Population", { - "Bonus": entPopBonus + "Bonus": entPopBonus, + "Cost": entPopCost }); // Test ownership change adds bonus. let cmpPlayer = AddMock(player, IID_Player, { - "AddPopulationBonuses": bonus => TS_ASSERT_EQUALS(bonus, entPopBonus) + "AddPopulationBonuses": bonus => TS_ASSERT_EQUALS(bonus, entPopBonus), + "AddPopulation": space => TS_ASSERT_EQUALS(space, entPopCost) }); let spy = new Spy(cmpPlayer, "AddPopulationBonuses"); cmpPopulation.OnOwnershipChanged({ "from": INVALID_PLAYER, "to": player }); @@ -30,7 +33,8 @@ // Test ownership change removes bonus. cmpPlayer = AddMock(player, IID_Player, { - "AddPopulationBonuses": bonus => TS_ASSERT_EQUALS(bonus, -entPopBonus) + "AddPopulationBonuses": bonus => TS_ASSERT_EQUALS(bonus, -entPopBonus), + "AddPopulation": space => TS_ASSERT_EQUALS(space, -entPopCost) }); spy = new Spy(cmpPlayer, "AddPopulationBonuses"); cmpPopulation.OnOwnershipChanged({ "from": player, "to": INVALID_PLAYER }); @@ -40,11 +44,12 @@ // Test value modifications. // Test no change. Engine.RegisterGlobal("ApplyValueModificationsToEntity", - (valueName, currentValue, entity) => currentValue + (valueName, currentValue, ent) => currentValue ); cmpPlayer = AddMock(player, IID_Player, { - "AddPopulationBonuses": () => TS_ASSERT(false) + "AddPopulationBonuses": () => TS_ASSERT(false), + "AddPopulation": () => TS_ASSERT_EQUALS(false) }); cmpPopulation.OnValueModification({ "component": "bogus" }); cmpPopulation.OnValueModification({ "component": "Population" }); @@ -55,11 +60,12 @@ }); let difference = 3; Engine.RegisterGlobal("ApplyValueModificationsToEntity", - (valueName, currentValue, entity) => currentValue + difference + (valueName, currentValue, ent) => currentValue + difference ); cmpPlayer = AddMock(player, IID_Player, { - "AddPopulationBonuses": bonus => TS_ASSERT_EQUALS(bonus, difference) + "AddPopulationBonuses": bonus => TS_ASSERT_EQUALS(bonus, difference), + "AddPopulation": space => TS_ASSERT_EQUALS(space, difference) }); spy = new Spy(cmpPlayer, "AddPopulationBonuses"); @@ -74,11 +80,12 @@ // Reset to no bonus. cmpPlayer = AddMock(player, IID_Player, { - "AddPopulationBonuses": bonus => TS_ASSERT_EQUALS(bonus, -3) + "AddPopulationBonuses": bonus => TS_ASSERT_EQUALS(bonus, -3), + "AddPopulation": space => TS_ASSERT_EQUALS(space, -3) }); -difference = 0 +difference = 0; Engine.RegisterGlobal("ApplyValueModificationsToEntity", - (valueName, currentValue, entity) => currentValue + difference + (valueName, currentValue, ent) => currentValue + difference ); spy = new Spy(cmpPlayer, "AddPopulationBonuses"); cmpPopulation.OnValueModification({ "component": "Population" }); @@ -87,11 +94,12 @@ // Test negative change. difference = -2; Engine.RegisterGlobal("ApplyValueModificationsToEntity", - (valueName, currentValue, entity) => currentValue + difference + (valueName, currentValue, ent) => currentValue + difference ); cmpPlayer = AddMock(player, IID_Player, { - "AddPopulationBonuses": bonus => TS_ASSERT_EQUALS(bonus, difference) + "AddPopulationBonuses": bonus => TS_ASSERT_EQUALS(bonus, difference), + "AddPopulation": space => TS_ASSERT_EQUALS(space, difference) }); spy = new Spy(cmpPlayer, "AddPopulationBonuses"); @@ -101,10 +109,11 @@ // Test newly created entities also get affected by modifications. difference = 3; Engine.RegisterGlobal("ApplyValueModificationsToEntity", - (valueName, currentValue, entity) => currentValue + difference + (valueName, currentValue, ent) => currentValue + difference ); cmpPlayer = AddMock(player, IID_Player, { - "AddPopulationBonuses": bonus => TS_ASSERT_EQUALS(bonus, entPopBonus + difference) + "AddPopulationBonuses": bonus => TS_ASSERT_EQUALS(bonus, entPopBonus + difference), + "AddPopulation": space => TS_ASSERT_EQUALS(space, entPopCost + difference) }); spy = new Spy(cmpPlayer, "AddPopulationBonuses"); cmpPopulation.OnOwnershipChanged({ "from": INVALID_PLAYER, "to": player }); Index: binaries/data/mods/public/simulation/components/tests/test_ProductionQueue.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_ProductionQueue.js +++ binaries/data/mods/public/simulation/components/tests/test_ProductionQueue.js @@ -225,9 +225,11 @@ "GetTemplate": name => ({ "Cost": { "BuildTime": 0, - "Population": 1, "Resources": {} }, + "Population": { + "Cost": 1 + }, "TrainingRestrictions": { "Category": "some_limit", "MatchLimit": "7" @@ -334,9 +336,11 @@ "GetTemplate": name => ({ "Cost": { "BuildTime": 0, - "Population": 1, "Resources": {} }, + "Population": { + "Cost": 1 + }, "TrainingRestrictions": { "Category": "some_limit" } @@ -413,9 +417,11 @@ "GetTemplate": name => ({ "Cost": { "BuildTime": 0, - "Population": 1, "Resources": {} }, + "Population": { + "Cost": 1 + }, "TrainingRestrictions": { "Category": "some_limit" } Index: binaries/data/mods/public/simulation/templates/special/spy.xml =================================================================== --- binaries/data/mods/public/simulation/templates/special/spy.xml +++ binaries/data/mods/public/simulation/templates/special/spy.xml @@ -1,12 +1,8 @@ - 0 0 - 0 - 0 - 0 500 Index: binaries/data/mods/public/simulation/templates/template_structure.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_structure.xml +++ binaries/data/mods/public/simulation/templates/template_structure.xml @@ -12,7 +12,6 @@ 5.0 - 0 10 0 Index: binaries/data/mods/public/simulation/templates/template_unit.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit.xml +++ binaries/data/mods/public/simulation/templates/template_unit.xml @@ -2,7 +2,6 @@ - 1 1 0 @@ -67,6 +66,9 @@ + + 1 + 0 pitch Index: binaries/data/mods/public/simulation/templates/template_unit_catafalque.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_catafalque.xml +++ binaries/data/mods/public/simulation/templates/template_unit_catafalque.xml @@ -24,6 +24,7 @@ + pitch-roll Index: binaries/data/mods/public/simulation/templates/template_unit_champion_elephant.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_champion_elephant.xml +++ binaries/data/mods/public/simulation/templates/template_unit_champion_elephant.xml @@ -1,7 +1,6 @@ - 3 36 300 @@ -24,6 +23,9 @@ 30 20 + + 3 + 3 Index: binaries/data/mods/public/simulation/templates/template_unit_dog.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_dog.xml +++ binaries/data/mods/public/simulation/templates/template_unit_dog.xml @@ -15,7 +15,6 @@ 15 - 0 100 @@ -37,6 +36,9 @@ 100 10 + + 0 + Index: binaries/data/mods/public/simulation/templates/template_unit_fauna.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_fauna.xml +++ binaries/data/mods/public/simulation/templates/template_unit_fauna.xml @@ -1,8 +1,5 @@ - - 0 - 4.0 @@ -18,6 +15,7 @@ food + 4 Index: binaries/data/mods/public/simulation/templates/template_unit_hero.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_hero.xml +++ binaries/data/mods/public/simulation/templates/template_unit_hero.xml @@ -13,7 +13,6 @@ units/heroes/hero_garrison - 0 50 100 @@ -37,6 +36,7 @@ hero + Index: binaries/data/mods/public/simulation/templates/template_unit_ship_bireme.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_ship_bireme.xml +++ binaries/data/mods/public/simulation/templates/template_unit_ship_bireme.xml @@ -28,7 +28,6 @@ Infantry Cavalry - 2 20 120 @@ -53,6 +52,9 @@ 24 12 + + 2 + attack/impact/arrow_impact.xml Index: binaries/data/mods/public/simulation/templates/template_unit_ship_quinquereme.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_ship_quinquereme.xml +++ binaries/data/mods/public/simulation/templates/template_unit_ship_quinquereme.xml @@ -33,7 +33,6 @@ StoneThrower - 5 30 600 @@ -58,6 +57,9 @@ 120 60 + + 5 + 2 Index: binaries/data/mods/public/simulation/templates/template_unit_ship_trireme.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_ship_trireme.xml +++ binaries/data/mods/public/simulation/templates/template_unit_ship_trireme.xml @@ -28,7 +28,6 @@ Infantry Cavalry - 3 25 200 @@ -53,6 +52,9 @@ 40 20 + + 3 + 2 Index: binaries/data/mods/public/simulation/templates/template_unit_siege.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_siege.xml +++ binaries/data/mods/public/simulation/templates/template_unit_siege.xml @@ -1,8 +1,5 @@ - - 3 - 0.0 0.0 @@ -17,6 +14,9 @@ Siege phase_city + + 3 + pitch-roll 2 Index: binaries/data/mods/public/simulation/templates/template_unit_siege_boltshooter.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_siege_boltshooter.xml +++ binaries/data/mods/public/simulation/templates/template_unit_siege_boltshooter.xml @@ -40,7 +40,6 @@ 250 250 - 2 @@ -61,6 +60,9 @@ + + 2 + attack/impact/arrow_metal.xml Index: binaries/data/mods/public/simulation/templates/template_unit_support_slave.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_support_slave.xml +++ binaries/data/mods/public/simulation/templates/template_unit_support_slave.xml @@ -32,7 +32,6 @@ - 0 15 50 @@ -52,6 +51,9 @@ 10 5 + + 0 + 2.0 1.0 Index: binaries/data/mods/public/simulation/templates/units/ptol/champion_juggernaut.xml =================================================================== --- binaries/data/mods/public/simulation/templates/units/ptol/champion_juggernaut.xml +++ binaries/data/mods/public/simulation/templates/units/ptol/champion_juggernaut.xml @@ -1,7 +1,6 @@ - 5 60 800 @@ -30,6 +29,9 @@ 160 80 + + 5 + Juggernaut