mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-07-24 04:12:54 +00:00
Move damage types definition to a new helper similar to how resources are handled.
This should make adding new damage types a little easier, however such an extension would still need changes to the AI, and to all templates that have Armour, Attack, or DeathDamage. Reviewed By: elexis Differential Revision: https://code.wildfiregames.com/D866 This was SVN commit r20203.
This commit is contained in:
@@ -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);
|
||||||
|
};
|
||||||
@@ -117,11 +117,12 @@ function GetModifiedTemplateDataValue(template, value_path, mod_key, player, mod
|
|||||||
* of properties.
|
* of properties.
|
||||||
* @param {object} auraTemplates - In the form of { key: { "auraName": "", "auraDescription": "" } }.
|
* @param {object} auraTemplates - In the form of { key: { "auraName": "", "auraDescription": "" } }.
|
||||||
* @param {object} resources - An instance of the Resources prototype.
|
* @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
|
* @param {object} modifiers - Modifications from auto-researched techs, unit upgrades
|
||||||
* etc. Optional as only used if there's no player
|
* etc. Optional as only used if there's no player
|
||||||
* id provided.
|
* 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).
|
// Return data either from template (in tech tree) or sim state (ingame).
|
||||||
// @param {string} value_path - Route to the value within the template.
|
// @param {string} value_path - Route to the value within the template.
|
||||||
@@ -133,11 +134,11 @@ function GetTemplateDataHelper(template, player, auraTemplates, resources, modif
|
|||||||
let ret = {};
|
let ret = {};
|
||||||
|
|
||||||
if (template.Armour)
|
if (template.Armour)
|
||||||
ret.armour = {
|
{
|
||||||
"hack": getEntityValue("Armour/Hack"),
|
ret.armour = {};
|
||||||
"pierce": getEntityValue("Armour/Pierce"),
|
for (let damageType of damageTypes.GetTypes())
|
||||||
"crush": getEntityValue("Armour/Crush")
|
ret.armour[damageType] = getEntityValue("Armour/" + damageType);
|
||||||
};
|
}
|
||||||
|
|
||||||
if (template.Attack)
|
if (template.Attack)
|
||||||
{
|
{
|
||||||
@@ -155,38 +156,38 @@ function GetTemplateDataHelper(template, player, auraTemplates, resources, modif
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret.attack[type] = {
|
ret.attack[type] = {
|
||||||
"hack": getAttackStat("Hack"),
|
|
||||||
"pierce": getAttackStat("Pierce"),
|
|
||||||
"crush": getAttackStat("Crush"),
|
|
||||||
"minRange": getAttackStat("MinRange"),
|
"minRange": getAttackStat("MinRange"),
|
||||||
"maxRange": getAttackStat("MaxRange"),
|
"maxRange": getAttackStat("MaxRange"),
|
||||||
"elevationBonus": getAttackStat("ElevationBonus")
|
"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 *
|
ret.attack[type].elevationAdaptedRange = Math.sqrt(ret.attack[type].maxRange *
|
||||||
(2 * ret.attack[type].elevationBonus + ret.attack[type].maxRange));
|
(2 * ret.attack[type].elevationBonus + ret.attack[type].maxRange));
|
||||||
}
|
}
|
||||||
ret.attack[type].repeatTime = getAttackStat("RepeatTime");
|
ret.attack[type].repeatTime = getAttackStat("RepeatTime");
|
||||||
|
|
||||||
if (template.Attack[type].Splash)
|
if (template.Attack[type].Splash)
|
||||||
|
{
|
||||||
ret.attack[type].splash = {
|
ret.attack[type].splash = {
|
||||||
"hack": getAttackStat("Splash/Hack"),
|
|
||||||
"pierce": getAttackStat("Splash/Pierce"),
|
|
||||||
"crush": getAttackStat("Splash/Crush"),
|
|
||||||
// true if undefined
|
// true if undefined
|
||||||
"friendlyFire": template.Attack[type].Splash.FriendlyFire != "false",
|
"friendlyFire": template.Attack[type].Splash.FriendlyFire != "false",
|
||||||
"shape": template.Attack[type].Splash.Shape
|
"shape": template.Attack[type].Splash.Shape
|
||||||
};
|
};
|
||||||
|
for (let damageType of damageTypes.GetTypes())
|
||||||
|
ret.attack[type].splash[damageType] = getAttackStat("Splash/" + damageType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (template.DeathDamage)
|
if (template.DeathDamage)
|
||||||
{
|
{
|
||||||
ret.deathDamage = {
|
ret.deathDamage = {
|
||||||
"hack": getEntityValue("DeathDamage/Hack"),
|
|
||||||
"pierce": getEntityValue("DeathDamage/Pierce"),
|
|
||||||
"crush": getEntityValue("DeathDamage/Crush"),
|
|
||||||
"friendlyFire": template.DeathDamage.FriendlyFire != "false"
|
"friendlyFire": template.DeathDamage.FriendlyFire != "false"
|
||||||
};
|
};
|
||||||
|
for (let damageType of damageTypes.GetTypes())
|
||||||
|
ret.deathDamage[damageType] = getEntityValue("DeathDamage/" + damageType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (template.Auras)
|
if (template.Auras)
|
||||||
|
|||||||
@@ -11,11 +11,7 @@ var g_AttackTypes = {
|
|||||||
"Capture": translate("Capture Attack:")
|
"Capture": translate("Capture Attack:")
|
||||||
};
|
};
|
||||||
|
|
||||||
var g_DamageTypes = {
|
var g_DamageTypes = new DamageTypes();
|
||||||
"hack": translate("Hack"),
|
|
||||||
"pierce": translate("Pierce"),
|
|
||||||
"crush": translate("Crush"),
|
|
||||||
};
|
|
||||||
|
|
||||||
var g_SplashDamageTypes = {
|
var g_SplashDamageTypes = {
|
||||||
"Circular": translate("Circular Splash Damage"),
|
"Circular": translate("Circular Splash Damage"),
|
||||||
@@ -188,7 +184,7 @@ function getArmorTooltip(template)
|
|||||||
Object.keys(template.armour).map(
|
Object.keys(template.armour).map(
|
||||||
dmgType => sprintf(translate("%(damage)s %(damageType)s %(armorPercentage)s"), {
|
dmgType => sprintf(translate("%(damage)s %(damageType)s %(armorPercentage)s"), {
|
||||||
"damage": template.armour[dmgType].toFixed(1),
|
"damage": template.armour[dmgType].toFixed(1),
|
||||||
"damageType": unitFont(g_DamageTypes[dmgType]),
|
"damageType": unitFont(translateWithContext("damage type", g_DamageTypes.GetNames()[dmgType])),
|
||||||
"armorPercentage":
|
"armorPercentage":
|
||||||
'[font="sans-10"]' +
|
'[font="sans-10"]' +
|
||||||
sprintf(translate("(%(armorPercentage)s)"), {
|
sprintf(translate("(%(armorPercentage)s)"), {
|
||||||
@@ -204,11 +200,11 @@ function damageTypesToText(dmg)
|
|||||||
if (!dmg)
|
if (!dmg)
|
||||||
return '[font="sans-12"]' + translate("(None)") + '[/font]';
|
return '[font="sans-12"]' + translate("(None)") + '[/font]';
|
||||||
|
|
||||||
return Object.keys(g_DamageTypes).filter(
|
return g_DamageTypes.GetTypes().filter(
|
||||||
dmgType => dmg[dmgType]).map(
|
dmgType => dmg[dmgType]).map(
|
||||||
dmgType => sprintf(translate("%(damage)s %(damageType)s"), {
|
dmgType => sprintf(translate("%(damage)s %(damageType)s"), {
|
||||||
"damage": dmg[dmgType].toFixed(1),
|
"damage": dmg[dmgType].toFixed(1),
|
||||||
"damageType": unitFont(g_DamageTypes[dmgType])
|
"damageType": unitFont(translateWithContext("damage type", g_DamageTypes.GetNames()[dmgType]))
|
||||||
})).join(commaFont(translate(", ")));
|
})).join(commaFont(translate(", ")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ function getActualUpgradeData(upgradesInfo)
|
|||||||
{
|
{
|
||||||
upgrade.entity = upgrade.entity.replace("{civ}", g_SelectedCiv);
|
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.cost = upgrade.cost;
|
||||||
data.icon = upgrade.icon || data.icon;
|
data.icon = upgrade.icon || data.icon;
|
||||||
data.tooltip = upgrade.tooltip || data.tooltip;
|
data.tooltip = upgrade.tooltip || data.tooltip;
|
||||||
@@ -177,7 +177,7 @@ function unravelPhases(techs)
|
|||||||
function GetTemplateData(templateName)
|
function GetTemplateData(templateName)
|
||||||
{
|
{
|
||||||
var template = loadTemplate(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)
|
function isPairTech(technologyCode)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ var g_CivData = loadCivData(true, false);
|
|||||||
*/
|
*/
|
||||||
var g_ParsedData = {};
|
var g_ParsedData = {};
|
||||||
var g_ResourceData = new Resources();
|
var g_ResourceData = new Resources();
|
||||||
|
var g_DamageTypes = new DamageTypes();
|
||||||
|
|
||||||
// This must be defined after the g_TechnologyData cache object is declared.
|
// This must be defined after the g_TechnologyData cache object is declared.
|
||||||
var g_AutoResearchTechList = findAllAutoResearchedTechs();
|
var g_AutoResearchTechList = findAllAutoResearchedTechs();
|
||||||
@@ -101,7 +102,7 @@ function loadUnit(templateName)
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
let template = loadTemplate(templateName);
|
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)
|
if (template.ProductionQueue)
|
||||||
{
|
{
|
||||||
@@ -157,7 +158,7 @@ function loadStructure(templateName)
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
let template = loadTemplate(templateName);
|
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 = {
|
structure.production = {
|
||||||
"technology": [],
|
"technology": [],
|
||||||
|
|||||||
@@ -214,14 +214,14 @@ m.Template = m.Class({
|
|||||||
return +this.get("Cost/PopulationBonus");
|
return +this.get("Cost/PopulationBonus");
|
||||||
},
|
},
|
||||||
|
|
||||||
armourStrengths: function() {
|
"armourStrengths": function() {
|
||||||
if (!this.get("Armour"))
|
if (!this.get("Armour"))
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hack: +this.get("Armour/Hack"),
|
"Hack": +this.get("Armour/Hack"),
|
||||||
pierce: +this.get("Armour/Pierce"),
|
"Pierce": +this.get("Armour/Pierce"),
|
||||||
crush: +this.get("Armour/Crush")
|
"Crush": +this.get("Armour/Crush")
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -246,14 +246,14 @@ m.Template = m.Class({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
attackStrengths: function(type) {
|
"attackStrengths": function(type) {
|
||||||
if (!this.get("Attack/" + type +""))
|
if (!this.get("Attack/" + type +""))
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hack: +(this.get("Attack/" + type + "/Hack") || 0),
|
"Hack": +(this.get("Attack/" + type + "/Hack") || 0),
|
||||||
pierce: +(this.get("Attack/" + type + "/Pierce") || 0),
|
"Pierce": +(this.get("Attack/" + type + "/Pierce") || 0),
|
||||||
crush: +(this.get("Attack/" + type + "/Crush") || 0)
|
"Crush": +(this.get("Attack/" + type + "/Crush") || 0)
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -28,13 +28,13 @@ m.getMaxStrength = function(ent, againstClass)
|
|||||||
val *= ent.getMultiplierAgainst(type, againstClass);
|
val *= ent.getMultiplierAgainst(type, againstClass);
|
||||||
switch (str)
|
switch (str)
|
||||||
{
|
{
|
||||||
case "crush":
|
case "Crush":
|
||||||
strength += val * 0.085 / 3;
|
strength += val * 0.085 / 3;
|
||||||
break;
|
break;
|
||||||
case "hack":
|
case "Hack":
|
||||||
strength += val * 0.075 / 3;
|
strength += val * 0.075 / 3;
|
||||||
break;
|
break;
|
||||||
case "pierce":
|
case "Pierce":
|
||||||
strength += val * 0.065 / 3;
|
strength += val * 0.065 / 3;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -70,13 +70,13 @@ m.getMaxStrength = function(ent, againstClass)
|
|||||||
let val = parseFloat(armourStrength[str]);
|
let val = parseFloat(armourStrength[str]);
|
||||||
switch (str)
|
switch (str)
|
||||||
{
|
{
|
||||||
case "crush":
|
case "Crush":
|
||||||
strength += val * 0.085 / 3;
|
strength += val * 0.085 / 3;
|
||||||
break;
|
break;
|
||||||
case "hack":
|
case "Hack":
|
||||||
strength += val * 0.075 / 3;
|
strength += val * 0.075 / 3;
|
||||||
break;
|
break;
|
||||||
case "pierce":
|
case "Pierce":
|
||||||
strength += val * 0.065 / 3;
|
strength += val * 0.065 / 3;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -7,27 +7,11 @@ Armour.prototype.Schema =
|
|||||||
"<Pierce>0.0</Pierce>" +
|
"<Pierce>0.0</Pierce>" +
|
||||||
"<Crush>5.0</Crush>" +
|
"<Crush>5.0</Crush>" +
|
||||||
"</a:example>" +
|
"</a:example>" +
|
||||||
"<element name='Hack' a:help='Hack damage protection'>" +
|
DamageTypes.BuildSchema("damage protection") +
|
||||||
"<ref name='nonNegativeDecimal'/>" +
|
|
||||||
"</element>" +
|
|
||||||
"<element name='Pierce' a:help='Pierce damage protection'>" +
|
|
||||||
"<ref name='nonNegativeDecimal'/>" +
|
|
||||||
"</element>" +
|
|
||||||
"<element name='Crush' a:help='Crush damage protection'>" +
|
|
||||||
"<ref name='nonNegativeDecimal'/>" +
|
|
||||||
"</element>" +
|
|
||||||
"<optional>" +
|
"<optional>" +
|
||||||
"<element name='Foundation' a:help='Armour given to building foundations'>" +
|
"<element name='Foundation' a:help='Armour given to building foundations'>" +
|
||||||
"<interleave>" +
|
"<interleave>" +
|
||||||
"<element name='Hack' a:help='Hack damage protection'>" +
|
DamageTypes.BuildSchema("damage protection") +
|
||||||
"<ref name='nonNegativeDecimal'/>" +
|
|
||||||
"</element>" +
|
|
||||||
"<element name='Pierce' a:help='Pierce damage protection'>" +
|
|
||||||
"<ref name='nonNegativeDecimal'/>" +
|
|
||||||
"</element>" +
|
|
||||||
"<element name='Crush' a:help='Crush damage protection'>" +
|
|
||||||
"<ref name='nonNegativeDecimal'/>" +
|
|
||||||
"</element>" +
|
|
||||||
"</interleave>" +
|
"</interleave>" +
|
||||||
"</element>" +
|
"</element>" +
|
||||||
"</optional>";
|
"</optional>";
|
||||||
@@ -85,11 +69,11 @@ Armour.prototype.GetArmourStrengths = function()
|
|||||||
|
|
||||||
var foundation = Engine.QueryInterface(this.entity, IID_Foundation) && this.template.Foundation;
|
var foundation = Engine.QueryInterface(this.entity, IID_Foundation) && this.template.Foundation;
|
||||||
|
|
||||||
return {
|
let ret = {};
|
||||||
"hack": applyMods("Hack", foundation),
|
for (let damageType of DamageTypes.GetTypes())
|
||||||
"pierce": applyMods("Pierce", foundation),
|
ret[damageType] = applyMods(damageType, foundation);
|
||||||
"crush": applyMods("Crush", foundation)
|
|
||||||
};
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
Engine.RegisterComponentType(IID_DamageReceiver, "Armour", Armour);
|
Engine.RegisterComponentType(IID_DamageReceiver, "Armour", Armour);
|
||||||
|
|||||||
@@ -100,9 +100,7 @@ Attack.prototype.Schema =
|
|||||||
"<optional>" +
|
"<optional>" +
|
||||||
"<element name='Melee'>" +
|
"<element name='Melee'>" +
|
||||||
"<interleave>" +
|
"<interleave>" +
|
||||||
"<element name='Hack' a:help='Hack damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
DamageTypes.BuildSchema("damage strength") +
|
||||||
"<element name='Pierce' a:help='Pierce damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
|
||||||
"<element name='Crush' a:help='Crush damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
|
||||||
"<element name='MaxRange' a:help='Maximum attack range (in metres)'><ref name='nonNegativeDecimal'/></element>" +
|
"<element name='MaxRange' a:help='Maximum attack range (in metres)'><ref name='nonNegativeDecimal'/></element>" +
|
||||||
"<element name='PrepareTime' a:help='Time from the start of the attack command until the attack actually occurs (in milliseconds). This value relative to RepeatTime should closely match the \"event\" point in the actor's attack animation'>" +
|
"<element name='PrepareTime' a:help='Time from the start of the attack command until the attack actually occurs (in milliseconds). This value relative to RepeatTime should closely match the \"event\" point in the actor's attack animation'>" +
|
||||||
"<data type='nonNegativeInteger'/>" +
|
"<data type='nonNegativeInteger'/>" +
|
||||||
@@ -119,9 +117,7 @@ Attack.prototype.Schema =
|
|||||||
"<optional>" +
|
"<optional>" +
|
||||||
"<element name='Ranged'>" +
|
"<element name='Ranged'>" +
|
||||||
"<interleave>" +
|
"<interleave>" +
|
||||||
"<element name='Hack' a:help='Hack damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
DamageTypes.BuildSchema("damage strength") +
|
||||||
"<element name='Pierce' a:help='Pierce damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
|
||||||
"<element name='Crush' a:help='Crush damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
|
||||||
"<element name='MaxRange' a:help='Maximum attack range (in metres)'><ref name='nonNegativeDecimal'/></element>" +
|
"<element name='MaxRange' a:help='Maximum attack range (in metres)'><ref name='nonNegativeDecimal'/></element>" +
|
||||||
"<element name='MinRange' a:help='Minimum attack range (in metres)'><ref name='nonNegativeDecimal'/></element>" +
|
"<element name='MinRange' a:help='Minimum attack range (in metres)'><ref name='nonNegativeDecimal'/></element>" +
|
||||||
"<optional>"+
|
"<optional>"+
|
||||||
@@ -149,9 +145,7 @@ Attack.prototype.Schema =
|
|||||||
"<element name='Shape' a:help='Shape of the splash damage, can be circular or linear'><text/></element>" +
|
"<element name='Shape' a:help='Shape of the splash damage, can be circular or linear'><text/></element>" +
|
||||||
"<element name='Range' a:help='Size of the area affected by the splash'><ref name='nonNegativeDecimal'/></element>" +
|
"<element name='Range' a:help='Size of the area affected by the splash'><ref name='nonNegativeDecimal'/></element>" +
|
||||||
"<element name='FriendlyFire' a:help='Whether the splash damage can hurt non enemy units'><data type='boolean'/></element>" +
|
"<element name='FriendlyFire' a:help='Whether the splash damage can hurt non enemy units'><data type='boolean'/></element>" +
|
||||||
"<element name='Hack' a:help='Hack damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
DamageTypes.BuildSchema("damage strength") +
|
||||||
"<element name='Pierce' a:help='Pierce damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
|
||||||
"<element name='Crush' a:help='Crush damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
|
||||||
Attack.prototype.bonusesSchema +
|
Attack.prototype.bonusesSchema +
|
||||||
"</interleave>" +
|
"</interleave>" +
|
||||||
"</element>" +
|
"</element>" +
|
||||||
@@ -176,9 +170,7 @@ Attack.prototype.Schema =
|
|||||||
"<optional>" +
|
"<optional>" +
|
||||||
"<element name='Slaughter' a:help='A special attack to kill domestic animals'>" +
|
"<element name='Slaughter' a:help='A special attack to kill domestic animals'>" +
|
||||||
"<interleave>" +
|
"<interleave>" +
|
||||||
"<element name='Hack' a:help='Hack damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
DamageTypes.BuildSchema("damage strength") +
|
||||||
"<element name='Pierce' a:help='Pierce damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
|
||||||
"<element name='Crush' a:help='Crush damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
|
||||||
"<element name='MaxRange'><ref name='nonNegativeDecimal'/></element>" + // TODO: how do these work?
|
"<element name='MaxRange'><ref name='nonNegativeDecimal'/></element>" + // TODO: how do these work?
|
||||||
Attack.prototype.bonusesSchema +
|
Attack.prototype.bonusesSchema +
|
||||||
Attack.prototype.preferredClassesSchema +
|
Attack.prototype.preferredClassesSchema +
|
||||||
@@ -403,11 +395,11 @@ Attack.prototype.GetAttackStrengths = function(type)
|
|||||||
if (type == "Capture")
|
if (type == "Capture")
|
||||||
return { "value": applyMods("Value") };
|
return { "value": applyMods("Value") };
|
||||||
|
|
||||||
return {
|
let ret = {};
|
||||||
"hack": applyMods("Hack"),
|
for (let damageType of DamageTypes.GetTypes())
|
||||||
"pierce": applyMods("Pierce"),
|
ret[damageType] = applyMods(damageType);
|
||||||
"crush": applyMods("Crush")
|
|
||||||
};
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
Attack.prototype.GetSplashDamage = function(type)
|
Attack.prototype.GetSplashDamage = function(type)
|
||||||
@@ -502,7 +494,6 @@ Attack.prototype.PerformAttack = function(type, target)
|
|||||||
let cmpProjectileManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ProjectileManager);
|
let cmpProjectileManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ProjectileManager);
|
||||||
let id = cmpProjectileManager.LaunchProjectileAtPoint(this.entity, realTargetPosition, horizSpeed, gravity);
|
let id = cmpProjectileManager.LaunchProjectileAtPoint(this.entity, realTargetPosition, horizSpeed, gravity);
|
||||||
|
|
||||||
cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
|
|
||||||
let data = {
|
let data = {
|
||||||
"type": type,
|
"type": type,
|
||||||
"attacker": this.entity,
|
"attacker": this.entity,
|
||||||
|
|||||||
@@ -31,9 +31,7 @@ DeathDamage.prototype.Schema =
|
|||||||
"<element name='Shape' a:help='Shape of the splash damage, can be circular'><text/></element>" +
|
"<element name='Shape' a:help='Shape of the splash damage, can be circular'><text/></element>" +
|
||||||
"<element name='Range' a:help='Size of the area affected by the splash'><ref name='nonNegativeDecimal'/></element>" +
|
"<element name='Range' a:help='Size of the area affected by the splash'><ref name='nonNegativeDecimal'/></element>" +
|
||||||
"<element name='FriendlyFire' a:help='Whether the splash damage can hurt non enemy units'><data type='boolean'/></element>" +
|
"<element name='FriendlyFire' a:help='Whether the splash damage can hurt non enemy units'><data type='boolean'/></element>" +
|
||||||
"<element name='Hack' a:help='Hack damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
DamageTypes.BuildSchema("damage strength") +
|
||||||
"<element name='Pierce' a:help='Pierce damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
|
||||||
"<element name='Crush' a:help='Crush damage strength'><ref name='nonNegativeDecimal'/></element>" +
|
|
||||||
DeathDamage.prototype.bonusesSchema;
|
DeathDamage.prototype.bonusesSchema;
|
||||||
|
|
||||||
DeathDamage.prototype.Init = function()
|
DeathDamage.prototype.Init = function()
|
||||||
@@ -48,11 +46,11 @@ DeathDamage.prototype.GetDeathDamageStrengths = function()
|
|||||||
let applyMods = damageType =>
|
let applyMods = damageType =>
|
||||||
ApplyValueModificationsToEntity("DeathDamage/" + damageType, +(this.template[damageType] || 0), this.entity);
|
ApplyValueModificationsToEntity("DeathDamage/" + damageType, +(this.template[damageType] || 0), this.entity);
|
||||||
|
|
||||||
return {
|
let ret = {};
|
||||||
"hack": applyMods("Hack"),
|
for (let damageType of DamageTypes.GetTypes())
|
||||||
"pierce": applyMods("Pierce"),
|
ret[damageType] = applyMods(damageType);
|
||||||
"crush": applyMods("Crush")
|
|
||||||
};
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
DeathDamage.prototype.GetBonusTemplate = function()
|
DeathDamage.prototype.GetBonusTemplate = function()
|
||||||
|
|||||||
@@ -656,14 +656,14 @@ GuiInterface.prototype.GetTemplateData = function(player, name)
|
|||||||
let aurasTemplate = {};
|
let aurasTemplate = {};
|
||||||
|
|
||||||
if (!template.Auras)
|
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
|
// Add aura name and description loaded from JSON file
|
||||||
let auraNames = template.Auras._string.split(/\s+/);
|
let auraNames = template.Auras._string.split(/\s+/);
|
||||||
let cmpDataTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_DataTemplateManager);
|
let cmpDataTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_DataTemplateManager);
|
||||||
for (let name of auraNames)
|
for (let name of auraNames)
|
||||||
aurasTemplate[name] = cmpDataTemplateManager.GetAuraTemplate(name);
|
aurasTemplate[name] = cmpDataTemplateManager.GetAuraTemplate(name);
|
||||||
return GetTemplateDataHelper(template, player, aurasTemplate, Resources);
|
return GetTemplateDataHelper(template, player, aurasTemplate, Resources, DamageTypes);
|
||||||
};
|
};
|
||||||
|
|
||||||
GuiInterface.prototype.GetTechnologyData = function(player, data)
|
GuiInterface.prototype.GetTechnologyData = function(player, data)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
Engine.LoadHelperScript("DamageBonus.js");
|
Engine.LoadHelperScript("DamageBonus.js");
|
||||||
|
Engine.LoadHelperScript("DamageTypes.js");
|
||||||
Engine.LoadHelperScript("Player.js");
|
Engine.LoadHelperScript("Player.js");
|
||||||
Engine.LoadHelperScript("ValueModification.js");
|
Engine.LoadHelperScript("ValueModification.js");
|
||||||
Engine.LoadComponentScript("interfaces/Auras.js");
|
Engine.LoadComponentScript("interfaces/Auras.js");
|
||||||
@@ -139,15 +140,15 @@ attackComponentTest(undefined, true ,(attacker, cmpAttack, defender) => {
|
|||||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackStrengths("Capture"), { "value": 8 });
|
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackStrengths("Capture"), { "value": 8 });
|
||||||
|
|
||||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackStrengths("Ranged"), {
|
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackStrengths("Ranged"), {
|
||||||
"hack": 0,
|
"Hack": 0,
|
||||||
"pierce": 10,
|
"Pierce": 10,
|
||||||
"crush": 0
|
"Crush": 0
|
||||||
});
|
});
|
||||||
|
|
||||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackStrengths("Ranged.Splash"), {
|
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackStrengths("Ranged.Splash"), {
|
||||||
"hack": 0.0,
|
"Hack": 0.0,
|
||||||
"pierce": 15.0,
|
"Pierce": 15.0,
|
||||||
"crush": 35.0
|
"Crush": 35.0
|
||||||
});
|
});
|
||||||
|
|
||||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetTimers("Ranged"), {
|
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetTimers("Ranged"), {
|
||||||
@@ -160,7 +161,13 @@ attackComponentTest(undefined, true ,(attacker, cmpAttack, defender) => {
|
|||||||
"repeat": 1000
|
"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"])
|
for (let className of ["Infantry", "Cavalry"])
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
Engine.LoadHelperScript("DamageBonus.js");
|
Engine.LoadHelperScript("DamageBonus.js");
|
||||||
|
Engine.LoadHelperScript("DamageTypes.js");
|
||||||
Engine.LoadHelperScript("Player.js");
|
Engine.LoadHelperScript("Player.js");
|
||||||
Engine.LoadHelperScript("Sound.js");
|
Engine.LoadHelperScript("Sound.js");
|
||||||
Engine.LoadHelperScript("ValueModification.js");
|
Engine.LoadHelperScript("ValueModification.js");
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
Engine.LoadHelperScript("DamageBonus.js");
|
Engine.LoadHelperScript("DamageBonus.js");
|
||||||
|
Engine.LoadHelperScript("DamageTypes.js");
|
||||||
Engine.LoadHelperScript("ValueModification.js");
|
Engine.LoadHelperScript("ValueModification.js");
|
||||||
Engine.LoadComponentScript("interfaces/AuraManager.js");
|
Engine.LoadComponentScript("interfaces/AuraManager.js");
|
||||||
Engine.LoadComponentScript("interfaces/Damage.js");
|
Engine.LoadComponentScript("interfaces/Damage.js");
|
||||||
@@ -26,9 +27,9 @@ let template = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let modifiedDamage = {
|
let modifiedDamage = {
|
||||||
"hack": 0.0,
|
"Hack": 0.0,
|
||||||
"pierce": 215.0,
|
"Pierce": 215.0,
|
||||||
"crush": 35.0
|
"Crush": 35.0
|
||||||
};
|
};
|
||||||
|
|
||||||
let cmpDeathDamage = ConstructComponent(deadEnt, "DeathDamage", template);
|
let cmpDeathDamage = ConstructComponent(deadEnt, "DeathDamage", template);
|
||||||
|
|||||||
@@ -126,11 +126,11 @@ cmpUpgrade.owner = playerID;
|
|||||||
* To start with, no techs are researched...
|
* 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).
|
// 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 });
|
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).
|
// 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 });
|
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.
|
// T3: Check that the value is correct within the Update Component.
|
||||||
@@ -144,11 +144,11 @@ cmpUpgrade.Upgrade("structures/"+civCode+"_defense_tower");
|
|||||||
isResearched = true;
|
isResearched = true;
|
||||||
|
|
||||||
// T4: Check that the player-less value hasn't increased...
|
// 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 });
|
TS_ASSERT_UNEVAL_EQUALS(parsed_template.upgrades[0].cost, { "stone": 100, "wood": 50, "time": 100 });
|
||||||
|
|
||||||
// T5: ...but the player-backed value has.
|
// 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 });
|
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...
|
// T6: The upgrade component should still be using the old resource cost (but new time cost) for the upgrade in progress...
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
DamageTypes.prototype.BuildSchema = function(helptext = "")
|
||||||
|
{
|
||||||
|
return this.GetTypes().reduce((schema, type) =>
|
||||||
|
schema + "<element name='"+type+"' a:help='"+type+" "+helptext+"'><ref name='nonNegativeDecimal'/></element>",
|
||||||
|
"");
|
||||||
|
};
|
||||||
|
|
||||||
|
DamageTypes = new DamageTypes();
|
||||||
Reference in New Issue
Block a user