diff --git a/binaries/data/mods/public/gui/structree/helper.js b/binaries/data/mods/public/gui/structree/helper.js
index eef5c6c..8eb8bd3 100644
a
|
b
|
function GetTemplateData(templateName)
|
107 | 107 | var template = loadTemplate(templateName); |
108 | 108 | return GetTemplateDataHelper(template, null, g_AuraData); |
109 | 109 | } |
| 110 | |
| 111 | /** |
| 112 | * Determines and returns the phase of a given technology. Works |
| 113 | * recursively through the given tech's pre-requisite and superseded |
| 114 | * techs if necessary. |
| 115 | * |
| 116 | * @param techName the Technology's name |
| 117 | * @return The name of the phase the technology belongs to, or false if |
| 118 | * the current civ can't research this tech |
| 119 | */ |
| 120 | function GetPhaseOfTechnology(techName) |
| 121 | { |
| 122 | let phaseIdx = -1; |
| 123 | let techReqs = []; |
| 124 | |
| 125 | if (depath(techName).slice(0, 5) === "phase") |
| 126 | { |
| 127 | phaseIdx = g_ParsedData.phaseList.indexOf(g_ParsedData.phases[techName].actualPhase); |
| 128 | if (phaseIdx > 0) |
| 129 | return g_ParsedData.phaseList[phaseIdx - 1]; |
| 130 | } |
| 131 | else if (g_SelectedCiv in g_ParsedData.techs[techName].reqs) |
| 132 | { |
| 133 | if (g_ParsedData.techs[techName].reqs[g_SelectedCiv] === false) |
| 134 | return false; |
| 135 | techReqs = g_ParsedData.techs[techName].reqs[g_SelectedCiv]; |
| 136 | } |
| 137 | else if ("generic" in g_ParsedData.techs[techName].reqs) |
| 138 | techReqs = g_ParsedData.techs[techName].reqs.generic; |
| 139 | |
| 140 | for (let req of techReqs) |
| 141 | if (depath(req).slice(0, 5) === "phase") |
| 142 | return req; |
| 143 | else |
| 144 | { |
| 145 | let newIdx = g_ParsedData.phaseList.indexOf(GetPhaseOfTechnology(req)); |
| 146 | if (newIdx > phaseIdx) |
| 147 | phaseIdx = newIdx; |
| 148 | } |
| 149 | |
| 150 | return g_ParsedData.phaseList[phaseIdx] || false; |
| 151 | |
| 152 | } |
diff --git a/binaries/data/mods/public/gui/structree/load.js b/binaries/data/mods/public/gui/structree/load.js
index dee89d2..6846804 100644
a
|
b
|
function loadTechnology(techName)
|
197 | 197 | |
198 | 198 | if (template.requirements !== undefined) |
199 | 199 | { |
200 | | for (let op in template.requirements) |
201 | | { |
202 | | let val = template.requirements[op]; |
203 | | let req = calcReqs(op, val); |
204 | | |
205 | | switch (op) |
206 | | { |
207 | | case "tech": |
208 | | tech.reqs.generic = req; |
209 | | break; |
210 | | |
211 | | case "civ": |
212 | | tech.reqs[req] = []; |
213 | | break; |
214 | | |
215 | | case "any": |
216 | | if (req[0].length > 0) |
217 | | for (let r of req[0]) |
218 | | { |
219 | | let v = req[0][r]; |
220 | | if (typeof r == "number") |
221 | | tech.reqs[v] = []; |
222 | | else |
223 | | tech.reqs[r] = v; |
224 | | } |
225 | | if (req[1].length > 0) |
226 | | tech.reqs.generic = req[1]; |
227 | | break; |
228 | | |
229 | | case "all": |
230 | | if (!req[0].length) |
231 | | tech.reqs.generic = req[1]; |
232 | | else |
233 | | for (let r of req[0]) |
234 | | tech.reqs[r] = req[1]; |
235 | | break; |
236 | | } |
237 | | } |
| 200 | let op = Object.keys(template.requirements)[0]; |
| 201 | let val = template.requirements[op]; |
| 202 | tech.reqs = calcReqs(op, val); |
238 | 203 | } |
239 | 204 | |
240 | 205 | if (template.supersedes !== undefined) |
241 | 206 | { |
242 | 207 | if (tech.reqs.generic !== undefined) |
243 | 208 | tech.reqs.generic.push(template.supersedes); |
| 209 | else if (!Object.keys(tech.reqs).length) |
| 210 | tech.reqs.generic = [template.supersedes]; |
244 | 211 | else |
245 | 212 | for (let ck of Object.keys(tech.reqs)) |
246 | 213 | tech.reqs[ck].push(template.supersedes); |
… |
… |
function loadTechnologyPair(pairCode)
|
275 | 242 | * Calculate the prerequisite requirements of a technology. |
276 | 243 | * Works recursively if needed. |
277 | 244 | * |
278 | | * @param op The base operation. Can be "civ", "tech", "all" or "any". |
279 | | * @param val The value associated with the above operation. |
| 245 | * @param operator The base operation. Can be "civ", "notciv", "tech", "all" or "any". |
| 246 | * @param value The value associated with the above operation. |
280 | 247 | * |
281 | | * @return Sorted requirments. |
| 248 | * @return Object containing the requirements, sorted. |
282 | 249 | */ |
283 | | function calcReqs(op, val) |
| 250 | function calcReqs(operator, value) |
284 | 251 | { |
285 | | switch (op) |
| 252 | let retVal = {}; |
| 253 | |
| 254 | switch (operator) |
286 | 255 | { |
287 | 256 | case "civ": |
288 | | case "class": |
| 257 | retVal[value] = []; |
| 258 | break; |
| 259 | |
289 | 260 | case "notciv": |
| 261 | retVal[value] = false; |
| 262 | break; |
| 263 | |
| 264 | case "class": |
290 | 265 | case "number": |
291 | | // nothing needs doing |
| 266 | // do nothing |
292 | 267 | break; |
293 | 268 | |
294 | 269 | case "tech": |
295 | | if (depath(val).slice(0,4) === "pair") |
296 | | return loadTechnologyPair(val).techs; |
297 | | return [ val ]; |
| 270 | if (depath(value).slice(0,4) === "pair") |
| 271 | return { "generic": loadTechnologyPair(value).techs }; |
| 272 | return { "generic": [ value ] }; |
298 | 273 | |
299 | 274 | case "all": |
300 | | case "any": |
301 | | let t = []; |
302 | | let c = []; |
303 | | for (let nv of val) |
304 | | { |
305 | | for (let o in nv) |
| 275 | let civs = []; |
| 276 | let techs = []; |
| 277 | for (let subvalue of value) |
| 278 | for (let newOper in subvalue) |
306 | 279 | { |
307 | | let v = nv[o]; |
308 | | let r = calcReqs(o, v); |
309 | | switch (o) |
| 280 | let newValue = subvalue[newOper]; |
| 281 | let result = calcReqs(newOper, newValue) |
| 282 | |
| 283 | switch (newOper) |
310 | 284 | { |
311 | 285 | case "civ": |
| 286 | civs.push(Object.keys(result)[0]); |
| 287 | break; |
| 288 | |
312 | 289 | case "notciv": |
313 | | c.push(r); |
| 290 | retVal[Object.keys(result)[0]] = false; |
314 | 291 | break; |
315 | 292 | |
316 | 293 | case "tech": |
317 | | t = t.concat(r); |
| 294 | techs = techs.concat(result.generic); |
318 | 295 | break; |
319 | 296 | |
320 | 297 | case "any": |
321 | | c = c.concat(r[0]); |
322 | | t = t.concat(r[1]); |
| 298 | case "all": |
| 299 | if (result.generic) |
| 300 | techs = techs.concat(result.generic); |
| 301 | else |
| 302 | for (let c of Object.keys(result)) |
| 303 | if (result[c] === false) |
| 304 | retVal[c] = false; |
| 305 | else if (newOper === "any") |
| 306 | civs.push(c); |
| 307 | else |
| 308 | warn("Uncomprehensible technology requirements - "+operator +":"+uneval(value)); |
| 309 | break; |
| 310 | } |
| 311 | } |
| 312 | if (!civs.length && techs.length > 0) |
| 313 | retVal.generic = techs; |
| 314 | else |
| 315 | for (let c of civs) |
| 316 | retVal[c] = techs; |
| 317 | break; |
| 318 | |
| 319 | case "any": |
| 320 | for (let subvalue of value) |
| 321 | for (let newOper in subvalue) |
| 322 | { |
| 323 | let newValue = subvalue[newOper]; |
| 324 | let result = calcReqs(newOper, newValue) |
| 325 | |
| 326 | switch (newOper) |
| 327 | { |
| 328 | case "civ": |
| 329 | retVal[Object.keys(result)[0]] = []; |
| 330 | break; |
| 331 | |
| 332 | case "notciv": |
| 333 | retVal[Object.keys(result)[0]] = false; |
| 334 | break; |
| 335 | |
| 336 | case "tech": |
| 337 | if (!retVal.generic) |
| 338 | retVal.generic = []; |
| 339 | retVal.generic.push(result.generic); |
323 | 340 | break; |
324 | 341 | |
325 | 342 | case "all": |
326 | | for (let ci in r[0]) |
327 | | c[ci] = r[1]; |
328 | | t = t; |
| 343 | for (let c of Object.keys(result)) |
| 344 | retVal[c] = result[c]; |
| 345 | break; |
| 346 | |
| 347 | case "any": |
| 348 | for (let civ of Object.keys(result)) |
| 349 | { |
| 350 | if (!retVal[civ]) |
| 351 | { |
| 352 | warn("Possible any/all req operator problem - "+operator +":"+uneval(value)); |
| 353 | retVal[civ] = []; |
| 354 | } |
| 355 | for (let v of result[civ]) |
| 356 | retVal.generic.push(v); |
| 357 | } |
| 358 | break; |
329 | 359 | } |
330 | 360 | } |
331 | | } |
332 | | return [ c, t ]; |
| 361 | break; |
333 | 362 | |
334 | 363 | default: |
335 | | warn("Unknown reqs operator: "+op); |
| 364 | warn("Unknown requirement operator: "+operator); |
336 | 365 | } |
337 | | return val; |
| 366 | return retVal; |
338 | 367 | } |
339 | 368 | |
340 | 369 | /** |
… |
… |
function unravelPhases(techs)
|
373 | 402 | let reqPhasePos = phaseList.indexOf(reqPhase); |
374 | 403 | let myPhasePos = phaseList.indexOf(myPhase); |
375 | 404 | |
376 | | if (phaseList.length === 0) |
| 405 | if (!phaseList.length) |
377 | 406 | phaseList = [reqPhase, myPhase]; |
378 | 407 | else if (reqPhasePos < 0 && myPhasePos > -1) |
379 | 408 | phaseList.splice(myPhasePos, 0, reqPhase); |
diff --git a/binaries/data/mods/public/gui/structree/structree.js b/binaries/data/mods/public/gui/structree/structree.js
index 65bfd9e..1415022 100644
a
|
b
|
function selectCiv(civCode)
|
188 | 188 | let newProdTech = {}; |
189 | 189 | for (let prod of structInfo.production.technology) |
190 | 190 | { |
191 | | let phase = ""; |
| 191 | let phase = GetPhaseOfTechnology(prod); |
192 | 192 | |
193 | | if (depath(prod).slice(0,5) === "phase") |
194 | | { |
195 | | phase = g_ParsedData.phaseList.indexOf(g_ParsedData.phases[prod].actualPhase); |
196 | | if (phase > 0) |
197 | | phase = g_ParsedData.phaseList[phase - 1]; |
198 | | } |
199 | | else if (g_SelectedCiv in g_ParsedData.techs[prod].reqs) |
200 | | { |
201 | | for (let req of g_ParsedData.techs[prod].reqs[g_SelectedCiv]) |
202 | | if (depath(req).slice(0,5) === "phase") |
203 | | phase = req; |
204 | | } |
205 | | else if ("generic" in g_ParsedData.techs[prod].reqs) |
206 | | { |
207 | | for (let req of g_ParsedData.techs[prod].reqs.generic) |
208 | | if (depath(req).slice(0,5) === "phase") |
209 | | phase = req; |
210 | | } |
| 193 | if (phase === false) |
| 194 | continue; |
211 | 195 | |
212 | | if (depath(phase).slice(0,5) !== "phase" || |
213 | | g_ParsedData.phaseList.indexOf(phase) < structPhaseIdx) |
| 196 | if (g_ParsedData.phaseList.indexOf(phase) < structPhaseIdx) |
214 | 197 | { |
215 | 198 | if (structInfo.phase !== false) |
216 | 199 | phase = structInfo.phase; |
… |
… |
function selectCiv(civCode)
|
243 | 226 | } |
244 | 227 | else if (unit.required !== undefined) |
245 | 228 | { |
246 | | if (g_ParsedData.phases[unit.required]) |
247 | | phase = g_ParsedData.phases[unit.required].actualPhase; |
248 | | else if (g_ParsedData.techs[unit.required]) |
249 | | { |
250 | | let reqs = g_ParsedData.techs[unit.required].reqs; |
251 | | if (reqs[g_SelectedCiv]) |
252 | | phase = reqs[g_SelectedCiv][0]; |
253 | | else if (reqs.generic) |
254 | | phase = reqs.generic[0]; |
255 | | else |
256 | | warn("Empty requirements found on technology " + unit.required); |
257 | | } |
258 | | else |
259 | | warn("Technology " + unit.required + " for " + prod + " not found."); |
| 229 | phase = GetPhaseOfTechnology(unit.required); |
| 230 | if (phase === false) |
| 231 | continue; |
260 | 232 | } |
261 | 233 | |
262 | 234 | if (depath(phase).slice(0,5) !== "phase" || g_ParsedData.phaseList.indexOf(phase) < structPhaseIdx) |