mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-08-15 14:43:32 -07:00
Revamp GetTemplateDataHelper
This patch is primarily meant as preparation in order to be able to reuse this logic for GetEntityState calls in the future. Key changes: - Clearer API by providing different functions for different purposes. - Slight performance optimisation by storing parameters in a context object and pulling the info from there instead of redeclaring a lambda each time, which it seems Spidermonkey struggled to optimise well. - Allow computing only partial template data, specified by passing a list of desired components. (to be used more in the future) - Make it so the naming and structure of template data and matches 1:1 with the data in entity states. This makes accessing values from them more consistent and would also allow e.g. adopting data between the two in the future.
This commit is contained in:
parent
f90804c78f
commit
a89ce596a4
10 changed files with 587 additions and 495 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -157,12 +157,12 @@ function getHistoryTooltip(template)
|
|||
|
||||
function getHealthTooltip(template)
|
||||
{
|
||||
if (!template.health)
|
||||
if (!template.maxHitpoints)
|
||||
return "";
|
||||
|
||||
return sprintf(translate("%(label)s %(details)s"), {
|
||||
"label": headerFont(translate("Health:")),
|
||||
"details": template.health
|
||||
"details": template.maxHitpoints
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class TemplateParser
|
|||
return null;
|
||||
|
||||
const template = this.TemplateLoader.loadEntityTemplate(templateName, civCode);
|
||||
const parsed = GetTemplateDataHelper(template, null, this.TemplateLoader.auraData, g_ResourceData, this.modifiers[civCode] || {});
|
||||
const parsed = g_TemplateHelper.computeDataFromModifiers(template, this.TemplateLoader.auraData, g_ResourceData, this.modifiers[civCode] || {});
|
||||
parsed.name.internal = templateName;
|
||||
|
||||
parsed.history = template.Identity.History;
|
||||
|
|
@ -118,11 +118,11 @@ class TemplateParser
|
|||
parsed.resistance = struct.resistance;
|
||||
parsed.auras = struct.auras;
|
||||
|
||||
// For technology cost multiplier, we need to use the tower
|
||||
// For technology cost multiplier (in the researcher component), we need to use the tower
|
||||
struct = this.getEntity(parsed.wallSet.templates.tower, civCode);
|
||||
parsed.techCostMultiplier = struct.techCostMultiplier;
|
||||
parsed.researcher = struct.researcher;
|
||||
|
||||
let health;
|
||||
let hitpoints;
|
||||
|
||||
for (const wSegm in parsed.wallSet.templates)
|
||||
{
|
||||
|
|
@ -141,30 +141,30 @@ class TemplateParser
|
|||
if (["gate", "tower"].indexOf(wSegm) != -1)
|
||||
continue;
|
||||
|
||||
if (!health)
|
||||
if (!hitpoints)
|
||||
{
|
||||
health = { "min": wPart.health, "max": wPart.health };
|
||||
hitpoints = { "min": wPart.maxHitpoints, "max": wPart.maxHitpoints };
|
||||
continue;
|
||||
}
|
||||
|
||||
health.min = Math.min(health.min, wPart.health);
|
||||
health.max = Math.max(health.max, wPart.health);
|
||||
hitpoints.min = Math.min(hitpoints.min, wPart.maxHitpoints);
|
||||
hitpoints.max = Math.max(hitpoints.max, wPart.maxHitpoints);
|
||||
}
|
||||
|
||||
if (parsed.wallSet.templates.curves)
|
||||
for (const curve of parsed.wallSet.templates.curves)
|
||||
{
|
||||
const wPart = this.getEntity(curve, civCode);
|
||||
health.min = Math.min(health.min, wPart.health);
|
||||
health.max = Math.max(health.max, wPart.health);
|
||||
hitpoints.min = Math.min(hitpoints.min, wPart.maxHitpoints);
|
||||
hitpoints.max = Math.max(hitpoints.max, wPart.maxHitpoints);
|
||||
}
|
||||
|
||||
if (health.min == health.max)
|
||||
parsed.health = health.min;
|
||||
if (hitpoints.min === hitpoints.max)
|
||||
parsed.maxHitpoints = hitpoints.min;
|
||||
else
|
||||
parsed.health = sprintf(translate("%(health_min)s to %(health_max)s"), {
|
||||
"health_min": health.min,
|
||||
"health_max": health.max
|
||||
parsed.maxHitpoints = sprintf(translate("%(health_min)s to %(health_max)s"), {
|
||||
"health_min": hitpoints.min,
|
||||
"health_max": hitpoints.max
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -252,7 +252,7 @@ class TemplateParser
|
|||
|
||||
/**
|
||||
* Provided with an array containing basic information about possible
|
||||
* upgrades, such as that generated by globalscript's GetTemplateDataHelper,
|
||||
* upgrades, such as that generated by globalscript's g_TemplateHelper,
|
||||
* this function loads the actual template data of the upgrades, overwrites
|
||||
* certain values within, then passes an array containing the template data
|
||||
* back to caller.
|
||||
|
|
@ -264,7 +264,7 @@ class TemplateParser
|
|||
{
|
||||
upgrade.entity = upgrade.entity.replace(/\{(civ|native)\}/g, civCode);
|
||||
|
||||
const data = GetTemplateDataHelper(this.TemplateLoader.loadEntityTemplate(upgrade.entity, civCode), null, this.TemplateLoader.auraData, g_ResourceData, this.modifiers[civCode] || {});
|
||||
const data = g_TemplateHelper.computeDataFromModifiers(this.TemplateLoader.loadEntityTemplate(upgrade.entity, civCode), this.TemplateLoader.auraData, g_ResourceData, this.modifiers[civCode] || {});
|
||||
data.name.internal = upgrade.entity;
|
||||
data.cost = upgrade.cost;
|
||||
data.icon = upgrade.icon || data.icon;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ var g_Page;
|
|||
function GetTemplateData(templateName)
|
||||
{
|
||||
const template = g_Page.TemplateLoader.loadEntityTemplate(templateName, g_Page.activeCiv);
|
||||
return GetTemplateDataHelper(template, null, g_Page.TemplateLoader.auraData, g_ResourceData, g_Page.TemplateParser.getModifiers(g_Page.activeCiv));
|
||||
return g_TemplateHelper.computeDataFromModifiers(template, g_Page.TemplateLoader.auraData, g_ResourceData, g_Page.TemplateParser.getModifiers(g_Page.activeCiv));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ class ProductionRowManager
|
|||
case "techs":
|
||||
pIdx = this.page.TemplateParser.phaseList.indexOf(this.page.TemplateParser.getPhaseOfTechnology(prod, civCode));
|
||||
prod = clone(this.page.TemplateParser.getTechnology(prod, civCode));
|
||||
for (const res in template.techCostMultiplier)
|
||||
for (const res in template.researcher.techCostMultiplier)
|
||||
if (prod.cost[res])
|
||||
prod.cost[res] *= template.techCostMultiplier[res];
|
||||
prod.cost[res] *= template.researcher.techCostMultiplier[res];
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -78,8 +78,8 @@ class ViewerPage extends ReferencePage
|
|||
if (researchers && researchers.length)
|
||||
{
|
||||
this.currentTemplate.researchedByListOfNames = researchers.map(researcher => getEntityNames(this.TemplateParser.getEntity(researcher, this.activeCiv)));
|
||||
const { techCostMultiplier } = this.TemplateParser.getEntity(researchers[0], this.activeCiv);
|
||||
for (const res in this.currentTemplate.cost)
|
||||
const techCostMultiplier = this.TemplateParser.getEntity(researchers[0], this.activeCiv).researcher.techCostMultiplier;
|
||||
for (const res in techCostMultiplier)
|
||||
if (this.currentTemplate.cost[res])
|
||||
this.currentTemplate.cost[res] *= techCostMultiplier[res];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ function loadWallsetsFromCivData()
|
|||
function loadWallset(wallsetPath, civ)
|
||||
{
|
||||
const newWallset = { "curves": [] };
|
||||
const wallsetData = GetTemplateDataHelper(wallsetPath, null, null, g_Resources).wallSet;
|
||||
const wallsetData = g_TemplateHelper.getBasicData(wallsetPath, {}, g_Resources, ["WallSet"]).wallSet;
|
||||
|
||||
for (const element in wallsetData.templates)
|
||||
if (element == "curves")
|
||||
|
|
@ -271,7 +271,7 @@ function getWallElement(element, style)
|
|||
function readyWallElement(path, civCode)
|
||||
{
|
||||
path = path.replace(/\{civ\}/g, civCode);
|
||||
const template = GetTemplateDataHelper(Engine.GetTemplate(path), null, null, g_Resources);
|
||||
const template = g_TemplateHelper.getBasicData(Engine.GetTemplate(path), null, g_Resources, ["WallPiece", "Obstruction"]);
|
||||
const length = template.wallPiece ? template.wallPiece.length : template.obstruction.shape.width;
|
||||
|
||||
return deepfreeze({
|
||||
|
|
|
|||
|
|
@ -654,7 +654,7 @@ GuiInterface.prototype.GetTemplateData = function(player, data)
|
|||
const aurasTemplate = {};
|
||||
|
||||
if (!template.Auras)
|
||||
return GetTemplateDataHelper(template, owner, aurasTemplate, Resources);
|
||||
return g_TemplateHelper.computeDataFromPlayer(template, aurasTemplate, Resources, owner);
|
||||
|
||||
const auraNames = template.Auras._string.split(/\s+/);
|
||||
|
||||
|
|
@ -667,7 +667,7 @@ GuiInterface.prototype.GetTemplateData = function(player, data)
|
|||
aurasTemplate[name] = auraTemplate;
|
||||
}
|
||||
|
||||
return GetTemplateDataHelper(template, owner, aurasTemplate, Resources);
|
||||
return g_TemplateHelper.computeDataFromPlayer(template, aurasTemplate, Resources, owner);
|
||||
};
|
||||
|
||||
GuiInterface.prototype.AreRequirementsMet = function(player, data)
|
||||
|
|
|
|||
|
|
@ -139,8 +139,7 @@ AddMock(100, IID_Diplomacy, {
|
|||
|
||||
AddMock(100, IID_Identity, {
|
||||
"GetName": function() { return "Player 1"; },
|
||||
"GetCiv": function() { return "gaia"; },
|
||||
"GetRankTechName": function() { return undefined; }
|
||||
"GetCiv": function() { return "gaia"; }
|
||||
});
|
||||
|
||||
AddMock(100, IID_EntityLimits, {
|
||||
|
|
@ -236,8 +235,7 @@ AddMock(101, IID_Diplomacy, {
|
|||
|
||||
AddMock(101, IID_Identity, {
|
||||
"GetName": function() { return "Player 2"; },
|
||||
"GetCiv": function() { return "mace"; },
|
||||
"GetRankTechName": function() { return undefined; }
|
||||
"GetCiv": function() { return "mace"; }
|
||||
});
|
||||
|
||||
AddMock(101, IID_EntityLimits, {
|
||||
|
|
@ -593,8 +591,7 @@ AddMock(10, IID_Identity, {
|
|||
"GetSelectionGroupName": function() { return "Selection Group Name"; },
|
||||
"HasClass": function() { return true; },
|
||||
"IsUndeletable": function() { return false; },
|
||||
"IsControllable": function() { return true; },
|
||||
"GetRankTechName": function() { return undefined; }
|
||||
"IsControllable": function() { return true; }
|
||||
});
|
||||
|
||||
AddMock(10, IID_Position, {
|
||||
|
|
@ -623,7 +620,6 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetEntityState(-1, 10), {
|
|||
"template": "example",
|
||||
"identity": {
|
||||
"rank": "foo",
|
||||
"rankTechName": undefined,
|
||||
"classes": ["class1", "class2"],
|
||||
"selectionGroupName": "Selection Group Name",
|
||||
"canDelete": true,
|
||||
|
|
|
|||
|
|
@ -140,12 +140,12 @@ cmpUpgrade.OnOwnershipChanged({ "to": playerID });
|
|||
* Now to start the test proper
|
||||
* 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);
|
||||
// T1: Check the cost of the upgrade without accounting for any player modifications (as it would be in the structree).
|
||||
let parsed_template = g_TemplateHelper.getBasicData(template, {}, Resources, ["Upgrade"]);
|
||||
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);
|
||||
// T2: Check the value, this time accounting for player modifiers (as it would be in-session).
|
||||
parsed_template = g_TemplateHelper.computeDataFromPlayer(template, {}, Resources, playerID, ["Upgrade"]);
|
||||
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.
|
||||
|
|
@ -159,11 +159,11 @@ cmpUpgrade.Upgrade("structures/" + civCode + "/defense_tower");
|
|||
isResearched = true;
|
||||
|
||||
// T4: Check that the player-less value hasn't increased...
|
||||
parsed_template = GetTemplateDataHelper(template, null, {}, Resources);
|
||||
parsed_template = g_TemplateHelper.getBasicData(template, {}, Resources, ["Upgrade"]);
|
||||
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 = g_TemplateHelper.computeDataFromPlayer(template, {}, Resources, playerID, ["Upgrade"]);
|
||||
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...
|
||||
|
|
|
|||
Loading…
Reference in a new issue