Index: binaries/data/mods/public/globalscripts/ModificationTemplates.js
===================================================================
--- binaries/data/mods/public/globalscripts/ModificationTemplates.js
+++ binaries/data/mods/public/globalscripts/ModificationTemplates.js
@@ -17,11 +17,6 @@
deepfreeze(this.templates);
}
-ModificationTemplates.prototype.GetNames = function()
-{
- return this.names;
-};
-
ModificationTemplates.prototype.Has = function(name)
{
return this.names.indexOf(name) != -1;
@@ -37,11 +32,9 @@
return this.templates;
};
-
function LoadModificationTemplates()
{
global.AuraTemplates = new ModificationTemplates("simulation/data/auras/");
- global.TechnologyTemplates = new ModificationTemplates("simulation/data/technologies/");
}
/**
Index: binaries/data/mods/public/globalscripts/Templates.js
===================================================================
--- binaries/data/mods/public/globalscripts/Templates.js
+++ binaries/data/mods/public/globalscripts/Templates.js
@@ -313,8 +313,12 @@
if (template.Cost)
{
ret.cost = {};
- for (let resCode in template.Cost.Resources)
- ret.cost[resCode] = getEntityValue("Cost/Resources/" + resCode);
+ if (template.Cost.Resources)
+ {
+ ret.cost.resources = {}
+ for (let resCode in template.Cost.Resources)
+ ret.cost.resources[resCode] = getEntityValue("Cost/Resources/" + resCode);
+ }
if (template.Cost.Population)
ret.cost.population = getEntityValue("Cost/Population");
@@ -494,6 +498,15 @@
"GainMultiplier": getEntityValue("Trader/GainMultiplier")
};
+ if (template.Technology)
+ ret.technology = {
+ "choice": template.Technology.Choice,
+ "choiceRoot": template.Technology.ChoiceRoot,
+ "ID": template.Technology.ID,
+ "modifications": template.Technology.Modifiers,
+ "supersedes": template.Technology.Supersedes
+ };
+
if (template.Treasure)
{
ret.treasure = {
@@ -551,49 +564,6 @@
}
/**
- * Get basic information about a technology template.
- * @param {Object} template - A valid template as obtained by loading the tech JSON file.
- * @param {string} civ - Civilization for which the tech requirements should be calculated.
- */
-function GetTechnologyBasicDataHelper(template, civ)
-{
- return {
- "name": {
- "generic": template.genericName
- },
- "icon": template.icon ? "technologies/" + template.icon : undefined,
- "description": template.description,
- "reqs": DeriveTechnologyRequirements(template, civ),
- "modifications": template.modifications,
- "affects": template.affects,
- "replaces": template.replaces
- };
-}
-
-/**
- * Get information about a technology template.
- * @param {Object} template - A valid template as obtained by loading the tech JSON file.
- * @param {string} civ - Civilization for which the specific name and tech requirements should be returned.
- * @param {Object} resources - An instance of the Resources class.
- */
-function GetTechnologyDataHelper(template, civ, resources)
-{
- let ret = GetTechnologyBasicDataHelper(template, civ);
-
- if (template.specificName)
- ret.name.specific = template.specificName[civ] || template.specificName.generic;
-
- ret.cost = { "time": template.researchTime ? +template.researchTime : 0 };
- for (let type of resources.GetCodes())
- ret.cost[type] = +(template.cost && template.cost[type] || 0);
-
- ret.tooltip = template.tooltip;
- ret.requirementsTooltip = template.requirementsTooltip || "";
-
- return ret;
-}
-
-/**
* Get information about an aura template.
* @param {object} template - A valid template as obtained by loading the aura JSON file.
*/
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
@@ -971,7 +971,7 @@
if ("Techs" in requirements && !requirements.Techs._string.includes(" ") &&
requirements.Techs._string[0] != "!")
return objectionFont(sprintf(translate("Requires %(technology)s"), {
- "technology": getEntityNames(GetTechnologyData(requirements.Techs._string, civ))
+ "technology": getEntityNames(GetTemplateData(Engine.GetTemplate(requirements.Techs._string), civ))
}));
// More complex ones need a tooltip.
Index: binaries/data/mods/public/gui/reference/common/TemplateLoader.js
===================================================================
--- binaries/data/mods/public/gui/reference/common/TemplateLoader.js
+++ binaries/data/mods/public/gui/reference/common/TemplateLoader.js
@@ -100,23 +100,17 @@
*
* Loads from local cache if available, else from file system.
*
+ * @param {string} civCode
* @param {string} templateName
* @return {Object} Object containing raw template data.
*/
- loadTechnologyTemplate(templateName)
+ loadTechnologyTemplate(templateName, civCode)
{
if (!(templateName in this.technologyData))
{
- let data = Engine.ReadJSONFile(this.TechnologyPath + templateName + ".json");
+ const data = clone(Engine.GetTemplate(templateName));
translateObjectKeys(data, this.TechnologyTranslateKeys);
- // Translate specificName as in GetTechnologyData() from gui/session/session.js
- if (typeof (data.specificName) === 'object')
- for (let civ in data.specificName)
- data.specificName[civ] = translate(data.specificName[civ]);
- else if (data.specificName)
- warn("specificName should be an object of civ->name mappings in " + templateName + ".json");
-
this.technologyData[templateName] = data;
}
@@ -232,21 +226,15 @@
}
/**
- * Crudely iterates through every tech JSON file and identifies those
+ * Crudely iterates through every tech file and identifies those
* that are auto-researched.
*
* @return {array} List of techs that are researched automatically
*/
findAllAutoResearchedTechs()
{
- let techList = [];
- for (let templateName of listFiles(this.TechnologyPath, ".json", true))
- {
- let data = this.loadTechnologyTemplate(templateName);
- if (data && data.autoResearch)
- techList.push(templateName);
- }
- return techList;
+ return Engine.FindAllTemplates().filter(templateName =>
+ this.loadTechnologyTemplate(templateName)?.Technology?.AutoResearched);
}
/**
@@ -333,4 +321,4 @@
*/
TemplateLoader.prototype.AuraTranslateKeys = ["auraName", "auraDescription"];
TemplateLoader.prototype.EntityTranslateKeys = ["GenericName", "SpecificName", "Tooltip", "History"];
-TemplateLoader.prototype.TechnologyTranslateKeys = ["genericName", "tooltip", "description"];
+TemplateLoader.prototype.TechnologyTranslateKeys = ["GenericName", "SpecificName", "Tooltip", "History"];
Index: binaries/data/mods/public/gui/reference/common/TemplateParser.js
===================================================================
--- binaries/data/mods/public/gui/reference/common/TemplateParser.js
+++ binaries/data/mods/public/gui/reference/common/TemplateParser.js
@@ -192,8 +192,8 @@
else if (technologyName in this.techs[civCode])
return this.techs[civCode][technologyName];
- let template = this.TemplateLoader.loadTechnologyTemplate(technologyName);
- const tech = GetTechnologyDataHelper(template, civCode, g_ResourceData, this.modifiers[civCode] || {});
+ let template = this.TemplateLoader.loadTechnologyTemplate(technologyName, civCode);
+ const tech = GetTemplateDataHelper(template, civCode, g_ResourceData, this.modifiers[civCode] || {});
tech.name.internal = technologyName;
if (template.pair !== undefined)
Index: binaries/data/mods/public/gui/session/ResearchProgress.js
===================================================================
--- binaries/data/mods/public/gui/session/ResearchProgress.js
+++ binaries/data/mods/public/gui/session/ResearchProgress.js
@@ -68,7 +68,7 @@
{
this.researcher = researchStatus.researcher;
- let template = GetTechnologyData(techName, g_Players[g_ViewedPlayer].civ);
+ const template = GetTemplateData(techName, g_ViewedPlayer);
let modifier = "stretched:";
if (researchStatus.paused)
modifier += "color:0 0 0 127:grayscale:";
Index: binaries/data/mods/public/gui/session/chat/ChatMessageFormatSimulation.js
===================================================================
--- binaries/data/mods/public/gui/session/chat/ChatMessageFormatSimulation.js
+++ binaries/data/mods/public/gui/session/chat/ChatMessageFormatSimulation.js
@@ -116,7 +116,7 @@
return {
"text": sprintf(message, {
"player": colorizePlayernameByID(msg.player),
- "phaseName": getEntityNames(GetTechnologyData(msg.phaseName, g_Players[msg.player].civ))
+ "phaseName": getEntityNames(GetTemplateData(msg.phaseName, msg.player))
})
};
}
Index: binaries/data/mods/public/gui/session/selection_details.js
===================================================================
--- binaries/data/mods/public/gui/session/selection_details.js
+++ binaries/data/mods/public/gui/session/selection_details.js
@@ -80,7 +80,10 @@
// Rank
if (entState.identity && entState.identity.rank && entState.identity.classes)
{
- const rankObj = GetTechnologyData(entState.identity.rankTechName, playerState.civ);
+ const rankObj = Engine.GUIInterfaceCall("GetTemplateData", {
+ "templateName": entState.identity.rankTechName,
+ "player": entState.player
+ });
Engine.GetGUIObjectByName("rankIcon").tooltip = sprintf(translate("%(rank)s Rank"), {
"rank": translateWithContext("Rank", entState.identity.rank)
}) + (rankObj ? "\n" + rankObj.tooltip : "");
Index: binaries/data/mods/public/gui/session/selection_panels.js
===================================================================
--- binaries/data/mods/public/gui/session/selection_panels.js
+++ binaries/data/mods/public/gui/session/selection_panels.js
@@ -545,7 +545,7 @@
if (queuedItem.unitTemplate)
template = GetTemplateData(queuedItem.unitTemplate);
else if (queuedItem.technologyTemplate)
- template = GetTechnologyData(queuedItem.technologyTemplate, GetSimState().players[data.player].civ);
+ template = GetTemplateData(queuedItem.technologyTemplate);
else
{
warning("Unknown production queue template " + uneval(queuedItem));
@@ -712,10 +712,10 @@
// Handle one or two techs (tech pair)
let player = data.player;
let playerState = GetSimState().players[player];
- for (let tech of data.item.tech.pair ? [data.item.tech.bottom, data.item.tech.top] : [data.item.tech])
+ for (let tech of data.item.tech.Choice ? data.item.tech.Choice.split(" ") : [data.item.tech])
{
- // Don't change the object returned by GetTechnologyData
- let template = clone(GetTechnologyData(tech, playerState.civ));
+ // Don't change the object returned by GetTemplateData
+ let template = clone(GetTemplateData(tech));
if (!template)
return false;
@@ -737,8 +737,8 @@
"player": player
});
- let requirementsPassed = Engine.GuiInterfaceCall("CheckTechnologyRequirements", {
- "tech": tech,
+ const requirementsPassed = Engine.GuiInterfaceCall("AreRequirementsMet", {
+ "requirements": template.requirements,
"player": player
});
Index: binaries/data/mods/public/gui/session/session.js
===================================================================
--- binaries/data/mods/public/gui/session/session.js
+++ binaries/data/mods/public/gui/session/session.js
@@ -221,30 +221,12 @@
if (!(templateName in g_TemplateData))
{
let template = Engine.GuiInterfaceCall("GetTemplateData", { "templateName": templateName, "player": player });
- translateObjectKeys(template, ["specific", "generic", "tooltip"]);
+ translateObjectKeys(template, ["specific", "generic", "tooltip", "history"]);
g_TemplateData[templateName] = deepfreeze(template);
}
return g_TemplateData[templateName];
}
-function GetTechnologyData(technologyName, civ)
-{
- if (!g_TechnologyData[civ])
- g_TechnologyData[civ] = {};
-
- if (!(technologyName in g_TechnologyData[civ]))
- {
- const tech = TechnologyTemplates.Get(technologyName);
- if (!tech)
- return;
- let template = GetTechnologyDataHelper(tech, civ, g_ResourceData);
- translateObjectKeys(template, ["specific", "generic", "description", "tooltip", "requirementsTooltip"]);
- g_TechnologyData[civ][technologyName] = deepfreeze(template);
- }
-
- return g_TechnologyData[civ][technologyName];
-}
-
function init(initData, hotloadData)
{
if (!g_Settings)
Index: binaries/data/mods/public/simulation/components/GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/GuiInterface.js
+++ binaries/data/mods/public/simulation/components/GuiInterface.js
@@ -669,18 +669,6 @@
};
/**
- * Checks whether the requirements for this technology have been met.
- */
-GuiInterface.prototype.CheckTechnologyRequirements = function(player, data)
-{
- let cmpTechnologyManager = QueryPlayerIDInterface(data.player !== undefined ? data.player : player, IID_TechnologyManager);
- if (!cmpTechnologyManager)
- return false;
-
- return cmpTechnologyManager.CanResearch(data.tech);
-};
-
-/**
* Returns technologies that are being actively researched, along with
* which entity is researching them and how far along the research is.
*/
Index: binaries/data/mods/public/simulation/components/Researcher.js
===================================================================
--- binaries/data/mods/public/simulation/components/Researcher.js
+++ binaries/data/mods/public/simulation/components/Researcher.js
@@ -199,36 +199,26 @@
let techs = string.split(/\s+/);
// Replace the civ specific technologies.
- const civ = Engine.QueryInterface(playerEnt, IID_Identity).GetCiv();
+ const playerCiv = Engine.QueryInterface(playerEnt, IID_Identity).GetCiv();
+ const nativeCiv = Engine.QueryInterface(this.entity, IID_Identity).GetCiv();
for (let i = 0; i < techs.length; ++i)
- {
- const tech = techs[i];
- if (tech.indexOf("{civ}") == -1)
- continue;
- const civTech = tech.replace("{civ}", civ);
- techs[i] = TechnologyTemplates.Has(civTech) ? civTech : tech.replace("{civ}", "generic");
- }
-
- // Remove any technologies that can't be researched by this civ.
- techs = techs.filter(tech =>
- cmpTechnologyManager.CheckTechnologyRequirements(
- DeriveTechnologyRequirements(TechnologyTemplates.Get(tech), civ),
- true));
+ techs[i] = tech.replace("{native}", nativeCiv).replace("{civ}", playerCiv);
const techList = [];
const superseded = {};
const disabledTechnologies = cmpPlayer.GetDisabledTechnologies();
+ const cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
// Add any top level technologies to an array which corresponds to the displayed icons.
// Also store what technology is superseded in the superseded object { "tech1":"techWhichSupercedesTech1", ... }.
for (const tech of techs)
{
- if (disabledTechnologies && disabledTechnologies[tech])
+ if (!cmpTemplateManager.TemplateExists(tech) || disabledTechnologies && disabledTechnologies[tech])
continue;
- const template = TechnologyTemplates.Get(tech);
- if (!template.supersedes || techs.indexOf(template.supersedes) === -1)
+ const template = GetTemplateDataHelper(cmpTemplateManager.GetTemplate(tech)).technology;
+ if (!template.supersedes || !techs.includes(template.supersedes))
techList.push(tech);
else
superseded[template.supersedes] = tech;
@@ -256,7 +246,7 @@
continue;
}
- const template = TechnologyTemplates.Get(tech);
+ const template = cmpTemplateManager.GetTemplate(tech);
if (template.top)
ret[i] = { "pair": true, "top": template.top, "bottom": template.bottom };
else
@@ -293,7 +283,7 @@
if (!cmpTechnologyManager)
return false;
- const template = TechnologyTemplates.Get(tech);
+ const template = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager).GetTemplate(tech);
if (template.top)
return cmpTechnologyManager.IsTechnologyResearched(template.top) ||
cmpTechnologyManager.IsInProgress(template.top) ||
Index: binaries/data/mods/public/simulation/components/Technology.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/simulation/components/Technology.js
@@ -0,0 +1,28 @@
+function Technology() {}
+
+Technology.prototype.Schema =
+ "Specifies the effects of a technology." +
+ "" +
+ "phase_village" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ ModificationsSchema +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
Index: binaries/data/mods/public/simulation/components/TechnologyManager.js
===================================================================
--- binaries/data/mods/public/simulation/components/TechnologyManager.js
+++ binaries/data/mods/public/simulation/components/TechnologyManager.js
@@ -23,14 +23,14 @@
*/
TechnologyManager.prototype.Technology.prototype.Queue = function(techCostMultiplier)
{
- const template = TechnologyTemplates.Get(this.templateName);
+ const template = GetTemplateDataHelper(Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager).GetTemplate(this.templateName));
if (!template)
return false;
this.resources = {};
- if (template.cost)
- for (const res in template.cost)
- this.resources[res] = Math.floor(techCostMultiplier[res] * template.cost[res]);
+ if (template.cost?.resources)
+ for (const res in template.cost.resources)
+ this.resources[res] = Math.floor(techCostMultiplier[res] * template.cost.resources[res]);
// ToDo: Subtract resources here or in cmpResearcher?
const cmpPlayer = Engine.QueryInterface(this.player, IID_Player);
@@ -38,7 +38,7 @@
if (!cmpPlayer?.TrySubtractResources(this.resources))
return false;
- const time = techCostMultiplier.time * (template.researchTime || 0) * 1000;
+ const time = techCostMultiplier.time * (template.cost.time || 0) * 1000;
this.timeRemaining = time;
this.timeTotal = time;
@@ -89,9 +89,9 @@
{
this.finished = true;
- const template = TechnologyTemplates.Get(this.templateName);
- if (template.soundComplete)
- Engine.QueryInterface(SYSTEM_ENTITY, IID_SoundManager)?.PlaySoundGroup(template.soundComplete, this.researcher);
+ const template = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager).GetTemplate(this.templateName);
+ if (template.Sound?.completed)
+ Engine.QueryInterface(SYSTEM_ENTITY, IID_SoundManager)?.PlaySoundGroup(template.Sound.completed, this.researcher);
if (template.modifications)
{
@@ -207,10 +207,15 @@
// Some technologies are automatically researched when their conditions are met. They have no cost and are
// researched instantly. This allows civ bonuses and more complicated technologies.
this.unresearchedAutoResearchTechs = new Set();
- let allTechs = TechnologyTemplates.GetAll();
- for (let key in allTechs)
- if (allTechs[key].autoResearch || allTechs[key].top)
+
+ const cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
+ const allTemplates = cmpTemplateManager.FindAllTemplates(false);
+ for (const key in allTemplates)
+ {
+ const template = cmpTemplateManager.GetTemplate(key);
+ if (template.Technology && (template.Technology.AutoResearched || template.Technology.Choice))
this.unresearchedAutoResearchTechs.add(key);
+ }
};
TechnologyManager.prototype.SerializableAttributes = [
@@ -259,9 +264,9 @@
{
for (let key of this.unresearchedAutoResearchTechs)
{
- let tech = TechnologyTemplates.Get(key);
- if ((tech.autoResearch && this.CanResearch(key)) ||
- (tech.top && (this.IsTechnologyResearched(tech.top) || this.IsTechnologyResearched(tech.bottom))))
+ let tech = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager).GetTemplate(key).Technology;
+ if (tech.AutoResearched && this.CanResearch(key) ||
+ tech.Choice?._string.split(" ").some(choiceTech => this.IsTechnologyResearched(choiceTech)))
{
this.unresearchedAutoResearchTechs.delete(key);
this.ResearchTechnology(key);
Index: binaries/data/mods/public/simulation/components/tests/test_Technology.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/simulation/components/tests/test_Technology.js
@@ -0,0 +1 @@
+Engine.LoadComponentScript("Technology.js");
Index: binaries/data/mods/public/simulation/helpers/Cheat.js
===================================================================
--- binaries/data/mods/public/simulation/helpers/Cheat.js
+++ binaries/data/mods/public/simulation/helpers/Cheat.js
@@ -109,22 +109,20 @@
if (!cmpTechnologyManager)
return;
- // store the phase we want in the next input parameter
- let parameter;
- if (!cmpTechnologyManager.IsTechnologyResearched("phase_town"))
- parameter = "phase_town";
- else if (!cmpTechnologyManager.IsTechnologyResearched("phase_city"))
- parameter = "phase_city";
- else
- return;
+ const phases = [ "village", "town", "city" ];
- const civ = Engine.QueryInterface(playerEnt, IID_Identity).GetCiv();
- parameter += TechnologyTemplates.Has(parameter + "_" + civ) ? "_" + civ : "_generic";
+ let technologyName = "technologies/{civ}/phase_";
+ for (const phase of phases)
+ if (!cmpTechnologyManager.IsTechnologyResearched(technologyName + phase))
+ {
+ technologyName += phase;
+ break;
+ }
Cheat({
"player": input.player,
"action": "researchTechnology",
- "parameter": parameter,
+ "parameter": technologyName,
"selected": input.selected
});
return;
@@ -173,7 +171,7 @@
}
}
- if (TechnologyTemplates.Has(techname))
+ if (Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager).TemplateExists(techname))
cmpTechnologyManager.ResearchTechnology(techname);
return;
}