1
0
forked from mirrors/0ad

Bugfix & optimisations to ApplyModifiers

This functions is amongst the most called in JS, so it's important to
make it speedy.

- Bugfix: if 'originalValue' is falsy, the result was never cached. This
in particular affected the minRange of archers, which is 0. It's a large
optimisation on combatDemoHuge, but the effect elsewhere is less likely
to be noticeable.
- Don't go through the helper to get the player Entity ID, in this case
it's slower.
- Concat is slower than Flat() in this case according to my profiling.
- Some micro-optimisation by strict equality.

Differential Revision: https://code.wildfiregames.com/D5012
This was SVN commit r27696.
This commit is contained in:
wraitii
2023-06-14 07:27:06 +00:00
parent 080599442f
commit cce7d02036
2 changed files with 15 additions and 16 deletions
@@ -86,16 +86,16 @@ function MatchesClassList(classes, match)
if (!match || !classes)
return undefined;
// Transform the string to an array
if (typeof match == "string")
if (typeof match === "string")
match = match.split(/\s+/);
for (let sublist of match)
{
// If the elements are still strings, split them by space or by '+'
if (typeof sublist == "string")
if (typeof sublist === "string")
sublist = sublist.split(/[+\s]+/);
if (sublist.every(c => (c[0] == "!" && classes.indexOf(c.substr(1)) == -1) ||
(c[0] != "!" && classes.indexOf(c) != -1)))
if (sublist.every(c => (c[0] === "!" && classes.indexOf(c.substr(1)) === -1) ||
(c[0] !== "!" && classes.indexOf(c) !== -1)))
return true;
}
@@ -106,8 +106,8 @@ ModifiersManager.prototype.FetchModifiedProperty = function(classesList, propert
return originalValue;
// Flatten the list of modifications
let modifications = [];
modifs.forEach(item => { modifications = modifications.concat(item.value); });
return GetTechModifiedProperty(modifications, classesList, originalValue);
modifs.forEach(item => { modifications.push(item.value); });
return GetTechModifiedProperty(modifications.flat(), classesList, originalValue);
};
/**
@@ -142,23 +142,17 @@ ModifiersManager.prototype.Cache = function(classesList, propertyName, originalV
ModifiersManager.prototype.ApplyModifiers = function(propertyName, originalValue, entity)
{
let newValue = this.cachedValues.get(propertyName);
if (newValue)
if (newValue !== undefined)
{
newValue = newValue.get(entity);
if (newValue)
if (newValue !== undefined)
{
newValue = newValue.get(originalValue);
if (newValue)
if (newValue !== undefined)
return newValue;
}
}
// Get the entity ID of the player / owner of the entity, since we use that to store per-player modifiers
// (this prevents conflicts between player ID and entity ID).
let ownerEntity = QueryOwnerEntityID(entity);
if (ownerEntity == entity)
ownerEntity = null;
newValue = originalValue;
let cmpIdentity = QueryMiragedInterface(entity, IID_Identity);
@@ -166,9 +160,14 @@ ModifiersManager.prototype.ApplyModifiers = function(propertyName, originalValue
return originalValue;
let classesList = cmpIdentity.GetClassesList();
// Get the entity ID of the player / owner of the entity, since we use that to store per-player modifiers
// (this prevents conflicts between player ID and entity ID).
let ownerPlayer = Engine.QueryInterface(entity, IID_Ownership)?.GetOwner();
// Apply player-wide modifiers before entity-local modifiers.
if (ownerEntity)
if (ownerPlayer !== undefined && ownerPlayer !== INVALID_PLAYER)
{
const ownerEntity = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetPlayerByID(ownerPlayer);
let pc = this.playerEntitiesCached.get(ownerEntity).get(propertyName);
if (!pc)
pc = this.playerEntitiesCached.get(ownerEntity).set(propertyName, new Set()).get(propertyName);