Index: ps/trunk/binaries/data/mods/public/globalscripts/DamageTypes.js =================================================================== --- ps/trunk/binaries/data/mods/public/globalscripts/DamageTypes.js +++ ps/trunk/binaries/data/mods/public/globalscripts/DamageTypes.js @@ -0,0 +1,22 @@ +function DamageTypes() +{ + // TODO: load these from files + + this.names = { + "Hack": markForTranslationWithContext("damage type", "Hack"), + "Pierce": markForTranslationWithContext("damage type", "Pierce"), + "Crush": markForTranslationWithContext("damage type", "Crush"), + }; + + deepfreeze(this.names); +} + +DamageTypes.prototype.GetNames = function() +{ + return this.names; +}; + +DamageTypes.prototype.GetTypes = function() +{ + return Object.keys(this.names); +}; Index: ps/trunk/binaries/data/mods/public/globalscripts/Templates.js =================================================================== --- ps/trunk/binaries/data/mods/public/globalscripts/Templates.js +++ ps/trunk/binaries/data/mods/public/globalscripts/Templates.js @@ -117,11 +117,12 @@ * of properties. * @param {object} auraTemplates - In the form of { key: { "auraName": "", "auraDescription": "" } }. * @param {object} resources - An instance of the Resources prototype. + * @param {object} damageTypes - An instance of the DamageTypes prototype. * @param {object} modifiers - Modifications from auto-researched techs, unit upgrades * etc. Optional as only used if there's no player * id provided. */ -function GetTemplateDataHelper(template, player, auraTemplates, resources, modifiers={}) +function GetTemplateDataHelper(template, player, auraTemplates, resources, damageTypes, modifiers={}) { // Return data either from template (in tech tree) or sim state (ingame). // @param {string} value_path - Route to the value within the template. @@ -133,11 +134,11 @@ let ret = {}; if (template.Armour) - ret.armour = { - "hack": getEntityValue("Armour/Hack"), - "pierce": getEntityValue("Armour/Pierce"), - "crush": getEntityValue("Armour/Crush") - }; + { + ret.armour = {}; + for (let damageType of damageTypes.GetTypes()) + ret.armour[damageType] = getEntityValue("Armour/" + damageType); + } if (template.Attack) { @@ -155,38 +156,38 @@ else { ret.attack[type] = { - "hack": getAttackStat("Hack"), - "pierce": getAttackStat("Pierce"), - "crush": getAttackStat("Crush"), "minRange": getAttackStat("MinRange"), "maxRange": getAttackStat("MaxRange"), "elevationBonus": getAttackStat("ElevationBonus") }; + for (let damageType of damageTypes.GetTypes()) + ret.attack[type][damageType] = getAttackStat(damageType); + ret.attack[type].elevationAdaptedRange = Math.sqrt(ret.attack[type].maxRange * (2 * ret.attack[type].elevationBonus + ret.attack[type].maxRange)); } ret.attack[type].repeatTime = getAttackStat("RepeatTime"); if (template.Attack[type].Splash) + { ret.attack[type].splash = { - "hack": getAttackStat("Splash/Hack"), - "pierce": getAttackStat("Splash/Pierce"), - "crush": getAttackStat("Splash/Crush"), // true if undefined "friendlyFire": template.Attack[type].Splash.FriendlyFire != "false", "shape": template.Attack[type].Splash.Shape }; + for (let damageType of damageTypes.GetTypes()) + ret.attack[type].splash[damageType] = getAttackStat("Splash/" + damageType); + } } } if (template.DeathDamage) { ret.deathDamage = { - "hack": getEntityValue("DeathDamage/Hack"), - "pierce": getEntityValue("DeathDamage/Pierce"), - "crush": getEntityValue("DeathDamage/Crush"), "friendlyFire": template.DeathDamage.FriendlyFire != "false" }; + for (let damageType of damageTypes.GetTypes()) + ret.deathDamage[damageType] = getEntityValue("DeathDamage/" + damageType); } if (template.Auras) Index: ps/trunk/binaries/data/mods/public/gui/common/tooltips.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/common/tooltips.js +++ ps/trunk/binaries/data/mods/public/gui/common/tooltips.js @@ -11,11 +11,7 @@ "Capture": translate("Capture Attack:") }; -var g_DamageTypes = { - "hack": translate("Hack"), - "pierce": translate("Pierce"), - "crush": translate("Crush"), -}; +var g_DamageTypes = new DamageTypes(); var g_SplashDamageTypes = { "Circular": translate("Circular Splash Damage"), @@ -188,7 +184,7 @@ Object.keys(template.armour).map( dmgType => sprintf(translate("%(damage)s %(damageType)s %(armorPercentage)s"), { "damage": template.armour[dmgType].toFixed(1), - "damageType": unitFont(g_DamageTypes[dmgType]), + "damageType": unitFont(translateWithContext("damage type", g_DamageTypes.GetNames()[dmgType])), "armorPercentage": '[font="sans-10"]' + sprintf(translate("(%(armorPercentage)s)"), { @@ -204,11 +200,11 @@ if (!dmg) return '[font="sans-12"]' + translate("(None)") + '[/font]'; - return Object.keys(g_DamageTypes).filter( + return g_DamageTypes.GetTypes().filter( dmgType => dmg[dmgType]).map( dmgType => sprintf(translate("%(damage)s %(damageType)s"), { "damage": dmg[dmgType].toFixed(1), - "damageType": unitFont(g_DamageTypes[dmgType]) + "damageType": unitFont(translateWithContext("damage type", g_DamageTypes.GetNames()[dmgType])) })).join(commaFont(translate(", "))); } Index: ps/trunk/binaries/data/mods/public/gui/reference/common/helper.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/reference/common/helper.js +++ ps/trunk/binaries/data/mods/public/gui/reference/common/helper.js @@ -23,7 +23,7 @@ { upgrade.entity = upgrade.entity.replace("{civ}", g_SelectedCiv); - let data = GetTemplateDataHelper(loadTemplate(upgrade.entity), null, g_AuraData, g_ResourceData); + let data = GetTemplateDataHelper(loadTemplate(upgrade.entity), null, g_AuraData, g_ResourceData, g_DamageTypes); data.cost = upgrade.cost; data.icon = upgrade.icon || data.icon; data.tooltip = upgrade.tooltip || data.tooltip; @@ -177,7 +177,7 @@ function GetTemplateData(templateName) { var template = loadTemplate(templateName); - return GetTemplateDataHelper(template, null, g_AuraData, g_ResourceData, g_CurrentModifiers); + return GetTemplateDataHelper(template, null, g_AuraData, g_ResourceData, g_DamageTypes, g_CurrentModifiers); } function isPairTech(technologyCode) Index: ps/trunk/binaries/data/mods/public/gui/reference/common/load.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/reference/common/load.js +++ ps/trunk/binaries/data/mods/public/gui/reference/common/load.js @@ -17,6 +17,7 @@ */ var g_ParsedData = {}; var g_ResourceData = new Resources(); +var g_DamageTypes = new DamageTypes(); // This must be defined after the g_TechnologyData cache object is declared. var g_AutoResearchTechList = findAllAutoResearchedTechs(); @@ -101,7 +102,7 @@ return null; let template = loadTemplate(templateName); - let unit = GetTemplateDataHelper(template, null, g_AuraData, g_ResourceData, g_CurrentModifiers); + let unit = GetTemplateDataHelper(template, null, g_AuraData, g_ResourceData, g_DamageTypes, g_CurrentModifiers); if (template.ProductionQueue) { @@ -157,7 +158,7 @@ return null; let template = loadTemplate(templateName); - let structure = GetTemplateDataHelper(template, null, g_AuraData, g_ResourceData, g_CurrentModifiers); + let structure = GetTemplateDataHelper(template, null, g_AuraData, g_ResourceData, g_DamageTypes, g_CurrentModifiers); structure.production = { "technology": [], Index: ps/trunk/binaries/data/mods/public/simulation/ai/common-api/entity.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/ai/common-api/entity.js +++ ps/trunk/binaries/data/mods/public/simulation/ai/common-api/entity.js @@ -214,14 +214,14 @@ return +this.get("Cost/PopulationBonus"); }, - armourStrengths: function() { + "armourStrengths": function() { if (!this.get("Armour")) return undefined; return { - hack: +this.get("Armour/Hack"), - pierce: +this.get("Armour/Pierce"), - crush: +this.get("Armour/Crush") + "Hack": +this.get("Armour/Hack"), + "Pierce": +this.get("Armour/Pierce"), + "Crush": +this.get("Armour/Crush") }; }, @@ -246,14 +246,14 @@ }; }, - attackStrengths: function(type) { + "attackStrengths": function(type) { if (!this.get("Attack/" + type +"")) return undefined; return { - hack: +(this.get("Attack/" + type + "/Hack") || 0), - pierce: +(this.get("Attack/" + type + "/Pierce") || 0), - crush: +(this.get("Attack/" + type + "/Crush") || 0) + "Hack": +(this.get("Attack/" + type + "/Hack") || 0), + "Pierce": +(this.get("Attack/" + type + "/Pierce") || 0), + "Crush": +(this.get("Attack/" + type + "/Crush") || 0) }; }, Index: ps/trunk/binaries/data/mods/public/simulation/ai/petra/entityExtend.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/ai/petra/entityExtend.js +++ ps/trunk/binaries/data/mods/public/simulation/ai/petra/entityExtend.js @@ -28,13 +28,13 @@ val *= ent.getMultiplierAgainst(type, againstClass); switch (str) { - case "crush": + case "Crush": strength += val * 0.085 / 3; break; - case "hack": + case "Hack": strength += val * 0.075 / 3; break; - case "pierce": + case "Pierce": strength += val * 0.065 / 3; break; default: @@ -70,13 +70,13 @@ let val = parseFloat(armourStrength[str]); switch (str) { - case "crush": + case "Crush": strength += val * 0.085 / 3; break; - case "hack": + case "Hack": strength += val * 0.075 / 3; break; - case "pierce": + case "Pierce": strength += val * 0.065 / 3; break; default: Index: ps/trunk/binaries/data/mods/public/simulation/components/Armour.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/Armour.js +++ ps/trunk/binaries/data/mods/public/simulation/components/Armour.js @@ -7,27 +7,11 @@ "0.0" + "5.0" + "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + + DamageTypes.BuildSchema("damage protection") + "" + "" + "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + + DamageTypes.BuildSchema("damage protection") + "" + "" + ""; @@ -85,11 +69,11 @@ var foundation = Engine.QueryInterface(this.entity, IID_Foundation) && this.template.Foundation; - return { - "hack": applyMods("Hack", foundation), - "pierce": applyMods("Pierce", foundation), - "crush": applyMods("Crush", foundation) - }; + let ret = {}; + for (let damageType of DamageTypes.GetTypes()) + ret[damageType] = applyMods(damageType, foundation); + + return ret; }; Engine.RegisterComponentType(IID_DamageReceiver, "Armour", Armour); Index: ps/trunk/binaries/data/mods/public/simulation/components/Attack.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/Attack.js +++ ps/trunk/binaries/data/mods/public/simulation/components/Attack.js @@ -100,9 +100,7 @@ "" + "" + "" + - "" + - "" + - "" + + DamageTypes.BuildSchema("damage strength") + "" + "" + "" + @@ -119,9 +117,7 @@ "" + "" + "" + - "" + - "" + - "" + + DamageTypes.BuildSchema("damage strength") + "" + "" + ""+ @@ -149,9 +145,7 @@ "" + "" + "" + - "" + - "" + - "" + + DamageTypes.BuildSchema("damage strength") + Attack.prototype.bonusesSchema + "" + "" + @@ -176,9 +170,7 @@ "" + "" + "" + - "" + - "" + - "" + + DamageTypes.BuildSchema("damage strength") + "" + // TODO: how do these work? Attack.prototype.bonusesSchema + Attack.prototype.preferredClassesSchema + @@ -403,11 +395,11 @@ if (type == "Capture") return { "value": applyMods("Value") }; - return { - "hack": applyMods("Hack"), - "pierce": applyMods("Pierce"), - "crush": applyMods("Crush") - }; + let ret = {}; + for (let damageType of DamageTypes.GetTypes()) + ret[damageType] = applyMods(damageType); + + return ret; }; Attack.prototype.GetSplashDamage = function(type) @@ -502,7 +494,6 @@ let cmpProjectileManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ProjectileManager); let id = cmpProjectileManager.LaunchProjectileAtPoint(this.entity, realTargetPosition, horizSpeed, gravity); - cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); let data = { "type": type, "attacker": this.entity, Index: ps/trunk/binaries/data/mods/public/simulation/components/DeathDamage.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/DeathDamage.js +++ ps/trunk/binaries/data/mods/public/simulation/components/DeathDamage.js @@ -31,9 +31,7 @@ "" + "" + "" + - "" + - "" + - "" + + DamageTypes.BuildSchema("damage strength") + DeathDamage.prototype.bonusesSchema; DeathDamage.prototype.Init = function() @@ -48,11 +46,11 @@ let applyMods = damageType => ApplyValueModificationsToEntity("DeathDamage/" + damageType, +(this.template[damageType] || 0), this.entity); - return { - "hack": applyMods("Hack"), - "pierce": applyMods("Pierce"), - "crush": applyMods("Crush") - }; + let ret = {}; + for (let damageType of DamageTypes.GetTypes()) + ret[damageType] = applyMods(damageType); + + return ret; }; DeathDamage.prototype.GetBonusTemplate = function() Index: ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js +++ ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js @@ -656,14 +656,14 @@ let aurasTemplate = {}; if (!template.Auras) - return GetTemplateDataHelper(template, player, aurasTemplate, Resources); + return GetTemplateDataHelper(template, player, aurasTemplate, Resources, DamageTypes); // Add aura name and description loaded from JSON file let auraNames = template.Auras._string.split(/\s+/); let cmpDataTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_DataTemplateManager); for (let name of auraNames) aurasTemplate[name] = cmpDataTemplateManager.GetAuraTemplate(name); - return GetTemplateDataHelper(template, player, aurasTemplate, Resources); + return GetTemplateDataHelper(template, player, aurasTemplate, Resources, DamageTypes); }; GuiInterface.prototype.GetTechnologyData = function(player, data) Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Attack.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Attack.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Attack.js @@ -1,4 +1,5 @@ Engine.LoadHelperScript("DamageBonus.js"); +Engine.LoadHelperScript("DamageTypes.js"); Engine.LoadHelperScript("Player.js"); Engine.LoadHelperScript("ValueModification.js"); Engine.LoadComponentScript("interfaces/Auras.js"); @@ -139,15 +140,15 @@ TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackStrengths("Capture"), { "value": 8 }); TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackStrengths("Ranged"), { - "hack": 0, - "pierce": 10, - "crush": 0 + "Hack": 0, + "Pierce": 10, + "Crush": 0 }); TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackStrengths("Ranged.Splash"), { - "hack": 0.0, - "pierce": 15.0, - "crush": 35.0 + "Hack": 0.0, + "Pierce": 15.0, + "Crush": 35.0 }); TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetTimers("Ranged"), { @@ -160,7 +161,13 @@ "repeat": 1000 }); - TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetSplashDamage("Ranged"), { "hack": 0, "pierce": 15, "crush": 35, "friendlyFire": false, "shape": "Circular" }); + TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetSplashDamage("Ranged"), { + "Hack": 0, + "Pierce": 15, + "Crush": 35, + "friendlyFire": false, + "shape": "Circular" + }); }); for (let className of ["Infantry", "Cavalry"]) Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Damage.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Damage.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Damage.js @@ -1,4 +1,5 @@ Engine.LoadHelperScript("DamageBonus.js"); +Engine.LoadHelperScript("DamageTypes.js"); Engine.LoadHelperScript("Player.js"); Engine.LoadHelperScript("Sound.js"); Engine.LoadHelperScript("ValueModification.js"); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_DeathDamage.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_DeathDamage.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_DeathDamage.js @@ -1,4 +1,5 @@ Engine.LoadHelperScript("DamageBonus.js"); +Engine.LoadHelperScript("DamageTypes.js"); Engine.LoadHelperScript("ValueModification.js"); Engine.LoadComponentScript("interfaces/AuraManager.js"); Engine.LoadComponentScript("interfaces/Damage.js"); @@ -26,9 +27,9 @@ }; let modifiedDamage = { - "hack": 0.0, - "pierce": 215.0, - "crush": 35.0 + "Hack": 0.0, + "Pierce": 215.0, + "Crush": 35.0 }; let cmpDeathDamage = ConstructComponent(deadEnt, "DeathDamage", template); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_UpgradeModification.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_UpgradeModification.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_UpgradeModification.js @@ -126,11 +126,11 @@ * To start with, no techs are researched... */ // T1: Check the cost of the upgrade without a player value being passed (as it would be in the structree). -let parsed_template = GetTemplateDataHelper(template, null, {}, Resources); +let parsed_template = GetTemplateDataHelper(template, null, {}, Resources, DamageTypes); TS_ASSERT_UNEVAL_EQUALS(parsed_template.upgrades[0].cost, { "stone": 100, "wood": 50, "time": 100 }); // T2: Check the value, with a player ID (as it would be in-session). -parsed_template = GetTemplateDataHelper(template, playerID, {}, Resources); +parsed_template = GetTemplateDataHelper(template, playerID, {}, Resources, DamageTypes); TS_ASSERT_UNEVAL_EQUALS(parsed_template.upgrades[0].cost, { "stone": 100, "wood": 50, "time": 100 }); // T3: Check that the value is correct within the Update Component. @@ -144,11 +144,11 @@ isResearched = true; // T4: Check that the player-less value hasn't increased... -parsed_template = GetTemplateDataHelper(template, null, {}, Resources); +parsed_template = GetTemplateDataHelper(template, null, {}, Resources, DamageTypes); TS_ASSERT_UNEVAL_EQUALS(parsed_template.upgrades[0].cost, { "stone": 100, "wood": 50, "time": 100 }); // T5: ...but the player-backed value has. -parsed_template = GetTemplateDataHelper(template, playerID, {}, Resources); +parsed_template = GetTemplateDataHelper(template, playerID, {}, Resources, DamageTypes); TS_ASSERT_UNEVAL_EQUALS(parsed_template.upgrades[0].cost, { "stone": 160, "wood": 25, "time": 90 }); // T6: The upgrade component should still be using the old resource cost (but new time cost) for the upgrade in progress... Index: ps/trunk/binaries/data/mods/public/simulation/helpers/DamageTypes.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/helpers/DamageTypes.js +++ ps/trunk/binaries/data/mods/public/simulation/helpers/DamageTypes.js @@ -0,0 +1,8 @@ +DamageTypes.prototype.BuildSchema = function(helptext = "") +{ + return this.GetTypes().reduce((schema, type) => + schema + "", + ""); +}; + +DamageTypes = new DamageTypes();