mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
Define technology pairs in an array
This patch renames the "pair" property of paired technologies to "partOfPair" for clarity and in the pair parent packs the two techs (previously "top" and "bottom") into an array called "pair". This makes the hierarchy more clear in the code and pairs might not be always placed vertically in the future.
This commit is contained in:
parent
3922a7ee0a
commit
107a49caf1
23 changed files with 51 additions and 83 deletions
|
|
@ -132,7 +132,7 @@ class TemplateLoader
|
|||
{
|
||||
const template = this.loadTechnologyTemplate(templateName);
|
||||
return {
|
||||
"techs": [template.top, template.bottom],
|
||||
"techs": template.pair,
|
||||
"reqs": DeriveTechnologyRequirements(template, civCode)
|
||||
};
|
||||
}
|
||||
|
|
@ -308,7 +308,7 @@ class TemplateLoader
|
|||
|
||||
isPairTech(technologyCode)
|
||||
{
|
||||
return !!this.loadTechnologyTemplate(technologyCode).top;
|
||||
return !!this.loadTechnologyTemplate(technologyCode).pair;
|
||||
}
|
||||
|
||||
isPhaseTech(technologyCode)
|
||||
|
|
|
|||
|
|
@ -196,10 +196,10 @@ class TemplateParser
|
|||
const tech = GetTechnologyDataHelper(template, civCode, g_ResourceData, this.modifiers[civCode] || {});
|
||||
tech.name.internal = technologyName;
|
||||
|
||||
if (template.pair !== undefined)
|
||||
if (template.partOfPair !== undefined)
|
||||
{
|
||||
tech.pair = template.pair;
|
||||
tech.reqs = this.mergeRequirements(tech.reqs, this.TemplateLoader.loadTechnologyPairTemplate(template.pair).reqs);
|
||||
tech.partOfPair = template.partOfPair;
|
||||
tech.reqs = this.mergeRequirements(tech.reqs, this.TemplateLoader.loadTechnologyPairTemplate(template.partOfPair).reqs);
|
||||
}
|
||||
|
||||
if (this.TemplateLoader.isPhaseTech(technologyName))
|
||||
|
|
|
|||
|
|
@ -684,8 +684,8 @@ g_SelectionPanels.Research = {
|
|||
(item.tech == tech ||
|
||||
item.tech.pair &&
|
||||
tech.pair &&
|
||||
item.tech.bottom == tech.bottom &&
|
||||
item.tech.top == tech.top) &&
|
||||
item.tech.pair?.[0] == tech.pair?.[0] &&
|
||||
item.tech.pair?.[1] == tech.pair?.[1]) &&
|
||||
Object.keys(item.techCostMultiplier).every(
|
||||
k => item.techCostMultiplier[k] == state.researcher.techCostMultiplier[k])
|
||||
));
|
||||
|
|
@ -731,7 +731,7 @@ g_SelectionPanels.Research = {
|
|||
// Handle one or two techs (tech pair)
|
||||
const player = data.player;
|
||||
const playerState = GetSimState().players[player];
|
||||
for (const tech of data.item.tech.pair ? [data.item.tech.bottom, data.item.tech.top] : [data.item.tech])
|
||||
for (const tech of (data.item.tech.pair || [data.item.tech]))
|
||||
{
|
||||
// Don't change the object returned by GetTechnologyData
|
||||
const template = clone(GetTechnologyData(tech, playerState.civ));
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ GameState.prototype.init = function(SharedScript, state, player)
|
|||
{
|
||||
// Cannot call pickrandom because this function is called on rejoin and that causes oos.
|
||||
// (reverting rP20750)
|
||||
techName = this.playerData.disabledTechnologies[techData._template.bottom] ?
|
||||
techData._template.top : techData._template.bottom;
|
||||
techName = this.playerData.disabledTechnologies[techData._template.pair[0]] ?
|
||||
techData._template.pair[1] : techData._template.pair[0];
|
||||
|
||||
const supersedes = techData._template.supersedes;
|
||||
techData = clone(this.getTemplate(techName));
|
||||
|
|
|
|||
|
|
@ -7,15 +7,14 @@ export function Technology(templateName)
|
|||
const template = TechnologyTemplates.Get(templateName);
|
||||
|
||||
// check if this is one of two paired technologies.
|
||||
this._isPair = template.pair !== undefined;
|
||||
if (this._isPair)
|
||||
if (template.partOfPair)
|
||||
{
|
||||
const pairTech = TechnologyTemplates.Get(template.pair);
|
||||
this._pairedWith = pairTech.top == templateName ? pairTech.bottom : pairTech.top;
|
||||
const parentTech = TechnologyTemplates.Get(template.partOfPair);
|
||||
this._pairedWith = parentTech.pair[0] == templateName ? parentTech.pair[1] : parentTech.pair[0];
|
||||
}
|
||||
|
||||
// check if it only defines a pair:
|
||||
this._definesPair = template.top !== undefined;
|
||||
this._definesPair = !!template.pair;
|
||||
this._template = template;
|
||||
}
|
||||
|
||||
|
|
@ -41,22 +40,17 @@ Technology.prototype.getPairedTechs = function()
|
|||
if (!this._definesPair)
|
||||
return undefined;
|
||||
|
||||
return [
|
||||
new Technology(this._template.top),
|
||||
new Technology(this._template.bottom)
|
||||
];
|
||||
return this._template.pair.map(name => new Technology(name));
|
||||
};
|
||||
|
||||
Technology.prototype.pair = function()
|
||||
{
|
||||
if (!this._isPair)
|
||||
return undefined;
|
||||
return this._template.pair;
|
||||
return this._template.partOfPair;
|
||||
};
|
||||
|
||||
Technology.prototype.pairedWith = function()
|
||||
{
|
||||
if (!this._isPair)
|
||||
if (!this._template.partOfPair)
|
||||
return undefined;
|
||||
return this._pairedWith;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -234,36 +234,22 @@ Researcher.prototype.GetTechnologiesList = function()
|
|||
superseded[template.supersedes] = tech;
|
||||
}
|
||||
|
||||
// Now make researched/in progress techs invisible.
|
||||
for (const i in techList)
|
||||
return techList.map(tech =>
|
||||
{
|
||||
let tech = techList[i];
|
||||
while (this.IsTechnologyResearchedOrInProgress(tech))
|
||||
tech = superseded[tech];
|
||||
// Make researched/in progress techs invisible.
|
||||
while (tech && this.IsTechnologyResearchedOrInProgress(tech))
|
||||
tech = superseded[tech]; // might be undefined
|
||||
|
||||
techList[i] = tech;
|
||||
}
|
||||
|
||||
const ret = [];
|
||||
|
||||
// This inserts the techs into the correct positions to line up the technology pairs.
|
||||
for (let i = 0; i < techList.length; ++i)
|
||||
{
|
||||
const tech = techList[i];
|
||||
if (!tech)
|
||||
{
|
||||
ret[i] = undefined;
|
||||
continue;
|
||||
}
|
||||
return undefined;
|
||||
|
||||
// "Unwrap" tech pairs
|
||||
const template = TechnologyTemplates.Get(tech);
|
||||
if (template.top)
|
||||
ret[i] = { "pair": true, "top": template.top, "bottom": template.bottom };
|
||||
else
|
||||
ret[i] = tech;
|
||||
}
|
||||
if (template?.pair)
|
||||
tech = { "pair": template.pair };
|
||||
|
||||
return ret;
|
||||
return tech;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -294,11 +280,9 @@ Researcher.prototype.IsTechnologyResearchedOrInProgress = function(tech)
|
|||
return false;
|
||||
|
||||
const template = TechnologyTemplates.Get(tech);
|
||||
if (template.top)
|
||||
return cmpTechnologyManager.IsTechnologyResearched(template.top) ||
|
||||
cmpTechnologyManager.IsInProgress(template.top) ||
|
||||
cmpTechnologyManager.IsTechnologyResearched(template.bottom) ||
|
||||
cmpTechnologyManager.IsInProgress(template.bottom);
|
||||
if (template.pair)
|
||||
return template.pair.some(t => cmpTechnologyManager.IsTechnologyResearched(t) ||
|
||||
cmpTechnologyManager.IsInProgress(t));
|
||||
|
||||
return cmpTechnologyManager.IsTechnologyResearched(tech) || cmpTechnologyManager.IsInProgress(tech);
|
||||
};
|
||||
|
|
@ -310,9 +294,7 @@ Researcher.prototype.IsTechnologyResearchedOrInProgress = function(tech)
|
|||
*/
|
||||
Researcher.prototype.QueueTechnology = function(templateName, metadata)
|
||||
{
|
||||
if (!this.GetTechnologiesList().some(tech =>
|
||||
tech && (tech == templateName ||
|
||||
tech.pair && (tech.top == templateName || tech.bottom == templateName))))
|
||||
if (!this.GetTechnologiesList().some(tech => tech === templateName || tech?.pair?.includes(templateName)))
|
||||
{
|
||||
error("This entity cannot research " + templateName + ".");
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ TechnologyManager.prototype.Init = function()
|
|||
this.unresearchedAutoResearchTechs = new Set();
|
||||
const allTechs = TechnologyTemplates.GetAll();
|
||||
for (const key in allTechs)
|
||||
if (allTechs[key].autoResearch || allTechs[key].top)
|
||||
if (allTechs[key].autoResearch || allTechs[key].pair)
|
||||
this.unresearchedAutoResearchTechs.add(key);
|
||||
};
|
||||
|
||||
|
|
@ -263,8 +263,7 @@ TechnologyManager.prototype.UpdateAutoResearch = function()
|
|||
for (const key of this.unresearchedAutoResearchTechs)
|
||||
{
|
||||
const tech = TechnologyTemplates.Get(key);
|
||||
if ((tech.autoResearch && this.CanResearch(key)) ||
|
||||
(tech.top && (this.IsTechnologyResearched(tech.top) || this.IsTechnologyResearched(tech.bottom))))
|
||||
if ((tech.autoResearch && this.CanResearch(key)) || (tech.pair?.some(t => this.IsTechnologyResearched(t))))
|
||||
{
|
||||
this.unresearchedAutoResearchTechs.delete(key);
|
||||
this.ResearchTechnology(key);
|
||||
|
|
@ -306,11 +305,10 @@ TechnologyManager.prototype.CanResearch = function(tech)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (template.top && this.IsInProgress(template.top) ||
|
||||
template.bottom && this.IsInProgress(template.bottom))
|
||||
if (template.pair?.some(t => this.IsInProgress(t)))
|
||||
return false;
|
||||
|
||||
if (template.pair && !this.CanResearch(template.pair))
|
||||
if (template.partOfPair && !this.CanResearch(template.partOfPair))
|
||||
return false;
|
||||
|
||||
if (this.IsInProgress(tech))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"pair": "pair_unlock_civil_engineering_han",
|
||||
"partOfPair": "pair_unlock_civil_engineering_han",
|
||||
"genericName": "Improved Construction",
|
||||
"specificName": { "han": "Gōngchéng" },
|
||||
"description": "",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"pair": "pair_unlock_civil_engineering_han",
|
||||
"partOfPair": "pair_unlock_civil_engineering_han",
|
||||
"genericName": "Robust Architecture",
|
||||
"specificName": { "han": "Gōngchéng" },
|
||||
"description": "",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"pair": "pair_unlock_civil_service_han",
|
||||
"partOfPair": "pair_unlock_civil_service_han",
|
||||
"genericName": "Efficient Bureaucracy",
|
||||
"specificName": { "han": "Guānliáo" },
|
||||
"description": "",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"pair": "pair_unlock_civil_service_han",
|
||||
"partOfPair": "pair_unlock_civil_service_han",
|
||||
"genericName": "Intensive Training",
|
||||
"specificName": { "han": "Guānliáo" },
|
||||
"description": "",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"pair": "pair_gather_food_maur",
|
||||
"partOfPair": "pair_gather_food_maur",
|
||||
"genericName": "Ahimsa",
|
||||
"description": "Ahimsa is the ancient Indian principle of nonviolence which applies to actions towards all living beings. It is a key virtue in Indian religions like Jainism, Buddhism, Hinduism, and Sikhism.",
|
||||
"cost": {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"pair": "pair_gather_food_maur",
|
||||
"partOfPair": "pair_gather_food_maur",
|
||||
"genericName": "Wicker Baskets",
|
||||
"description": "Equip your foragers with wicker baskets for foraging.",
|
||||
"cost": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"genericName": "Wicker Basket vs Ahimsa",
|
||||
"top": "gather_wicker_baskets_maur",
|
||||
"bottom": "gather_ahimsa",
|
||||
"pair": ["gather_wicker_baskets_maur", "gather_ahimsa"],
|
||||
"requirements": { "civ": "maur" }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"genericName": "Traditional Army vs Reform Army",
|
||||
"top": "traditional_army_sele",
|
||||
"bottom": "reformed_army_sele",
|
||||
"pair": ["traditional_army_sele", "reformed_army_sele"],
|
||||
"requirements": { "civ": "sele" }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"genericName": "Civil Engineering",
|
||||
"top": "civil_engineering_01",
|
||||
"bottom": "civil_engineering_02",
|
||||
"pair": ["civil_engineering_01", "civil_engineering_02"],
|
||||
"requirements": { "civ": "han" }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"genericName": "Civil Service",
|
||||
"top": "civil_service_01",
|
||||
"bottom": "civil_service_02",
|
||||
"pair": ["civil_service_01", "civil_service_02"],
|
||||
"requirements": { "civ": "han" }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"genericName": "Cult",
|
||||
"top": "pharaonic_cult",
|
||||
"bottom": "serapis_cult",
|
||||
"pair": ["pharaonic_cult", "serapis_cult"],
|
||||
"requirements": { "civ": "ptol" }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"pair": "pair_unlock_cult_ptol",
|
||||
"partOfPair": "pair_unlock_cult_ptol",
|
||||
"genericName": "Pharaonic Cult",
|
||||
"description": "The Pharaohs were worshipped as living gods. Their word was sacrosanct and beyond reproach, at least among the common people. The Ptolemaic dynasts certainly took advantage of this ancient custom to the fullest, to varying degrees of success.",
|
||||
"cost": {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"pair": "pair_unlock_champions_sele",
|
||||
"partOfPair": "pair_unlock_champions_sele",
|
||||
"genericName": "Reform Army",
|
||||
"description": "The Roman-style core of the Seleucid army.",
|
||||
"requirements": {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"pair": "pair_unlock_cult_ptol",
|
||||
"partOfPair": "pair_unlock_cult_ptol",
|
||||
"genericName": "Serapis Cult",
|
||||
"description": "The cult of Serapis was introduced during the 3rd century BC on the orders of Ptolemy I of Egypt as a means to unify the Greeks and Egyptians in his realm. The god was depicted as Greek in appearance, but with Egyptian trappings, and combined iconography from a great many cults, signifying both abundance and resurrection. A serapeion was any temple or religious precinct devoted to Serapis. The cult of Serapis was spread as a matter of deliberate policy by the Ptolemaic kings, who also built an immense serapeum in Alexandria.",
|
||||
"cost": {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"pair": "pair_unlock_champions_sele",
|
||||
"partOfPair": "pair_unlock_champions_sele",
|
||||
"genericName": "Traditional Army",
|
||||
"description": "The Macedonian-style core of the Seleucid army.",
|
||||
"requirements": {
|
||||
|
|
|
|||
|
|
@ -151,7 +151,6 @@ function Cheat(input)
|
|||
// try to spilt the input
|
||||
const tmp = input.parameter.split(/\s+/);
|
||||
const number = +tmp[0];
|
||||
const pair = tmp.length > 1 && (tmp[1] == "top" || tmp[1] == "bottom") ? tmp[1] : "top"; // use top as default value
|
||||
|
||||
// check, if valid number was parsed.
|
||||
if (!isNaN(number))
|
||||
|
|
@ -166,7 +165,7 @@ function Cheat(input)
|
|||
|
||||
// get name of tech
|
||||
if (tech.pair)
|
||||
techname = tech[pair];
|
||||
techname = tech.pair[tmp[1] === "1" ? 1 : 0];
|
||||
else
|
||||
techname = tech;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue