Index: binaries/data/mods/public/globalscripts/Templates.js =================================================================== --- binaries/data/mods/public/globalscripts/Templates.js +++ binaries/data/mods/public/globalscripts/Templates.js @@ -180,6 +180,16 @@ effects.Damage[damageType] = getEntityValue(path + "/Damage/" + damageType); } + if (temp.Bonuses) + { + effects.Bonuses = {}; + for (let bonus in temp.Bonuses) + effects.Bonuses[bonus] = { + "Classes": temp.Bonuses[bonus].Classes.split(" "), + "Multiplier": getEntityValue(path + "/Bonuses/" + bonus + "/Multiplier") + }; + } + if (temp.ApplyStatus) effects.ApplyStatus = temp.ApplyStatus; 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 @@ -304,6 +304,24 @@ return effects.filter(effect => effect).join(commaFont(translate(", "))); } +/** + * Get the string to translate for this attack. + * @param {String} template - The template to use. + * @return {String} - Translatable string of the properties of the provided template. + */ +function getAttackTypeTranslation(template) +{ + let result = translate("%(attackLabel)s: %(effects)s, %(range)s, %(rate)s"); + if (template.Bonuses) + result = translate("%(attackLabel)s: %(effects)s, %(range)s, %(rate)s %(counters)s"); + if (template.ApplyStatus) + result = translate("%(attackLabel)s: %(effects)s, %(range)s, %(rate)s%(statusEffects)s"); + if (template.Bonuses && template.ApplyStatus) + result = translate("%(attackLabel)s: %(effects)s, %(range)s, %(rate)s %(counters)s%(statusEffects)s"); + + return result; +} + function getAttackTooltip(template) { if (!template.attack) @@ -327,23 +345,29 @@ if (template.buildingAI) projectiles = template.buildingAI.arrowCount || template.buildingAI.defaultArrowCount; - // Show the effects of status effects below - let statusEffectsDetails = []; + // This is what every attack ought to have and show. + let data = { + "attackLabel": attackLabel, + "effects": attackEffectsDetails(attackTypeTemplate), + "range": rangeDetails(attackTypeTemplate), + "rate": attackRateDetails(attackTypeTemplate.repeatTime, projectiles) + }; + + if (attackTypeTemplate.Bonuses) + data.counters = getCountersTooltip(attackTypeTemplate); + if (attackTypeTemplate.ApplyStatus) + { + let statusEffectsDetails = []; for (let status in attackTypeTemplate.ApplyStatus) { let status_template = g_StatusEffectsMetadata.augment(status, attackTypeTemplate.ApplyStatus[status]); statusEffectsDetails.push("\n " + getStatusEffectsTooltip(status_template, true)); } - statusEffectsDetails = statusEffectsDetails.join(""); + data.statusEffects = statusEffectsDetails.join(""); + } - tooltips.push(sprintf(translate("%(attackLabel)s: %(effects)s, %(range)s, %(rate)s%(statusEffects)s"), { - "attackLabel": attackLabel, - "effects": attackEffectsDetails(attackTypeTemplate), - "range": rangeDetails(attackTypeTemplate), - "rate": attackRateDetails(attackTypeTemplate.repeatTime, projectiles), - "statusEffects": statusEffectsDetails - })); + tooltips.push(sprintf(getAttackTypeTranslation(attackTypeTemplate), data)); } return tooltips.join("\n"); } @@ -443,6 +467,30 @@ }); } +function getCountersTooltip(template) +{ + if (!template.Bonuses) + return ""; + + let bonusesBody = []; + for (let key in template.Bonuses) + { + let bonus = template.Bonuses[key]; + + if (bonus.Multiplier == 1) + continue; + + bonusesBody.push(sprintf(translate("%(multiplier)s× vs %(classes)s"), { + "multiplier": bonus.Multiplier, + "classes": getClassesStringFormatted(bonus.Classes) + })); + } + + return sprintf(translate("(%(bonuses)s)"), { + "bonuses": bodyFont(bonusesBody.join(commaFont(translate(", ")))) + }); +} + function getGarrisonTooltip(template) { if (!template.garrisonHolder) @@ -913,7 +961,12 @@ return ""; return headerFont(translate("Classes:")) + ' ' + - bodyFont(template.visibleIdentityClasses.map(c => translate(c)).join(translate(", "))); + bodyFont(getClassesStringFormatted(template.visibleIdentityClasses)); +} + +function getClassesStringFormatted(classesList) +{ + return classesList.map(c => translate(c)).join(translate(", ")); } function getLootTooltip(template) Index: binaries/data/mods/public/gui/credits/texts/programming.json =================================================================== --- binaries/data/mods/public/gui/credits/texts/programming.json +++ binaries/data/mods/public/gui/credits/texts/programming.json @@ -87,6 +87,7 @@ { "nick": "falsevision", "name": "Mahdi Khodadadifard" }, { "nick": "fatherbushido", "name": "Nicolas Tisserand" }, { "nick": "fcxSanya", "name": "Alexander Olkhovskiy" }, + { "nick": "Feldfeld" }, { "nick": "FeXoR", "name": "Florian Finke" }, { "nick": "Fire Giant", "name": "Malte Schwarzkopf" }, { "name": "Fork AD" }, Index: binaries/data/mods/public/simulation/components/tests/test_Attack.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_Attack.js +++ binaries/data/mods/public/simulation/components/tests/test_Attack.js @@ -193,7 +193,7 @@ }, "Bonuses": { "BonusCav": { - "Classes": "Cavalry", + "Classes": ["Cavalry"], "Multiplier": 3 } } @@ -247,7 +247,7 @@ }, "Bonuses": { "BonusCav": { - "Classes": "Cavalry", + "Classes": ["Cavalry"], "Multiplier": 3 } } Index: binaries/data/mods/public/simulation/components/tests/test_DeathDamage.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_DeathDamage.js +++ binaries/data/mods/public/simulation/components/tests/test_DeathDamage.js @@ -66,8 +66,8 @@ cmpDeathDamage.CauseDeathDamage(); // Test splash damage bonus -effects.Bonuses = { "BonusCav": { "Classes": "Cavalry", "Multiplier": 3 } }; -template.Bonuses = effects.Bonuses; +template.Bonuses = { "BonusCav": { "Classes": "Cavalry", "Multiplier": 3 } }; +effects.Bonuses = { "BonusCav": { "Classes": ["Cavalry"], "Multiplier": 3 } }; cmpDeathDamage = ConstructComponent(deadEnt, "DeathDamage", template); result.attackData.Bonuses = effects.Bonuses; TS_ASSERT_UNEVAL_EQUALS(cmpDeathDamage.GetDeathDamageEffects(), effects); Index: binaries/data/mods/public/simulation/helpers/Attacking.js =================================================================== --- binaries/data/mods/public/simulation/helpers/Attacking.js +++ binaries/data/mods/public/simulation/helpers/Attacking.js @@ -122,7 +122,14 @@ ret.ApplyStatus = this.GetStatusEffectsData(valueModifRoot, template.ApplyStatus, entity); if (template.Bonuses) - ret.Bonuses = template.Bonuses; + { + ret.Bonuses = {}; + for (let bonus in template.Bonuses) + ret.Bonuses[bonus] = { + "Classes": template.Bonuses[bonus].Classes.split(" "), + "Multiplier": ApplyValueModificationsToEntity(valueModifRoot + "/Bonuses/" + bonus + "/Multiplier", +(template.Bonuses[bonus].Multiplier || 1), entity) + }; + } return ret; }; Index: binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_spearman.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_spearman.xml +++ binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_spearman.xml @@ -25,7 +25,6 @@ Spearman Cavalry Spearman - Counters: 1.5x vs. Cavalry. Index: binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_spearman.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_spearman.xml +++ binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_spearman.xml @@ -34,7 +34,6 @@ Melee Spearman Champion Cavalry Spearman - Counters: 1.5x vs. Cavalry. Index: binaries/data/mods/public/simulation/templates/template_unit_champion_infantry_pikeman.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_champion_infantry_pikeman.xml +++ binaries/data/mods/public/simulation/templates/template_unit_champion_infantry_pikeman.xml @@ -35,7 +35,6 @@ Melee Pikeman Champion Pikeman - Counters: 3x vs. Cavalry. special/formations/syntagma special/formations/testudo Index: binaries/data/mods/public/simulation/templates/template_unit_champion_infantry_spearman.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_champion_infantry_spearman.xml +++ binaries/data/mods/public/simulation/templates/template_unit_champion_infantry_spearman.xml @@ -34,7 +34,6 @@ Melee Spearman Champion Spearman - Counters: 3x vs. Cavalry. special/formations/testudo Index: binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_spearman.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_spearman.xml +++ binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_spearman.xml @@ -26,7 +26,6 @@ Melee Spearman Hero Cavalry Spearman - Counters: 1.5x vs. Cavalry. Index: binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_pikeman.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_pikeman.xml +++ binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_pikeman.xml @@ -26,7 +26,6 @@ Melee Pikeman Hero Pikeman - Counters: 3x vs. Cavalry. special/formations/testudo Index: binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_spearman.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_spearman.xml +++ binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_spearman.xml @@ -26,7 +26,6 @@ Melee Spearman Hero Spearman - Counters: 3x vs. Cavalry. special/formations/testudo Index: binaries/data/mods/public/simulation/templates/template_unit_infantry_melee_pikeman.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_infantry_melee_pikeman.xml +++ binaries/data/mods/public/simulation/templates/template_unit_infantry_melee_pikeman.xml @@ -29,7 +29,6 @@ Pikeman Pikeman - Counters: 3x vs. Cavalry. special/formations/syntagma Index: binaries/data/mods/public/simulation/templates/template_unit_infantry_melee_spearman.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_infantry_melee_spearman.xml +++ binaries/data/mods/public/simulation/templates/template_unit_infantry_melee_spearman.xml @@ -28,7 +28,6 @@ Spearman Spearman - Counters: 3x vs. Cavalry. 5 Index: binaries/data/mods/public/simulation/templates/units/iber_champion_cavalry.xml =================================================================== --- binaries/data/mods/public/simulation/templates/units/iber_champion_cavalry.xml +++ binaries/data/mods/public/simulation/templates/units/iber_champion_cavalry.xml @@ -13,7 +13,7 @@ Leial Zalduneria units/iber_champion_cavalry.png units/iber_champion_cavalry - Special: Flaming javelins. Good vs. Buildings. + Special: Flaming javelins. units/iberians/cavalry_javelinist_c_m.xml Index: binaries/data/mods/public/simulation/templates/units/mace_hero_alexander.xml =================================================================== --- binaries/data/mods/public/simulation/templates/units/mace_hero_alexander.xml +++ binaries/data/mods/public/simulation/templates/units/mace_hero_alexander.xml @@ -19,7 +19,6 @@ greek Alexander III the Great Alexandros ho Megas - "Herocide" Bonus: +20% attack bonus vs. enemy Heroes. units/mace_hero_alexander.png