Route faction job boards to their own description pools
This commit is contained in:
parent
57024084f4
commit
cb7033861f
|
|
@ -1734,6 +1734,43 @@ export function parseSideQuestId(id) {
|
||||||
return { systemId: m[1], worldKey: m[2].toLowerCase(), category: cat, slot: Math.floor(Number(m[4])) };
|
return { systemId: m[1], worldKey: m[2].toLowerCase(), category: cat, slot: Math.floor(Number(m[4])) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The COPY POOL a posting draws from (data/sidequests.json → descriptions).
|
||||||
|
*
|
||||||
|
* THREE-DEEP FALLBACK, fixed order (a board always reads something):
|
||||||
|
* 1. descriptions.faction.<factionId>.<category> — the FACTION'S OWN voice
|
||||||
|
* (apex / mindweave / zenith). Each of the nine pools is written in that
|
||||||
|
* faction's doctrine and names the rival it will actually fight through
|
||||||
|
* the {enemy} placeholder (the posting's seeded enemyFaction).
|
||||||
|
* 2. descriptions.faction.<category> — the shared war-voice pool: the
|
||||||
|
* documented fallback for a faction with no pool of its own (a new
|
||||||
|
* power, or a hand-edited data file).
|
||||||
|
* 3. descriptions.neutral.<category> — the neutral voice, last resort.
|
||||||
|
*
|
||||||
|
* A pool that stands but is not an array (a typo in the data) falls through
|
||||||
|
* to the next link rather than posting nothing. Pure in (context, category,
|
||||||
|
* faction): no RNG, so it never disturbs the posting's seeded draw.
|
||||||
|
*
|
||||||
|
* @param {object} ctx postingContext() shape ({ context: 'neutral'|'faction', … })
|
||||||
|
* @param {string} cat the category id
|
||||||
|
* @param {string|null} [factionId] the board's faction id (a faction board)
|
||||||
|
* @returns {object[]} the variant pool ([] = no copy at all)
|
||||||
|
*/
|
||||||
|
function descriptionPool(ctx, cat, factionId = null) {
|
||||||
|
const fallbacks = [];
|
||||||
|
const own = String(factionId ?? '').trim();
|
||||||
|
if (ctx?.context === 'faction' && own !== '') {
|
||||||
|
fallbacks.push(`sidequests.descriptions.faction.${own}.${cat}`);
|
||||||
|
}
|
||||||
|
fallbacks.push(`sidequests.descriptions.faction.${cat}`);
|
||||||
|
fallbacks.push(`sidequests.descriptions.neutral.${cat}`);
|
||||||
|
for (const path of fallbacks) {
|
||||||
|
const pool = config.get(path, null);
|
||||||
|
if (Array.isArray(pool)) return pool;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
/** One posting from its pool variant + reward roll (null on a bad pool entry). */
|
/** One posting from its pool variant + reward roll (null on a bad pool entry). */
|
||||||
function buildPosting(seed, rec, ctx, cat, slot, r, galaxy = null, usedDossier = null, world = 'p1') {
|
function buildPosting(seed, rec, ctx, cat, slot, r, galaxy = null, usedDossier = null, world = 'p1') {
|
||||||
const meta = sideQuestCategoryMeta(cat);
|
const meta = sideQuestCategoryMeta(cat);
|
||||||
|
|
@ -1772,10 +1809,11 @@ function buildPosting(seed, rec, ctx, cat, slot, r, galaxy = null, usedDossier =
|
||||||
if (!escortDestinationFor(seed, postingId, rec.id, galaxy)) return null;
|
if (!escortDestinationFor(seed, postingId, rec.id, galaxy)) return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const poolPath = `sidequests.descriptions.${ctx.context}.${cat}`;
|
// The copy pool: this faction's own pool when it has one (the three-deep
|
||||||
let pool = config.get(poolPath, null);
|
// fallback above), so an Apex board reads Apex and a Zenith board reads
|
||||||
if (!Array.isArray(pool)) pool = config.get(`sidequests.descriptions.neutral.${cat}`, null); // the neutral voice as fallback
|
// Zenith. The draw rides the posting's own seeded stream, exactly as the
|
||||||
pool = Array.isArray(pool) ? pool : [];
|
// shared pool did — same seed, same slot, same variant index.
|
||||||
|
const pool = descriptionPool(ctx, cat, factionCtx ? rec.faction : null);
|
||||||
let v = pool.length > 0 ? pool[r.int(0, pool.length - 1)] : null;
|
let v = pool.length > 0 ? pool[r.int(0, pool.length - 1)] : null;
|
||||||
// A WANTED LIST never posts the same leader twice on one board: the seeded
|
// A WANTED LIST never posts the same leader twice on one board: the seeded
|
||||||
// draw stands when it is fresh, otherwise the next entry forward (wrapping)
|
// draw stands when it is fresh, otherwise the next entry forward (wrapping)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue