Fix tech modifications calculations so we don't bump into stupid mistakes again (f.e. multiplying two positive numbers is now guaranteed to stay positive). See 7f300bbf3d and 0b8845eb4f

This was SVN commit r18207.
This commit is contained in:
sanderd17 2016-05-20 11:20:51 +00:00
parent ec1696ded3
commit 9368ffe345
3 changed files with 36 additions and 45 deletions

View File

@ -6,50 +6,41 @@
*/
/**
* Returns modified property value if at least one tech modification is found
* applicable to the given entity template; else, returns its original value.
* Returns modified property value modified by the applicable tech
* modifications.
*
* currentTechModifications: mapping of property names to modification arrays,
* retrieved from the intended player's TechnologyManager.
* entityTemplateData: raw entity template object.
* propertyName: name of the tech modification to apply.
* propertyValue: original value of property to be modified.
* @param currentTechModifications Object with mapping of property names to
* modification arrays, retrieved from the intended player's TechnologyManager.
* @param classes Array contianing the class list of the template.
* @param propertyName String encoding the name of the value.
* @param propertyValue Number storing the original value. Can also be
* non-numberic, but then only "replace" techs can be supported.
*/
function GetTechModifiedProperty(currentTechModifications, entityTemplateData, propertyName, propertyValue)
function GetTechModifiedProperty(currentTechModifications, classes, propertyName, propertyValue)
{
// Get all modifications to this value
var modifications = currentTechModifications[propertyName];
if (!modifications) // no modifications so return the original value
return propertyValue;
let modifications = currentTechModifications[propertyName] || [];
// TODO: will we ever need the full template?
// Get the classes which this entity template belongs to
var classes = [];
if (entityTemplateData && entityTemplateData.Identity)
classes = GetIdentityClasses(entityTemplateData.Identity);
let multiply = 1;
let add = 0;
var retValue = propertyValue;
for (var i in modifications)
for (let modification of modifications)
{
var modification = modifications[i];
if (DoesModificationApply(modification, classes))
{
// We found a match, apply the modification
// Nothing is cumulative so that ordering doesn't matter as much as possible
if (modification.multiply)
retValue += (modification.multiply - 1) * propertyValue;
else if (modification.add)
retValue += modification.add;
else if (modification.replace !== undefined) // This will depend on ordering because there is no choice
retValue = modification.replace;
else
warn("GetTechModifiedProperty: modification format not recognised (modifying " + propertyName + "): " + uneval(modification));
}
if (!DoesModificationApply(modification, classes))
continue;
if (modification.replace !== undefined)
return modification.replace;
if (modification.multiply)
multiply *= modification.multiply;
else if (modification.add)
add += modification.add;
else
warn("GetTechModifiedProperty: modification format not recognised (modifying " + propertyName + "): " + uneval(modification));
}
return retValue;
// Note, some components pass non-numeric values (for which only the "replace" modification makes sense)
if (typeof propertyValue == "number")
return propertyValue * multiply + add;
return propertyValue;
}
/**

View File

@ -377,13 +377,11 @@ TechnologyManager.prototype.ApplyModifications = function(valueName, curValue, e
if (!this.modificationCache[valueName][ent] || this.modificationCache[valueName][ent].origValue != curValue)
{
this.modificationCache[valueName][ent] = {"origValue": curValue};
var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
var templateName = cmpTemplateManager.GetCurrentTemplateName(ent);
// Ensure that preview or construction entites have the same properties as the final building
if (templateName.indexOf("preview|") > -1 || templateName.indexOf("construction|") > -1 )
templateName = templateName.slice(templateName.indexOf("|") + 1);
this.modificationCache[valueName][ent].newValue = GetTechModifiedProperty(this.modifications, cmpTemplateManager.GetTemplate(templateName), valueName, curValue);
this.modificationCache[valueName][ent] = { "origValue": curValue };
let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
if (!cmpIdentity)
return curValue;
this.modificationCache[valueName][ent].newValue = GetTechModifiedProperty(this.modifications, cmpIdentity.GetClassesList(), valueName, curValue);
}
return this.modificationCache[valueName][ent].newValue;
@ -392,7 +390,9 @@ TechnologyManager.prototype.ApplyModifications = function(valueName, curValue, e
// Alternative version of ApplyModifications, applies to templates instead of entities
TechnologyManager.prototype.ApplyModificationsTemplate = function(valueName, curValue, template)
{
return GetTechModifiedProperty(this.modifications, template, valueName, curValue);
if (!template || !template.Identity)
return curValue;
return GetTechModifiedProperty(this.modifications, GetIdentityClasses(template.Identity), valueName, curValue);
};
// Marks a technology as being queued for research

View File

@ -6,7 +6,7 @@
{"value": "Armour/Pierce", "add": 1 },
{"value": "Armour/Crush", "add": 1 },
{"value": "Attack/Capture/Value", "add": 0.4 },
{"value": "ResourceGatherer/BaseSpeed", "multiply": 0.75 },
{"value": "ResourceGatherer/BaseSpeed", "multiply": 0.5 },
{"value": "UnitMotion/WalkSpeed", "add": 0.5, "affects": "Infantry"},
{"value": "UnitMotion/WalkSpeed", "add": 1, "affects": "Cavalry" },
{"value": "Attack/Ranged/MaxRange", "add": 4, "affects": "Ranged" },