@px-lsp/server 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/data/ck3/skeletons.json +1 -0
- package/data/eu5/skeletons.json +1 -0
- package/data/vic3/skeletons.json +1 -0
- package/dist/browser-data/ck3/docs.json +1 -1
- package/dist/browser-data/ck3/tokens.json +1 -1
- package/dist/browser-data/vic3/tokens.json +1 -1
- package/dist/browser.js +50 -37
- package/dist/server.js +2000 -352
- package/dist/types/packages/server/src/features/blockSnippets.d.ts +20 -4
- package/dist/types/packages/server/src/features/completion.d.ts +11 -0
- package/dist/types/packages/server/src/features/definitionSkeletons.d.ts +24 -0
- package/dist/types/packages/server/src/games/ck3/schema.d.ts +1 -1
- package/dist/types/packages/server/src/games/eu5/index.d.ts +1 -1
- package/dist/types/packages/server/src/games/profile.d.ts +85 -1
- package/dist/types/packages/server/src/schema/skeletons.d.ts +102 -0
- package/dist/types/packages/server/src/schema/types.d.ts +30 -0
- package/package.json +3 -3
- package/src/coa/coa.ts +31 -0
- package/src/coa/coaDesigner.ts +131 -0
- package/src/coa/coaParse.ts +3 -0
- package/src/creators/definitionEdit.ts +198 -0
- package/src/creators/definitionForm.ts +479 -0
- package/src/creators/modifierFormats.ts +0 -0
- package/src/data/docsParser.ts +21 -4
- package/src/features/blockSnippets.ts +151 -20
- package/src/features/calendarDates.ts +8 -5
- package/src/features/completion.ts +38 -4
- package/src/features/definitionSkeletons.ts +109 -0
- package/src/features/inlayHints.ts +5 -2
- package/src/features/locText.ts +223 -0
- package/src/features/snippetList.ts +83 -0
- package/src/games/ck3/index.ts +16 -0
- package/src/games/ck3/meta.ts +81 -1
- package/src/games/ck3/schema.ts +83 -7
- package/src/games/ck3/structures.ts +37 -0
- package/src/games/eu5/index.ts +7 -1
- package/src/games/eu5/meta.ts +5 -1
- package/src/games/profile.ts +77 -1
- package/src/games/vic3/index.ts +4 -0
- package/src/games/vic3/meta.ts +5 -1
- package/src/gui/sourceModel.ts +51 -8
- package/src/gui/textResolve.ts +3 -3
- package/src/overview/dynastyTree.ts +493 -0
- package/src/overview/eventGraph.ts +21 -1
- package/src/overview/eventVocabulary.ts +33 -33
- package/src/overview/exampleWiki.ts +4 -1
- package/src/schema/loader.ts +2 -1
- package/src/schema/skeletons.ts +182 -0
- package/src/schema/types.ts +30 -0
- package/src/server.ts +147 -6
package/dist/server.js
CHANGED
|
@@ -1670,8 +1670,8 @@ var require_messageWriter = __commonJS({
|
|
|
1670
1670
|
get onError() {
|
|
1671
1671
|
return this.errorEmitter.event;
|
|
1672
1672
|
}
|
|
1673
|
-
fireError(error, message,
|
|
1674
|
-
this.errorEmitter.fire([this.asError(error), message,
|
|
1673
|
+
fireError(error, message, count2) {
|
|
1674
|
+
this.errorEmitter.fire([this.asError(error), message, count2]);
|
|
1675
1675
|
}
|
|
1676
1676
|
get onClose() {
|
|
1677
1677
|
return this.closeEmitter.event;
|
|
@@ -8097,12 +8097,12 @@ var require_server = __commonJS({
|
|
|
8097
8097
|
* @param message The message to add.
|
|
8098
8098
|
*/
|
|
8099
8099
|
add(message) {
|
|
8100
|
-
let
|
|
8101
|
-
if (!
|
|
8102
|
-
|
|
8100
|
+
let count2 = this._messages[message];
|
|
8101
|
+
if (!count2) {
|
|
8102
|
+
count2 = 0;
|
|
8103
8103
|
}
|
|
8104
|
-
|
|
8105
|
-
this._messages[message] =
|
|
8104
|
+
count2++;
|
|
8105
|
+
this._messages[message] = count2;
|
|
8106
8106
|
}
|
|
8107
8107
|
/**
|
|
8108
8108
|
* Send all tracked messages to the connection's window.
|
|
@@ -8852,8 +8852,8 @@ var require_files = __commonJS({
|
|
|
8852
8852
|
exports2.resolveGlobalYarnPath = resolveGlobalYarnPath;
|
|
8853
8853
|
exports2.resolveModulePath = resolveModulePath;
|
|
8854
8854
|
var url = __importStar(require("url"));
|
|
8855
|
-
var
|
|
8856
|
-
var
|
|
8855
|
+
var path37 = __importStar(require("path"));
|
|
8856
|
+
var fs37 = __importStar(require("fs"));
|
|
8857
8857
|
var child_process_1 = require("child_process");
|
|
8858
8858
|
function uriToFilePath(uri) {
|
|
8859
8859
|
const parsed = url.parse(uri);
|
|
@@ -8871,7 +8871,7 @@ var require_files = __commonJS({
|
|
|
8871
8871
|
segments.shift();
|
|
8872
8872
|
}
|
|
8873
8873
|
}
|
|
8874
|
-
return
|
|
8874
|
+
return path37.normalize(segments.join("/"));
|
|
8875
8875
|
}
|
|
8876
8876
|
function isWindows() {
|
|
8877
8877
|
return process.platform === "win32";
|
|
@@ -8899,9 +8899,9 @@ var require_files = __commonJS({
|
|
|
8899
8899
|
const env = process.env;
|
|
8900
8900
|
const newEnv = /* @__PURE__ */ Object.create(null);
|
|
8901
8901
|
Object.keys(env).forEach((key) => newEnv[key] = env[key]);
|
|
8902
|
-
if (nodePath &&
|
|
8902
|
+
if (nodePath && fs37.existsSync(nodePath)) {
|
|
8903
8903
|
if (newEnv[nodePathKey]) {
|
|
8904
|
-
newEnv[nodePathKey] = nodePath +
|
|
8904
|
+
newEnv[nodePathKey] = nodePath + path37.delimiter + newEnv[nodePathKey];
|
|
8905
8905
|
} else {
|
|
8906
8906
|
newEnv[nodePathKey] = nodePath;
|
|
8907
8907
|
}
|
|
@@ -8973,9 +8973,9 @@ var require_files = __commonJS({
|
|
|
8973
8973
|
}
|
|
8974
8974
|
if (prefix.length > 0) {
|
|
8975
8975
|
if (isWindows()) {
|
|
8976
|
-
return
|
|
8976
|
+
return path37.join(prefix, "node_modules");
|
|
8977
8977
|
} else {
|
|
8978
|
-
return
|
|
8978
|
+
return path37.join(prefix, "lib", "node_modules");
|
|
8979
8979
|
}
|
|
8980
8980
|
}
|
|
8981
8981
|
return void 0;
|
|
@@ -9014,7 +9014,7 @@ var require_files = __commonJS({
|
|
|
9014
9014
|
try {
|
|
9015
9015
|
const yarn = JSON.parse(line);
|
|
9016
9016
|
if (yarn.type === "log") {
|
|
9017
|
-
return
|
|
9017
|
+
return path37.join(yarn.data, "node_modules");
|
|
9018
9018
|
}
|
|
9019
9019
|
} catch (e) {
|
|
9020
9020
|
}
|
|
@@ -9036,24 +9036,24 @@ var require_files = __commonJS({
|
|
|
9036
9036
|
if (process.platform === "win32") {
|
|
9037
9037
|
_isCaseSensitive = false;
|
|
9038
9038
|
} else {
|
|
9039
|
-
_isCaseSensitive = !
|
|
9039
|
+
_isCaseSensitive = !fs37.existsSync(__filename.toUpperCase()) || !fs37.existsSync(__filename.toLowerCase());
|
|
9040
9040
|
}
|
|
9041
9041
|
return _isCaseSensitive;
|
|
9042
9042
|
}
|
|
9043
9043
|
FileSystem2.isCaseSensitive = isCaseSensitive;
|
|
9044
9044
|
function isParent(parent, child) {
|
|
9045
9045
|
if (isCaseSensitive()) {
|
|
9046
|
-
return
|
|
9046
|
+
return path37.normalize(child).indexOf(path37.normalize(parent)) === 0;
|
|
9047
9047
|
} else {
|
|
9048
|
-
return
|
|
9048
|
+
return path37.normalize(child).toLowerCase().indexOf(path37.normalize(parent).toLowerCase()) === 0;
|
|
9049
9049
|
}
|
|
9050
9050
|
}
|
|
9051
9051
|
FileSystem2.isParent = isParent;
|
|
9052
9052
|
})(FileSystem || (exports2.FileSystem = FileSystem = {}));
|
|
9053
9053
|
function resolveModulePath(workspaceRoot, moduleName, nodePath, tracer) {
|
|
9054
9054
|
if (nodePath) {
|
|
9055
|
-
if (!
|
|
9056
|
-
nodePath =
|
|
9055
|
+
if (!path37.isAbsolute(nodePath)) {
|
|
9056
|
+
nodePath = path37.join(workspaceRoot, nodePath);
|
|
9057
9057
|
}
|
|
9058
9058
|
return resolve2(moduleName, nodePath, nodePath, tracer).then((value) => {
|
|
9059
9059
|
if (FileSystem.isParent(nodePath, value)) {
|
|
@@ -9286,9 +9286,9 @@ var require_main = __commonJS({
|
|
|
9286
9286
|
exports2.createMessageConnection = createMessageConnection;
|
|
9287
9287
|
var ril_1 = __importDefault(require_ril());
|
|
9288
9288
|
ril_1.default.install();
|
|
9289
|
-
var
|
|
9289
|
+
var path37 = __importStar(require("path"));
|
|
9290
9290
|
var os2 = __importStar(require("os"));
|
|
9291
|
-
var
|
|
9291
|
+
var fs37 = __importStar(require("fs"));
|
|
9292
9292
|
var crypto_1 = require("crypto");
|
|
9293
9293
|
var net_1 = require("net");
|
|
9294
9294
|
var api_1 = require_api();
|
|
@@ -9429,7 +9429,7 @@ var require_main = __commonJS({
|
|
|
9429
9429
|
}
|
|
9430
9430
|
let randomLength = 32;
|
|
9431
9431
|
const fixedLength = "/lsp-.sock".length;
|
|
9432
|
-
const tmpDir =
|
|
9432
|
+
const tmpDir = fs37.realpathSync(XDG_RUNTIME_DIR ?? os2.tmpdir());
|
|
9433
9433
|
const limit = safeIpcPathLengths.get(process.platform);
|
|
9434
9434
|
if (limit !== void 0) {
|
|
9435
9435
|
randomLength = Math.min(limit - tmpDir.length - fixedLength, randomLength);
|
|
@@ -9438,7 +9438,7 @@ var require_main = __commonJS({
|
|
|
9438
9438
|
throw new Error(`Unable to generate a random pipe name with ${randomLength} characters.`);
|
|
9439
9439
|
}
|
|
9440
9440
|
const randomSuffix = (0, crypto_1.randomBytes)(Math.floor(randomLength / 2)).toString("hex");
|
|
9441
|
-
return
|
|
9441
|
+
return path37.join(tmpDir, `lsp-${randomSuffix}.sock`);
|
|
9442
9442
|
}
|
|
9443
9443
|
function createClientPipeTransport(pipeName, encoding = "utf-8") {
|
|
9444
9444
|
let connectResolve;
|
|
@@ -9837,7 +9837,7 @@ var require_main3 = __commonJS({
|
|
|
9837
9837
|
logger.error(`Assertion failed: ${message} ${serialize2(rest)}`);
|
|
9838
9838
|
}
|
|
9839
9839
|
};
|
|
9840
|
-
console.count = function
|
|
9840
|
+
console.count = function count2(label = "default") {
|
|
9841
9841
|
const message = String(label);
|
|
9842
9842
|
let counter = counters.get(message) ?? 0;
|
|
9843
9843
|
counter += 1;
|
|
@@ -10107,13 +10107,13 @@ function getWellformedEdit(textEdit) {
|
|
|
10107
10107
|
}
|
|
10108
10108
|
|
|
10109
10109
|
// src/server.ts
|
|
10110
|
-
var
|
|
10110
|
+
var fs36 = __toESM(require("fs"));
|
|
10111
10111
|
var os = __toESM(require("os"));
|
|
10112
|
-
var
|
|
10112
|
+
var path36 = __toESM(require("path"));
|
|
10113
10113
|
var import_crypto = require("crypto");
|
|
10114
10114
|
|
|
10115
10115
|
// package.json
|
|
10116
|
-
var version = "0.3.
|
|
10116
|
+
var version = "0.3.1";
|
|
10117
10117
|
|
|
10118
10118
|
// ../protocol/src/arrays.ts
|
|
10119
10119
|
function pushAll(target, source) {
|
|
@@ -10203,6 +10203,7 @@ var modFileChangedNotification = "paradox/modFileChanged";
|
|
|
10203
10203
|
var reloadDocsRequest = "paradox/reloadDocs";
|
|
10204
10204
|
var indexStatsRequest = "paradox/indexStats";
|
|
10205
10205
|
var lookupLocRequest = "paradox/lookupLoc";
|
|
10206
|
+
var locTextRequest = "paradox/locText";
|
|
10206
10207
|
var statusNotification = "paradox/status";
|
|
10207
10208
|
var indexChangedNotification = "paradox/indexChanged";
|
|
10208
10209
|
var progressNotification = "paradox/progress";
|
|
@@ -10236,9 +10237,24 @@ var eventBannerRequest = "paradox/eventBanner";
|
|
|
10236
10237
|
var eventVocabularyRequest = "paradox/eventVocabulary";
|
|
10237
10238
|
var EVENT_VOCABULARY_MAX_TOKENS = 600;
|
|
10238
10239
|
var EVENT_VOCABULARY_MAX_VALUES = 400;
|
|
10240
|
+
var DEFINITION_FORM_MAX_SAMPLED = 80;
|
|
10241
|
+
var DEFINITION_FORM_MAX_EXAMPLE = 120;
|
|
10239
10242
|
var eventValueOptionsRequest = "paradox/eventValueOptions";
|
|
10240
10243
|
var dependenciesRequest = "paradox/dependencies";
|
|
10244
|
+
var snippetsRequest = "paradox/snippets";
|
|
10241
10245
|
var scopeAtRequest = "paradox/scopeAt";
|
|
10246
|
+
var definitionFormRequest = "paradox/definitionForm";
|
|
10247
|
+
var definitionEditRequest = "paradox/definitionEdit";
|
|
10248
|
+
var modifierFormatsRequest = "paradox/modifierFormats";
|
|
10249
|
+
var dynastyTreeRequest = "paradox/dynastyTree";
|
|
10250
|
+
var DYNASTY_SKILLS = [
|
|
10251
|
+
"diplomacy",
|
|
10252
|
+
"martial",
|
|
10253
|
+
"stewardship",
|
|
10254
|
+
"intrigue",
|
|
10255
|
+
"learning",
|
|
10256
|
+
"prowess"
|
|
10257
|
+
];
|
|
10242
10258
|
|
|
10243
10259
|
// src/parser/cst.ts
|
|
10244
10260
|
var LineIndex = class {
|
|
@@ -10358,11 +10374,11 @@ function offsetInRange(offset, range) {
|
|
|
10358
10374
|
return offset >= range.start && offset <= range.end;
|
|
10359
10375
|
}
|
|
10360
10376
|
function nodeAtOffset(root, offset) {
|
|
10361
|
-
const
|
|
10377
|
+
const path37 = [];
|
|
10362
10378
|
const searchStatements = (statements2) => {
|
|
10363
10379
|
for (const stmt of statements2) {
|
|
10364
10380
|
if (!offsetInRange(offset, stmt.range)) continue;
|
|
10365
|
-
|
|
10381
|
+
path37.push(stmt);
|
|
10366
10382
|
const child = statementChildBlock(stmt);
|
|
10367
10383
|
if (child && offsetInRange(offset, child.range)) {
|
|
10368
10384
|
searchStatements(child.statements);
|
|
@@ -10372,7 +10388,7 @@ function nodeAtOffset(root, offset) {
|
|
|
10372
10388
|
return false;
|
|
10373
10389
|
};
|
|
10374
10390
|
searchStatements(root.statements);
|
|
10375
|
-
return
|
|
10391
|
+
return path37.length > 0 ? { path: path37 } : null;
|
|
10376
10392
|
}
|
|
10377
10393
|
|
|
10378
10394
|
// src/parser/lexer.ts
|
|
@@ -10743,9 +10759,12 @@ var ck3Meta = {
|
|
|
10743
10759
|
shortName: "CK3",
|
|
10744
10760
|
engine: "jomini",
|
|
10745
10761
|
descriptor: "mod",
|
|
10746
|
-
configDirName: ".
|
|
10762
|
+
configDirName: ".px-toolkit",
|
|
10763
|
+
legacyConfigDirName: ".ck3modding",
|
|
10747
10764
|
docsFolderName: "Crusader Kings III",
|
|
10748
10765
|
steamAppId: 1158310,
|
|
10766
|
+
// Verified on the 1.19 install: dlc_001.dds .. dlc_029.dds.
|
|
10767
|
+
dlcIconDir: "gfx/interface/icons/dlc",
|
|
10749
10768
|
eventNamespaces: true,
|
|
10750
10769
|
// The engine's own default metrics: they were measured on this game's font,
|
|
10751
10770
|
// and the layout engine reuses them for games whose probe has not run.
|
|
@@ -10753,6 +10772,60 @@ var ck3Meta = {
|
|
|
10753
10772
|
guiTextMetrics: GITAN_MEASURED_METRICS,
|
|
10754
10773
|
scaffolds: CK3_SCAFFOLDS,
|
|
10755
10774
|
tiger: { binaryName: "ck3-tiger", repoSlug: "amtep/tiger", confName: "ck3-tiger.conf" },
|
|
10775
|
+
// Visual creators. Every row is backed by a folder the schema table already
|
|
10776
|
+
// indexes and a shape read out of the game's own files:
|
|
10777
|
+
// trait common/traits, documented by common/traits/_traits.info
|
|
10778
|
+
// dynasty_legacy common/dynasty_legacies, per _dynasty_legacies.info
|
|
10779
|
+
// ("Dynasty Legacies are containers for perks"); the perks
|
|
10780
|
+
// themselves live in common/dynasty_perks (`legacy = <track>`)
|
|
10781
|
+
// culture common/culture/cultures (00_arabic.txt: color, ethos,
|
|
10782
|
+
// heritage, language, traditions, name_list, parents…)
|
|
10783
|
+
// culture_tradition common/culture/traditions, whose _traditions.info adds
|
|
10784
|
+
// `category` and `layers` to the shape _cultural_traits.info
|
|
10785
|
+
// documents for every cultural trait
|
|
10786
|
+
// dynasty_tree NOT a definition kind: history/characters linked by
|
|
10787
|
+
// father/mother/dynasty/house (history/characters/*.txt)
|
|
10788
|
+
creators: [
|
|
10789
|
+
{
|
|
10790
|
+
kind: "trait",
|
|
10791
|
+
label: "Trait Creator",
|
|
10792
|
+
icon: "sparkles",
|
|
10793
|
+
tip: "Design a character trait and write it into the mod."
|
|
10794
|
+
},
|
|
10795
|
+
{
|
|
10796
|
+
kind: "dynasty_legacy",
|
|
10797
|
+
label: "Dynasty Legacy Creator",
|
|
10798
|
+
icon: "layers",
|
|
10799
|
+
tip: "Build a legacy track and its perks."
|
|
10800
|
+
},
|
|
10801
|
+
{
|
|
10802
|
+
kind: "culture",
|
|
10803
|
+
label: "Culture Creator",
|
|
10804
|
+
icon: "globe",
|
|
10805
|
+
tip: "Compose a culture from the game's own pillars and traditions."
|
|
10806
|
+
},
|
|
10807
|
+
{
|
|
10808
|
+
kind: "culture_tradition",
|
|
10809
|
+
label: "Tradition Creator",
|
|
10810
|
+
icon: "flame",
|
|
10811
|
+
tip: "Design a culture tradition, its layered icon and its modifiers."
|
|
10812
|
+
},
|
|
10813
|
+
{
|
|
10814
|
+
kind: "dynasty_tree",
|
|
10815
|
+
label: "Dynasty Tree",
|
|
10816
|
+
icon: "users",
|
|
10817
|
+
tip: "See and edit a dynasty's characters across history."
|
|
10818
|
+
}
|
|
10819
|
+
],
|
|
10820
|
+
// Measured on the 1.19 install: common/modifier_definition_formats/ holds 13
|
|
10821
|
+
// files documented by _definitions.info in the same folder (decimals, color,
|
|
10822
|
+
// prefix/suffix/negative_suffix as loc keys, percent, already_percent,
|
|
10823
|
+
// hidden, no_difference_sign), and gui/texticons.gui holds the `texticon`
|
|
10824
|
+
// blocks a `[gold_i]` in one of those loc values resolves to.
|
|
10825
|
+
modifierFormats: {
|
|
10826
|
+
folder: "common/modifier_definition_formats",
|
|
10827
|
+
textIcons: "gui/texticons.gui"
|
|
10828
|
+
},
|
|
10756
10829
|
// Date-format keys verified in ck3.exe 1.19 (the gamedate.cpp string block);
|
|
10757
10830
|
// formats mirror game/localization/english/core_l_english.yml. Vanilla
|
|
10758
10831
|
// appends $ERA$/$ERA_BCE$ itself - dropped here, the {era} slot replaces it.
|
|
@@ -10794,7 +10867,30 @@ var ck3Meta = {
|
|
|
10794
10867
|
],
|
|
10795
10868
|
// "" keeps the pre-profile cache filenames (docsCache.json, vanillaIndex-*.json)
|
|
10796
10869
|
// so existing users' caches survive the M2 restructure.
|
|
10797
|
-
cacheSuffix: ""
|
|
10870
|
+
cacheSuffix: "",
|
|
10871
|
+
// Coat-of-arms coverage measured against this install (1.19.0.6, 2026-09-03):
|
|
10872
|
+
// parseCoaFile reads all 2992 vanilla definitions in the 10 files of
|
|
10873
|
+
// common/coat_of_arms/coat_of_arms with 0 parse errors, and 100% of both the
|
|
10874
|
+
// 7800 texture references (1629 files, every one decoding) and the 15327
|
|
10875
|
+
// colors resolve, the named ones out of the 112 in common/named_colors. 239
|
|
10876
|
+
// flags (8.0%) carried something the model dropped, 387 of those 399 keys
|
|
10877
|
+
// being `depth` on an instance, which the model now carries; Vic3, which has
|
|
10878
|
+
// shipped the builder since 0.3.2, drops something on 8.3% of its flags, so
|
|
10879
|
+
// CK3 is no worse off.
|
|
10880
|
+
flagBuilder: true,
|
|
10881
|
+
// Measured on this install (1.19.0.6, 2026-09-03): the in-game designer's
|
|
10882
|
+
// own files are all present and parse - 38 visible patterns of 42 rows in
|
|
10883
|
+
// gfx/coat_of_arms/patterns/50_coa_designer_patterns.txt, 1576 visible
|
|
10884
|
+
// emblems of 1578 rows in 13 categories in
|
|
10885
|
+
// colored_emblems/50_coa_designer_emblems.txt, 13 palette colors in
|
|
10886
|
+
// color_palettes/50_coa_designer_palettes.txt, 35 whole layouts in
|
|
10887
|
+
// emblem_layouts/50_coa_designer_emblem_layouts.txt, the
|
|
10888
|
+
// `coa_designer_blank_default` template in
|
|
10889
|
+
// common/coat_of_arms/coat_of_arms/99_coa_designer_templates.txt and 35
|
|
10890
|
+
// preview frames under gfx/interface/coat_of_arms. Victoria 3 ships no
|
|
10891
|
+
// gfx/coat_of_arms/color_palettes or emblem_layouts at all, and EU5 no coa
|
|
10892
|
+
// designer either, so neither sets this.
|
|
10893
|
+
coaDesigner: true
|
|
10798
10894
|
};
|
|
10799
10895
|
|
|
10800
10896
|
// src/games/jomini/variables.ts
|
|
@@ -21412,7 +21508,44 @@ var CURATED = {
|
|
|
21412
21508
|
};
|
|
21413
21509
|
var KEY_PATCHES = {
|
|
21414
21510
|
trait: {
|
|
21415
|
-
valid_sex: { values: "enum:all|male|female", doc: "Which sex can have the trait. Default: all." }
|
|
21511
|
+
valid_sex: { values: "enum:all|male|female", doc: "Which sex can have the trait. Default: all." },
|
|
21512
|
+
// `opposites = { chaste }` in game/common/traits/00_traits.txt: the entries
|
|
21513
|
+
// are trait names. Deliberately NOT a global REF_FIELD - scripted_relations
|
|
21514
|
+
// spells the same key over relation names (00_scripted_relations.txt,
|
|
21515
|
+
// `friend = { opposites = { rival ... } }`), and a global row would
|
|
21516
|
+
// mis-resolve there.
|
|
21517
|
+
opposites: { refKinds: ["trait"] }
|
|
21518
|
+
},
|
|
21519
|
+
culture: {
|
|
21520
|
+
// game/common/culture/cultures/00_arabic.txt: `traditions = {
|
|
21521
|
+
// tradition_tribe_unity ... }` names definitions of
|
|
21522
|
+
// common/culture/traditions, and `parents = { bedouin assyrian }` names
|
|
21523
|
+
// other cultures (bedouin is the top-level key of the same file).
|
|
21524
|
+
traditions: { refKinds: ["culture_tradition"] },
|
|
21525
|
+
parents: { refKinds: ["culture"] },
|
|
21526
|
+
// The five pillar keys all name definitions of common/culture/pillars
|
|
21527
|
+
// (00_arabic.txt: `ethos = ethos_stoic heritage = heritage_arabic
|
|
21528
|
+
// language = language_arabic martial_custom = martial_custom_male_only
|
|
21529
|
+
// head_determination = head_determination_domain`, each of them a
|
|
21530
|
+
// top-level key in common/culture/pillars/00_*.txt). One folder, so one
|
|
21531
|
+
// ref kind; the pillar's own `type` sorts the five pickers apart (the
|
|
21532
|
+
// schema entry's groupKey).
|
|
21533
|
+
ethos: { refKinds: ["culture_pillar"] },
|
|
21534
|
+
heritage: { refKinds: ["culture_pillar"] },
|
|
21535
|
+
language: { refKinds: ["culture_pillar"] },
|
|
21536
|
+
martial_custom: { refKinds: ["culture_pillar"] },
|
|
21537
|
+
head_determination: { refKinds: ["culture_pillar"] },
|
|
21538
|
+
// `name_list = name_list_bedouin` (00_arabic.txt) names a top-level key of
|
|
21539
|
+
// common/culture/name_lists (00_arabic.txt line 1 there).
|
|
21540
|
+
name_list: { refKinds: ["name_list"] }
|
|
21541
|
+
},
|
|
21542
|
+
dynasty_perk: {
|
|
21543
|
+
// _dynasty_perks.info spells the block `traits = { trait_name = int }`, and
|
|
21544
|
+
// game/common/dynasty_perks/00_dynasty_perks.txt writes it that way
|
|
21545
|
+
// (blood_legacy_4: `beauty_good_1 = 100`, `fecund = 50`), so the entry keys
|
|
21546
|
+
// are trait names and the numbers are AI chances. Per-KIND and not a global
|
|
21547
|
+
// RefField: `traits` elsewhere is a history list, a filter, a count.
|
|
21548
|
+
traits: { refKinds: ["trait"] }
|
|
21416
21549
|
},
|
|
21417
21550
|
scheme_type: {
|
|
21418
21551
|
category: { values: "enum:personal|contract|hostile" }
|
|
@@ -21710,7 +21843,20 @@ var CK3_SCHEMA_BASE = [
|
|
|
21710
21843
|
{ path: "events", kind: "event", extraction: "event-id", rootScopes: ["character"] },
|
|
21711
21844
|
{ path: "localization", kind: "loc_key", ext: ".yml", extraction: "loc-key" },
|
|
21712
21845
|
// --- Characters, traits, interactions ---
|
|
21713
|
-
|
|
21846
|
+
// locPatterns and iconFolder verbatim from common/traits/_traits.info
|
|
21847
|
+
// ("== Loc/icon ==": "the name key is trait_<key>, and the desc key is
|
|
21848
|
+
// trait_<key>_desc", "The default icon path is
|
|
21849
|
+
// gfx/interface/icons/traits/<trait>.dds"). trait_$_desc stays OUT of
|
|
21850
|
+
// requiredLoc: schemaVanilla.test.ts measures it at 90.4% of vanilla traits,
|
|
21851
|
+
// under the 95% bar a missing-loc diagnostic needs.
|
|
21852
|
+
{
|
|
21853
|
+
path: "common/traits",
|
|
21854
|
+
kind: "trait",
|
|
21855
|
+
requiredLoc: ["trait_$"],
|
|
21856
|
+
locPatterns: ["trait_$", "trait_$_desc"],
|
|
21857
|
+
iconFolder: "gfx/interface/icons/traits",
|
|
21858
|
+
rootScopes: ["character"]
|
|
21859
|
+
},
|
|
21714
21860
|
{
|
|
21715
21861
|
path: "common/character_interactions",
|
|
21716
21862
|
kind: "character_interaction",
|
|
@@ -21773,13 +21919,43 @@ var CK3_SCHEMA_BASE = [
|
|
|
21773
21919
|
{ path: "common/court_amenities", kind: "court_amenity" },
|
|
21774
21920
|
{ path: "common/court_types", kind: "court_type" },
|
|
21775
21921
|
// --- Culture ---
|
|
21776
|
-
{
|
|
21777
|
-
|
|
21922
|
+
{
|
|
21923
|
+
path: "common/culture/cultures",
|
|
21924
|
+
kind: "culture",
|
|
21925
|
+
requiredLoc: ["$"],
|
|
21926
|
+
// Every one of the 244 vanilla cultures defines all three keys in
|
|
21927
|
+
// game/localization/english/culture/cultures_l_english.yml (`bedouin`,
|
|
21928
|
+
// `bedouin_prefix`, `bedouin_collective_noun`), measured 244/244 in
|
|
21929
|
+
// 2026-09. requiredLoc keeps only `$` because the diagnostic that hangs
|
|
21930
|
+
// off it is the conservative one; a creator writes the whole set.
|
|
21931
|
+
locPatterns: ["$", "$_prefix", "$_collective_noun"]
|
|
21932
|
+
},
|
|
21933
|
+
{
|
|
21934
|
+
path: "common/culture/pillars",
|
|
21935
|
+
kind: "culture_pillar",
|
|
21936
|
+
// One folder, five families: game/common/culture/pillars/_pillars.info
|
|
21937
|
+
// documents `type = ethos/heritage/language/martial` on top of the common
|
|
21938
|
+
// cultural-trait shape, and the files spell it that way
|
|
21939
|
+
// (00_ethos.txt `type = ethos`, 00_martial_custom.txt `type =
|
|
21940
|
+
// martial_custom`, 00_head_determination.txt `type = head_determination`).
|
|
21941
|
+
groupKey: "type",
|
|
21942
|
+
// Measured 2026-09-04 in game/localization/english against the 162 vanilla
|
|
21943
|
+
// pillars: `$_name` 160, `$_desc` 9, bare `$` 4. The _pillars.info doc
|
|
21944
|
+
// names only the generic-desc fallback, so the name pattern is a measurement.
|
|
21945
|
+
requiredLoc: ["$_name"],
|
|
21946
|
+
locPatterns: ["$_name", "$_desc"]
|
|
21947
|
+
},
|
|
21778
21948
|
{
|
|
21779
21949
|
path: "common/culture/traditions",
|
|
21780
21950
|
kind: "culture_tradition",
|
|
21781
21951
|
// def names already carry the `tradition_` prefix; loc key is `<name>_name`.
|
|
21782
21952
|
requiredLoc: ["$_name"],
|
|
21953
|
+
// All 196 vanilla traditions also define `$_desc`, measured 196/196 in
|
|
21954
|
+
// game/localization/english against common/culture/traditions in 2026-09
|
|
21955
|
+
// (`tradition_winter_warriors_name` / `_desc`). requiredLoc keeps only
|
|
21956
|
+
// `$_name` because the diagnostic that hangs off it is the conservative
|
|
21957
|
+
// one; a creator writes the whole set.
|
|
21958
|
+
locPatterns: ["$_name", "$_desc"],
|
|
21783
21959
|
rootScopes: ["culture"]
|
|
21784
21960
|
},
|
|
21785
21961
|
{ path: "common/culture/innovations", kind: "innovation", requiredLoc: ["$"], rootScopes: ["culture"] },
|
|
@@ -21799,8 +21975,33 @@ var CK3_SCHEMA_BASE = [
|
|
|
21799
21975
|
// dynasties top-level keys are numeric ids; huge and never typed → not completable.
|
|
21800
21976
|
{ path: "common/dynasties", kind: "dynasty", completable: false },
|
|
21801
21977
|
{ path: "common/dynasty_houses", kind: "dynasty_house", completable: false },
|
|
21802
|
-
|
|
21803
|
-
|
|
21978
|
+
// _dynasty_legacies.info, "Generated loc keys: key + "_name"". All 21 vanilla
|
|
21979
|
+
// legacies define it (measured 2026-09-03), so it clears the requiredLoc bar.
|
|
21980
|
+
// $_desc is not in the .info doc, but all 21 vanilla tracks define it
|
|
21981
|
+
// (localization/english/dynasty_legacies/legacies_l_english.yml, e.g.
|
|
21982
|
+
// blood_legacy_track_desc), so a creator asks for it too; it stays out of
|
|
21983
|
+
// requiredLoc, where only the keys the doc itself states belong.
|
|
21984
|
+
// iconFolder: window_dynasty_legacy.gui draws the picture from
|
|
21985
|
+
// "[DynastyLegacy.GetIcon]", a code-side path with no script key behind it,
|
|
21986
|
+
// and the files it finds are gfx/interface/icons/dynasty/<track key>.dds
|
|
21987
|
+
// (22 files for the 21 tracks). Name-derived, so a creator writes the
|
|
21988
|
+
// picture under the track's own name and never a path into the block.
|
|
21989
|
+
// A track reads a SECOND name-derived picture, the window's illustration at
|
|
21990
|
+
// gfx/interface/illustrations/legacy_tracks/<key>.dds ("[DynastyLegacy.
|
|
21991
|
+
// GetTrackIcon]", 21 files); iconFolder holds one path, so that one is left
|
|
21992
|
+
// to ck3-tiger, which names it as a missing-file warning on the track.
|
|
21993
|
+
{
|
|
21994
|
+
path: "common/dynasty_legacies",
|
|
21995
|
+
kind: "dynasty_legacy",
|
|
21996
|
+
requiredLoc: ["$_name"],
|
|
21997
|
+
locPatterns: ["$_name", "$_desc"],
|
|
21998
|
+
iconFolder: "gfx/interface/icons/dynasty"
|
|
21999
|
+
},
|
|
22000
|
+
// _dynasty_perks.info, "Generated loc keys: key + "_name"" — and only that:
|
|
22001
|
+
// all 105 vanilla perks define $_name, none defines $_desc (measured
|
|
22002
|
+
// 2026-09-03 over localization/english). No iconFolder: gfx/interface/icons
|
|
22003
|
+
// has a dynasty folder for the tracks and nothing for the perks.
|
|
22004
|
+
{ path: "common/dynasty_perks", kind: "dynasty_perk", locPatterns: ["$_name"] },
|
|
21804
22005
|
// --- Activities & schemes ---
|
|
21805
22006
|
{ path: "common/activities/activity_types", kind: "activity_type", rootScopes: ["character"] },
|
|
21806
22007
|
{
|
|
@@ -21853,7 +22054,15 @@ var CK3_SCHEMA_BASE = [
|
|
|
21853
22054
|
// remaining common/ folder with a standard top-level `name = { ... }`
|
|
21854
22055
|
// layout, verified by parsing vanilla files. Ordered by definition count.
|
|
21855
22056
|
{ path: "common/game_concepts", kind: "game_concept", requiredLoc: ["game_concept_$"] },
|
|
21856
|
-
{
|
|
22057
|
+
{
|
|
22058
|
+
path: "common/domiciles/buildings",
|
|
22059
|
+
kind: "domicile_building",
|
|
22060
|
+
rootScopes: ["character", "domicile"],
|
|
22061
|
+
// Measured 2026-09-04: all 1620 vanilla domicile buildings define
|
|
22062
|
+
// `$_domicile_building` (109 also `$_domicile_building_desc`), none a bare `$`.
|
|
22063
|
+
requiredLoc: ["$_domicile_building"],
|
|
22064
|
+
locPatterns: ["$_domicile_building", "$_domicile_building_desc"]
|
|
22065
|
+
},
|
|
21857
22066
|
{ path: "common/domiciles/types", kind: "domicile_type", rootScopes: ["character"] },
|
|
21858
22067
|
{ path: "common/artifacts/features", kind: "artifact_feature" },
|
|
21859
22068
|
{ path: "common/artifacts/feature_groups", kind: "artifact_feature_group" },
|
|
@@ -30798,6 +31007,9 @@ var guiSchema_default = {
|
|
|
30798
31007
|
]
|
|
30799
31008
|
};
|
|
30800
31009
|
|
|
31010
|
+
// data/ck3/skeletons.json
|
|
31011
|
+
var skeletons_default = { meta: { generated: "2026-09-03", sources: ["vanilla (3077 files)"], majority: 0.5 }, kinds: { accolade_name: { sampled: 16, keys: [{ key: "key" }, { key: "num_options", choices: ["2", "1"] }, { key: "option", block: [{ key: "random_valid", block: [] }] }, { key: "potential", block: [] }], blocks: { option: { sampled: 26, keys: [{ key: "random_valid", block: [{ key: "triggered_desc", block: [] }, { key: "desc" }] }] } } }, accolade_type: { sampled: 31, keys: [{ key: "adjective" }, { key: "noun" }, { key: "icon" }, { key: "portrait_pose" }, { key: "accolade_categories", block: [] }, { key: "squire_perfect_fit", block: [] }, { key: "squire_acceptable_fit", block: [] }, { key: "weight", block: [{ key: "value", choices: ["accolade_uninteresting_base_value", "accolade_standard_base_value", "accolade_fascinating_base_value"] }, { key: "if", block: [] }] }, { key: "ranks", block: [{ key: "1", block: [] }, { key: "2", block: [] }, { key: "3", block: [] }] }], blocks: { ranks: { sampled: 31, keys: [{ key: "1", block: [{ key: "liege_modifier", block: [] }] }, { key: "2", block: [{ key: "liege_modifier", block: [] }, { key: "knight_army_modifier", block: [] }] }, { key: "3", block: [{ key: "liege_modifier", block: [] }, { key: "knight_army_modifier", block: [] }] }] }, weight: { sampled: 31, keys: [{ key: "value", choices: ["accolade_uninteresting_base_value", "accolade_standard_base_value", "accolade_fascinating_base_value"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", placeholder: "50" }] }] } } }, achievement: { sampled: 188, keys: [{ key: "possible", block: [] }, { key: "happened", block: [{ key: "custom_description", block: [] }] }], blocks: { happened: { sampled: 188, keys: [{ key: "custom_description", block: [{ key: "text" }] }] } } }, activity_intent: { sampled: 59, keys: [{ key: "icon" }, { key: "auto_complete", choices: ["yes"] }, { key: "on_invalidated", block: [{ key: "trigger_event", choices: ["activity_system.0090"] }] }, { key: "scripted_animation", block: [{ key: "animation" }] }, { key: "ai_will_do", block: [{ key: "value" }, { key: "if", block: [] }] }], blocks: { ai_will_do: { sampled: 49, keys: [{ key: "value" }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add" }] }] }, on_invalidated: { sampled: 31, keys: [{ key: "trigger_event", choices: ["activity_system.0090"] }] }, scripted_animation: { sampled: 59, keys: [{ key: "animation" }] } } }, activity_pulse_action: { sampled: 307, keys: [{ key: "icon" }, { key: "is_valid", block: [{ key: "is_current_phase_active", choices: ["yes"] }, { key: "any_attending_character", block: [] }] }, { key: "weight", block: [{ key: "value" }] }, { key: "effect", block: [{ key: "random_attending_character", block: [] }, { key: "add_activity_log_entry", block: [] }] }], blocks: { effect: { sampled: 307, keys: [{ key: "random_attending_character", block: [{ key: "limit", block: [] }, { key: "save_scope_as", choices: ["first", "second", "hunter", "eggman", "hunter_2", "poet"] }] }, { key: "add_activity_log_entry", block: [{ key: "key" }, { key: "tags", block: [] }, { key: "character" }] }] }, is_valid: { sampled: 307, keys: [{ key: "is_current_phase_active", choices: ["yes"] }, { key: "any_attending_character", block: [] }] }, weight: { sampled: 255, keys: [{ key: "value" }] } } }, activity_type: { sampled: 21, keys: [{ key: "is_shown", block: [{ key: "highest_held_title_tier", choices: ["tier_barony", "tier_county", "tier_empire"] }, { key: "trigger_if", block: [] }] }, { key: "can_start_showing_failures_only", block: [{ key: "NOT", block: [] }, { key: "trigger_if", block: [] }] }, { key: "is_valid", block: [{ key: "trigger_if", block: [] }] }, { key: "on_invalidated", block: [{ key: "if", block: [] }] }, { key: "on_host_death", block: [] }, { key: "is_location_valid", block: [] }, { key: "ai_check_interval_by_tier", block: [{ key: "barony", choices: ["0"] }, { key: "county", choices: ["60", "0", "4", "72"] }, { key: "duchy", choices: ["60", "0", "4"] }, { key: "kingdom", choices: ["60", "0", "4"] }, { key: "empire", choices: ["60", "0", "100", "4"] }, { key: "hegemony", choices: ["60", "0", "12", "4"] }] }, { key: "ai_will_do", block: [{ key: "value", choices: ["0", "50", "100", "1000", "20", "30"] }, { key: "if", block: [] }, { key: "else_if", block: [] }] }, { key: "is_single_location", choices: ["yes", "no"] }, { key: "province_filter" }, { key: "province_description", block: [{ key: "desc" }, { key: "triggered_desc", block: [] }] }, { key: "ai_province_filter", choices: ["capital", "domicile_domain", "domain", "holy_sites", "holy_sites_realm", "realm", "top_realm"] }, { key: "max_province_icons", choices: ["5", "3", "1", "10000"] }, { key: "cooldown", block: [{ key: "years" }] }, { key: "province_score", block: [{ key: "add", choices: ["camp_party_province_reference_value", "coronation_province_reference_value", "hunt_province_reference_value", "journey_province_reference_value", "roaming_province_reference_value", "survey_province_reference_value"] }, { key: "if", block: [] }] }, { key: "ai_will_select_province", block: [{ key: "value", choices: ["10", "50", "0", "1", "5", "scope:score"] }, { key: "if", block: [] }] }, { key: "cost", block: [{ key: "gold", block: [] }] }, { key: "ui_predicted_cost", block: [{ key: "gold", block: [] }] }, { key: "options", block: [] }, { key: "phases", block: [] }, { key: "max_guest_arrival_delay_time", block: [{ key: "months", choices: ["5", "1", "2", "4", "8"] }] }, { key: "max_guests", placeholder: "20" }, { key: "host_intents", block: [{ key: "intents", block: [] }, { key: "default" }] }, { key: "can_be_activity_guest", block: [{ key: "in_diplomatic_range", choices: ["scope:host"] }] }, { key: "guest_invite_rules", block: [{ key: "defaults", block: [] }, { key: "rules", block: [] }] }, { key: "guest_intents", block: [{ key: "intents", block: [] }, { key: "default" }] }, { key: "guest_join_chance", block: [{ key: "base", choices: ["10", "5", "-25", "50"] }, { key: "base_activity_modifier", choices: ["yes"] }, { key: "activity_guest_shared_ai_accept_modifier", choices: ["yes"] }, { key: "modifier", block: [] }] }, { key: "pulse_actions", block: [{ key: "entries", block: [] }, { key: "chance_of_no_event", choices: ["5", "0", "3", "2", "10"] }] }, { key: "travel_entourage_selection", block: [{ key: "weight", block: [] }, { key: "max", choices: ["15", "10", "18", "2", "20", "5", "3"] }, { key: "invite_rule_order", choices: ["1", "3"] }, { key: "ai_max", choices: ["3", "15", "2", "7"] }] }, { key: "on_start", block: [{ key: "if", block: [] }] }, { key: "on_enter_active_state", block: [{ key: "surveyor_no_stone_unturned_perk_effect", choices: ["yes"] }] }, { key: "on_enter_passive_state", block: [{ key: "if", block: [] }] }, { key: "background", block: [{ key: "trigger", block: [] }, { key: "texture" }, { key: "environment" }, { key: "ambience" }] }, { key: "on_complete", block: [{ key: "if", block: [] }] }, { key: "window_characters", block: [{ key: "guest", block: [] }, { key: "host", block: [] }, { key: "travel_host", block: [] }] }, { key: "activity_window_widgets", block: [] }], blocks: { ai_check_interval_by_tier: { sampled: 15, keys: [{ key: "barony", choices: ["0"] }, { key: "county", choices: ["60", "0", "4", "72"] }, { key: "duchy", choices: ["60", "0", "4"] }, { key: "kingdom", choices: ["60", "0", "4"] }, { key: "empire", choices: ["60", "0", "100", "4"] }, { key: "hegemony", choices: ["60", "0", "12", "4"] }] }, ai_will_do: { sampled: 21, keys: [{ key: "value", choices: ["0", "50", "100", "1000", "20", "30"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", block: [] }] }, { key: "else_if", block: [{ key: "limit", block: [] }, { key: "add", block: [] }] }] }, ai_will_select_province: { sampled: 20, keys: [{ key: "value", choices: ["10", "50", "0", "1", "5", "scope:score"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", block: [] }] }] }, background: { sampled: 551, keys: [{ key: "trigger", block: [] }, { key: "texture" }, { key: "environment" }, { key: "ambience" }] }, can_be_activity_guest: { sampled: 20, keys: [{ key: "in_diplomatic_range", choices: ["scope:host"] }] }, can_start_showing_failures_only: { sampled: 21, keys: [{ key: "NOT", block: [{ key: "is_activity_type_on_cooldown" }] }, { key: "trigger_if", block: [{ key: "limit", block: [] }, { key: "custom_tooltip", block: [] }] }] }, cooldown: { sampled: 19, keys: [{ key: "years" }] }, cost: { sampled: 21, keys: [{ key: "gold", block: [{ key: "add", block: [] }, { key: "if", block: [] }] }] }, guest_intents: { sampled: 21, keys: [{ key: "intents", block: [] }, { key: "default" }] }, guest_invite_rules: { sampled: 15, keys: [{ key: "defaults", block: [{ key: "1" }, { key: "2" }, { key: "3" }] }, { key: "rules", block: [{ key: "2", choices: ["activity_invite_rule_lovers", "activity_invite_rule_rivals", "activity_invite_rule_potential_lovers", "activity_invite_rule_rivals_if_appropriate", "activity_invite_rule_extended_family", "activity_invite_rule_friends"] }, { key: "3", choices: ["activity_invite_rule_extended_family", "activity_invite_mp", "activity_invite_rule_close_family", "activity_invite_rule_vassals_children"] }, { key: "6", choices: ["activity_invite_mp"] }] }] }, guest_join_chance: { sampled: 19, keys: [{ key: "base", choices: ["10", "5", "-25", "50"] }, { key: "base_activity_modifier", choices: ["yes"] }, { key: "activity_guest_shared_ai_accept_modifier", choices: ["yes"] }, { key: "modifier", block: [{ key: "add" }, { key: "desc" }] }] }, host_intents: { sampled: 21, keys: [{ key: "intents", block: [] }, { key: "default" }] }, is_shown: { sampled: 21, keys: [{ key: "highest_held_title_tier", choices: ["tier_barony", "tier_county", "tier_empire"] }, { key: "trigger_if", block: [{ key: "limit", block: [] }, { key: "NOT", block: [] }] }] }, is_valid: { sampled: 21, keys: [{ key: "trigger_if", block: [{ key: "limit", block: [] }, { key: "has_attending_activity_guests", choices: ["yes"] }] }] }, max_guest_arrival_delay_time: { sampled: 19, keys: [{ key: "months", choices: ["5", "1", "2", "4", "8"] }] }, on_complete: { sampled: 17, keys: [{ key: "if", block: [{ key: "limit", block: [] }] }] }, on_enter_active_state: { sampled: 19, keys: [{ key: "surveyor_no_stone_unturned_perk_effect", choices: ["yes"] }] }, on_enter_passive_state: { sampled: 14, keys: [{ key: "if", block: [{ key: "limit", block: [] }] }] }, on_invalidated: { sampled: 20, keys: [{ key: "if", block: [{ key: "limit", block: [] }, { key: "every_attending_character", block: [] }] }] }, on_start: { sampled: 18, keys: [{ key: "if", block: [{ key: "limit", block: [] }] }] }, province_description: { sampled: 17, keys: [{ key: "desc" }, { key: "triggered_desc", block: [{ key: "trigger", block: [] }, { key: "desc" }] }] }, province_score: { sampled: 13, keys: [{ key: "add", choices: ["camp_party_province_reference_value", "coronation_province_reference_value", "hunt_province_reference_value", "journey_province_reference_value", "roaming_province_reference_value", "survey_province_reference_value"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", placeholder: "100" }] }] }, pulse_actions: { sampled: 21, keys: [{ key: "entries", block: [] }, { key: "chance_of_no_event", choices: ["5", "0", "3", "2", "10"] }] }, travel_entourage_selection: { sampled: 16, keys: [{ key: "weight", block: [{ key: "value", choices: ["standard_travel_entourage_additions", "10", "0"] }, { key: "if", block: [] }] }, { key: "max", choices: ["15", "10", "18", "2", "20", "5", "3"] }, { key: "invite_rule_order", choices: ["1", "3"] }, { key: "ai_max", choices: ["3", "15", "2", "7"] }] }, ui_predicted_cost: { sampled: 21, keys: [{ key: "gold", block: [{ key: "if", block: [] }, { key: "divide", choices: ["5"] }, { key: "ceiling", choices: ["yes"] }, { key: "multiply", choices: ["5"] }] }] }, window_characters: { sampled: 21, keys: [{ key: "guest", block: [{ key: "camera", choices: ["camera_event_center", "camera_body_left", "camera_body", "camera_body_right", "camera_body_left_slight", "camera_event_left", "camera_event_right", "camera_event_left_forward"] }, { key: "effect", block: [] }, { key: "scripted_animation", block: [] }] }, { key: "host", block: [{ key: "camera", choices: ["camera_body", "camera_event_center", "camera_activity_horse", "camera_event_left"] }, { key: "effect", block: [] }, { key: "scripted_animation", block: [] }] }, { key: "travel_host", block: [{ key: "camera", choices: ["camera_event_horse_left", "camera_activity_horse", "camera_event_center"] }, { key: "effect", block: [] }, { key: "scripted_animation", block: [] }] }] } } }, artifact_feature: { sampled: 632, keys: [{ key: "group" }, { key: "trigger", block: [] }, { key: "weight", placeholder: "1" }] }, artifact_feature_group: { sampled: 59, keys: [] }, artifact_slot: { sampled: 24, keys: [{ key: "type" }, { key: "category", choices: ["court", "inventory"] }] }, artifact_template: { sampled: 71, keys: [{ key: "can_equip", block: [{ key: "always", choices: ["yes"] }] }, { key: "can_benefit", block: [] }, { key: "fallback", block: [{ key: "court_grandeur_baseline_add", choices: ["3", "6", "4", "5", "2", "10"] }] }, { key: "unique", choices: ["yes"] }], blocks: { can_equip: { sampled: 70, keys: [{ key: "always", choices: ["yes"] }] }, fallback: { sampled: 71, keys: [{ key: "court_grandeur_baseline_add", choices: ["3", "6", "4", "5", "2", "10"] }] } } }, artifact_type: { sampled: 65, keys: [{ key: "slot" }, { key: "required_features", block: [] }] }, artifact_visual: { sampled: 175, keys: [{ key: "icon" }, { key: "asset", block: [{ key: "trigger", block: [] }, { key: "reference" }] }], blocks: { asset: { sampled: 681, keys: [{ key: "trigger", block: [{ key: "OR", block: [] }] }, { key: "reference" }] } } }, bookmark: { sampled: 19, keys: [{ key: "start_date", choices: ["1066.9.15", "867.1.1", "1178.10.1"] }, { key: "is_playable", choices: ["yes"] }, { key: "group", choices: ["bm_group_1066", "bm_group_867", "bm_group_1178"] }, { key: "character", block: [{ key: "name" }, { key: "dynasty" }, { key: "dynasty_splendor_level", choices: ["2", "1", "3", "5", "4"] }, { key: "type", choices: ["male", "female"] }, { key: "birth" }, { key: "title" }, { key: "government" }, { key: "culture" }, { key: "religion" }, { key: "difficulty", choices: ["BOOKMARK_CHARACTER_DIFFICULTY_HARD", "BOOKMARK_CHARACTER_DIFFICULTY_MEDIUM", "BOOKMARK_CHARACTER_DIFFICULTY_EASY"] }, { key: "history_id" }, { key: "position", block: [] }, { key: "animation" }, { key: "character", block: [] }] }, { key: "weight", block: [{ key: "value", choices: ["0", "100", "200", "50", "90"] }] }], blocks: { character: { sampled: 110, keys: [{ key: "name" }, { key: "dynasty" }, { key: "dynasty_splendor_level", choices: ["2", "1", "3", "5", "4"] }, { key: "type", choices: ["male", "female"] }, { key: "birth" }, { key: "title" }, { key: "government" }, { key: "culture" }, { key: "religion" }, { key: "difficulty", choices: ["BOOKMARK_CHARACTER_DIFFICULTY_HARD", "BOOKMARK_CHARACTER_DIFFICULTY_MEDIUM", "BOOKMARK_CHARACTER_DIFFICULTY_EASY"] }, { key: "history_id" }, { key: "position", block: [] }, { key: "animation" }, { key: "character", block: [{ key: "name" }, { key: "relation" }, { key: "dynasty" }, { key: "type", choices: ["male", "female"] }, { key: "birth" }, { key: "culture" }, { key: "religion" }, { key: "history_id" }, { key: "animation" }] }] }, weight: { sampled: 15, keys: [{ key: "value", choices: ["0", "100", "200", "50", "90"] }] } } }, building: { sampled: 981, keys: [{ key: "construction_time", choices: ["slow_construction_time", "standard_construction_time", "very_slow_construction_time", "quick_construction_time", "500", "0"] }, { key: "effect_desc" }, { key: "can_construct_potential", block: [{ key: "building_requirement_tribal", choices: ["no"] }] }, { key: "type_icon" }, { key: "can_construct", block: [{ key: "building_requirement_castle_city_church", block: [] }] }, { key: "cost_gold" }, { key: "character_modifier", block: [] }, { key: "province_modifier", block: [{ key: "monthly_income" }] }, { key: "county_modifier", block: [{ key: "development_growth_factor" }] }, { key: "next_building" }, { key: "on_complete", block: [{ key: "creator_mandala_built_regular_building_piety_effect", choices: ["yes"] }] }, { key: "ai_value", block: [{ key: "base", placeholder: "100" }, { key: "modifier", block: [] }] }, { key: "type", choices: ["special", "duchy_capital", "great_building"] }, { key: "flag" }], blocks: { ai_value: { sampled: 959, keys: [{ key: "base", placeholder: "100" }, { key: "modifier", block: [{ key: "factor", placeholder: "0" }, { key: "free_building_slots", choices: ["0", "1", "2", "3"] }] }] }, can_construct: { sampled: 654, keys: [{ key: "building_requirement_castle_city_church", block: [{ key: "LEVEL", choices: ["02", "03", "04", "01"] }] }] }, can_construct_potential: { sampled: 847, keys: [{ key: "building_requirement_tribal", choices: ["no"] }] }, county_modifier: { sampled: 741, keys: [{ key: "development_growth_factor" }] }, on_complete: { sampled: 505, keys: [{ key: "creator_mandala_built_regular_building_piety_effect", choices: ["yes"] }] }, province_modifier: { sampled: 870, keys: [{ key: "monthly_income" }] } } }, casus_belli: { sampled: 121, keys: [{ key: "icon" }, { key: "group" }, { key: "combine_into_one", choices: ["yes", "no"] }, { key: "should_show_war_goal_subview", choices: ["yes", "no"] }, { key: "allow_hostages", choices: ["no", "yes"] }, { key: "mutually_exclusive_titles", block: [{ key: "always", choices: ["yes", "no"] }] }, { key: "allowed_for_character", block: [] }, { key: "allowed_against_character", block: [] }, { key: "target_titles", choices: ["all", "neighbor_land_or_water", "neighbor_land", "claim", "none", "de_jure", "independence_domain"] }, { key: "target_de_jure_regions_above", choices: ["yes", "no"] }, { key: "target_title_tier", choices: ["all", "county", "duchy", "kingdom", "empire"] }, { key: "ignore_effect", choices: ["change_title_holder"] }, { key: "valid_to_start", block: [] }, { key: "should_invalidate", block: [] }, { key: "on_invalidated_desc" }, { key: "on_declaration", block: [{ key: "on_declared_war", choices: ["yes"] }] }, { key: "cost", block: [{ key: "prestige", block: [] }] }, { key: "on_victory_desc", block: [{ key: "first_valid", block: [] }] }, { key: "on_victory", block: [{ key: "add_legitimacy_attacker_victory_effect", choices: ["yes"] }, { key: "create_title_and_vassal_change", block: [] }, { key: "every_in_list", block: [] }, { key: "modify_allies_of_participants_fame_values", block: [] }, { key: "add_truce_attacker_victory_effect", choices: ["yes"] }, { key: "laamp_as_mercenary_payout_tooltip_effect", choices: ["yes"] }, { key: "mandala_war_victory_effects", choices: ["yes"] }] }, { key: "on_invalidated", block: [] }, { key: "on_white_peace_desc", block: [{ key: "first_valid", block: [] }] }, { key: "on_white_peace", block: [{ key: "modify_allies_of_participants_fame_values", block: [] }, { key: "add_truce_white_peace_effect", choices: ["yes"] }, { key: "laamp_as_mercenary_payout_tooltip_effect", choices: ["yes"] }] }, { key: "on_defeat", block: [{ key: "add_legitimacy_attacker_defeat_effect", choices: ["yes"] }, { key: "modify_allies_of_participants_fame_values", block: [] }, { key: "add_truce_attacker_defeat_effect", choices: ["yes"] }, { key: "on_lost_aggression_war_discontent_loss", choices: ["yes"] }, { key: "laamp_as_mercenary_payout_tooltip_effect", choices: ["yes"] }, { key: "mandala_war_defeat_effects", choices: ["yes"] }] }, { key: "on_defeat_desc", block: [{ key: "first_valid", block: [] }] }, { key: "on_primary_attacker_death", choices: ["inherit", "invalidate", "inherit_faction"] }, { key: "on_primary_defender_death", choices: ["inherit", "invalidate"] }, { key: "transfer_behavior", choices: ["transfer"] }, { key: "attacker_allies_inherit", choices: ["yes", "no"] }, { key: "defender_allies_inherit", choices: ["yes", "no"] }, { key: "war_name" }, { key: "interface_priority", placeholder: "80" }, { key: "ai_score_mult", block: [{ key: "value" }, { key: "add", choices: ["frankokratia_leader_protection_value", "house_relation_ai_score_value", "1"] }] }, { key: "war_name_base" }, { key: "cb_name" }, { key: "attacker_wargoal_percentage", placeholder: "0.8" }, { key: "max_ai_diplo_distance_to_title", choices: ["500", "1000", "10000", "2000", "1500", "750", "850"] }, { key: "use_de_jure_wargoal_only", choices: ["yes", "no"] }, { key: "max_defender_score_from_occupation", choices: ["150", "50", "100", "0", "25", "75"] }, { key: "max_attacker_score_from_occupation", choices: ["150", "50", "1", "100", "200", "450"] }], blocks: { ai_score_mult: { sampled: 77, keys: [{ key: "value" }, { key: "add", choices: ["frankokratia_leader_protection_value", "house_relation_ai_score_value", "1"] }] }, cost: { sampled: 92, keys: [{ key: "prestige", block: [{ key: "add", block: [] }, { key: "value" }, { key: "multiply", choices: ["common_cb_prestige_cost_multiplier", "common_claim_reduction_cost_multiplier_core", "common_cb_prestige_cost_multiplier_sans_struggles"] }] }] }, mutually_exclusive_titles: { sampled: 62, keys: [{ key: "always", choices: ["yes", "no"] }] }, on_declaration: { sampled: 117, keys: [{ key: "on_declared_war", choices: ["yes"] }] }, on_defeat: { sampled: 121, keys: [{ key: "add_legitimacy_attacker_defeat_effect", choices: ["yes"] }, { key: "modify_allies_of_participants_fame_values", block: [{ key: "WINNER", choices: ["scope:defender"] }, { key: "FAME_BASE", choices: ["medium_prestige_value", "major_prestige_value", "minor_prestige_value", "mongol_invasion_cb_ally_prestige", "religious_cb_ally_prestige_county", "religious_cb_ally_prestige_duchy", "religious_cb_ally_prestige_kingdom"] }, { key: "IS_RELIGIOUS_WAR", choices: ["no"] }, { key: "WINNER_ALLY_FAME_SCALE", choices: ["1", "0", "10"] }, { key: "LOSER_ALLY_FAME_SCALE", choices: ["1", "10"] }] }, { key: "add_truce_attacker_defeat_effect", choices: ["yes"] }, { key: "on_lost_aggression_war_discontent_loss", choices: ["yes"] }, { key: "laamp_as_mercenary_payout_tooltip_effect", choices: ["yes"] }, { key: "mandala_war_defeat_effects", choices: ["yes"] }] }, on_defeat_desc: { sampled: 121, keys: [{ key: "first_valid", block: [{ key: "triggered_desc", block: [] }, { key: "desc" }] }] }, on_victory: { sampled: 121, keys: [{ key: "add_legitimacy_attacker_victory_effect", choices: ["yes"] }, { key: "create_title_and_vassal_change", block: [{ key: "type", choices: ["conquest", "conquest_holy_war", "independency", "swear_fealty", "conquest_claim"] }, { key: "save_scope_as", choices: ["change", "title_change"] }, { key: "add_claim_on_loss", choices: ["yes", "no"] }] }, { key: "every_in_list", block: [{ key: "list", choices: ["target_titles", "titles_taken", "vassals_taken", "target_title_taken", "defender_player_vassals", "titles_to_destroy", "anti_gok_attackers", "anti_gok_defenders"] }] }, { key: "modify_allies_of_participants_fame_values", block: [{ key: "WINNER", choices: ["scope:attacker", "scope:defender"] }, { key: "FAME_BASE", choices: ["medium_prestige_value", "major_prestige_value", "minor_prestige_value", "mongol_invasion_cb_ally_prestige", "religious_cb_ally_prestige_county", "religious_cb_ally_prestige_duchy", "religious_cb_ally_prestige_kingdom"] }, { key: "IS_RELIGIOUS_WAR", choices: ["no"] }, { key: "WINNER_ALLY_FAME_SCALE", choices: ["1", "0", "10"] }, { key: "LOSER_ALLY_FAME_SCALE", choices: ["1", "3"] }] }, { key: "add_truce_attacker_victory_effect", choices: ["yes"] }, { key: "laamp_as_mercenary_payout_tooltip_effect", choices: ["yes"] }, { key: "mandala_war_victory_effects", choices: ["yes"] }] }, on_victory_desc: { sampled: 120, keys: [{ key: "first_valid", block: [{ key: "triggered_desc", block: [] }, { key: "desc" }] }] }, on_white_peace: { sampled: 112, keys: [{ key: "modify_allies_of_participants_fame_values", block: [{ key: "WINNER", choices: ["scope:attacker", "scope:defender"] }, { key: "FAME_BASE" }, { key: "IS_RELIGIOUS_WAR", choices: ["no"] }, { key: "WINNER_ALLY_FAME_SCALE", choices: ["1", "100", "10", "0"] }, { key: "LOSER_ALLY_FAME_SCALE", choices: ["1", "100", "10", "5"] }] }, { key: "add_truce_white_peace_effect", choices: ["yes"] }, { key: "laamp_as_mercenary_payout_tooltip_effect", choices: ["yes"] }] }, on_white_peace_desc: { sampled: 121, keys: [{ key: "first_valid", block: [{ key: "triggered_desc", block: [] }, { key: "desc" }] }] } } }, casus_belli_group: { sampled: 19, keys: [{ key: "allowed_for_character", block: [{ key: "herders_and_tributary_constraints", choices: ["yes"] }, { key: "tgp_dynastic_cycle_offensive_wars_ban_trigger", choices: ["yes"] }, { key: "tgp_war_ban_all_ministers_trigger", choices: ["yes"] }] }], blocks: { allowed_for_character: { sampled: 17, keys: [{ key: "herders_and_tributary_constraints", choices: ["yes"] }, { key: "tgp_dynastic_cycle_offensive_wars_ban_trigger", choices: ["yes"] }, { key: "tgp_war_ban_all_ministers_trigger", choices: ["yes"] }] } } }, challenge_character: { sampled: 52, keys: [{ key: "start_date", choices: ["1066.9.15", "867.1.1", "1178.10.1"] }, { key: "achievements", block: [] }, { key: "character", block: [{ key: "name" }, { key: "dynasty" }, { key: "dynasty_splendor_level", choices: ["1", "3", "4", "2", "5", "6"] }, { key: "type", choices: ["male"] }, { key: "birth" }, { key: "title" }, { key: "government", choices: ["feudal_government", "clan_government", "tribal_government"] }, { key: "culture" }, { key: "religion" }, { key: "difficulty", choices: ["BOOKMARK_CHARACTER_DIFFICULTY_MEDIUM", "BOOKMARK_CHARACTER_DIFFICULTY_HARD", "BOOKMARK_CHARACTER_DIFFICULTY_EASY"] }, { key: "history_id" }, { key: "animation" }] }], blocks: { character: { sampled: 52, keys: [{ key: "name" }, { key: "dynasty" }, { key: "dynasty_splendor_level", choices: ["1", "3", "4", "2", "5", "6"] }, { key: "type", choices: ["male"] }, { key: "birth" }, { key: "title" }, { key: "government", choices: ["feudal_government", "clan_government", "tribal_government"] }, { key: "culture" }, { key: "religion" }, { key: "difficulty", choices: ["BOOKMARK_CHARACTER_DIFFICULTY_MEDIUM", "BOOKMARK_CHARACTER_DIFFICULTY_HARD", "BOOKMARK_CHARACTER_DIFFICULTY_EASY"] }, { key: "history_id" }, { key: "animation" }] } } }, character: { sampled: 71142, keys: [{ key: "name" }, { key: "dynasty" }, { key: "religion" }, { key: "culture" }, { key: "father" }] }, character_interaction: { sampled: 470, keys: [{ key: "category" }, { key: "icon" }, { key: "interface_priority", placeholder: "60" }, { key: "common_interaction", choices: ["yes", "no"] }, { key: "desc" }, { key: "is_shown", block: [] }, { key: "auto_accept", choices: ["yes", "no"] }, { key: "is_valid_showing_failures_only", block: [] }, { key: "on_accept", block: [] }, { key: "ai_targets", block: [{ key: "ai_recipients" }] }, { key: "ai_frequency_by_tier", block: [{ key: "barony", choices: ["0", "72", "120", "180", "36", "60"] }, { key: "county", placeholder: "0" }, { key: "duchy", placeholder: "36" }, { key: "kingdom", placeholder: "12" }, { key: "empire", placeholder: "12" }, { key: "hegemony", placeholder: "0" }] }, { key: "ai_potential", block: [] }, { key: "ai_will_do", block: [{ key: "base" }, { key: "modifier", block: [] }] }], blocks: { ai_frequency_by_tier: { sampled: 271, keys: [{ key: "barony", choices: ["0", "72", "120", "180", "36", "60"] }, { key: "county", placeholder: "0" }, { key: "duchy", placeholder: "36" }, { key: "kingdom", placeholder: "12" }, { key: "empire", placeholder: "12" }, { key: "hegemony", placeholder: "0" }] }, ai_targets: { sampled: 389, keys: [{ key: "ai_recipients" }] }, ai_will_do: { sampled: 297, keys: [{ key: "base" }, { key: "modifier", block: [{ key: "add" }] }] } } }, character_interaction_category: { sampled: 15, keys: [{ key: "index", placeholder: "0" }, { key: "desc" }, { key: "color", block: [] }] }, character_memory_type: { sampled: 382, keys: [{ key: "categories", block: [] }, { key: "icon" }, { key: "description", block: [] }, { key: "second_perspective_description", block: [] }, { key: "third_perspective_description", block: [] }, { key: "participants", block: [] }, { key: "duration", block: [{ key: "years", choices: ["memory_default_duration", "100", "20"] }] }], blocks: { duration: { sampled: 382, keys: [{ key: "years", choices: ["memory_default_duration", "100", "20"] }] } } }, chronicle: { sampled: 33, keys: [{ key: "name", block: [{ key: "first_valid", block: [] }] }, { key: "description", block: [{ key: "first_valid", block: [] }] }, { key: "portrait_animation" }, { key: "properties", block: [] }, { key: "chapters", block: [{ key: "opening" }, { key: "motivation" }, { key: "famous_deed" }, { key: "extra_deed" }, { key: "conclusion" }] }], blocks: { chapters: { sampled: 33, keys: [{ key: "opening" }, { key: "motivation" }, { key: "famous_deed" }, { key: "extra_deed" }, { key: "conclusion" }] }, description: { sampled: 21, keys: [{ key: "first_valid", block: [{ key: "triggered_desc", block: [] }, { key: "desc" }] }] }, name: { sampled: 21, keys: [{ key: "first_valid", block: [{ key: "triggered_desc", block: [] }, { key: "desc" }] }] } } }, coat_of_arms: { sampled: 2995, keys: [{ key: "pattern" }, { key: "color1" }, { key: "color2" }, { key: "colored_emblem", block: [{ key: "texture" }, { key: "color1" }, { key: "color2" }, { key: "instance", block: [] }] }], blocks: { colored_emblem: { sampled: 4823, keys: [{ key: "texture" }, { key: "color1" }, { key: "color2" }, { key: "instance", block: [{ key: "position", block: [] }, { key: "scale", block: [] }] }] } } }, combat_effect: { sampled: 31, keys: [{ key: "advantage", placeholder: "-10" }, { key: "image", choices: ["owner_in_debt"] }] }, combat_phase_event: { sampled: 13, keys: [{ key: "type", choices: ["knight", "commander"] }, { key: "is_valid", block: [] }, { key: "chance", block: [{ key: "base", placeholder: "30" }, { key: "modifier", block: [] }] }, { key: "effect", block: [{ key: "save_scope_as", choices: ["knight", "commander", "acclaimed_knight"] }, { key: "if", block: [] }, { key: "else", block: [] }] }], blocks: { chance: { sampled: 13, keys: [{ key: "base", placeholder: "30" }, { key: "modifier", block: [{ key: "factor" }] }] }, effect: { sampled: 11, keys: [{ key: "save_scope_as", choices: ["knight", "commander", "acclaimed_knight"] }, { key: "if", block: [{ key: "limit", block: [] }] }, { key: "else", block: [] }] } } }, council_position: { sampled: 15, keys: [{ key: "skill", choices: ["diplomacy", "learning", "martial", "stewardship", "intrigue"] }, { key: "name", choices: ["councillor_kurultai", "councillor_vizier", "minister_grand_marshal", "minister_justice", "minister_personnel", "minister_works"] }, { key: "tooltip", choices: ["game_concept_kurultai_desc", "councillor_vizier_desc", "game_concept_minister_grand_marshal_desc", "game_concept_minister_of_justice_desc", "game_concept_minister_of_personnel_desc", "game_concept_minister_of_works_desc", "game_concept_spouse_desc"] }, { key: "auto_fill", block: [] }, { key: "valid_position", block: [] }, { key: "modifier", block: [{ key: "name" }, { key: "scale", choices: ["council_scaled_by_liege_tier", "council_scaled_monthly_income", "council_scaled_admin_value", "council_scaled_by_liege_tier_nomad", "council_scaled_by_liege_tier_not_nomad", "council_scaled_celestial_ministry_value", "council_scaled_by_liege_tier_not_admin", "council_scaled_celestial_ministry_favored_value"] }] }, { key: "council_owner_modifier", block: [{ key: "name", choices: ["learn_on_the_job_modifier", "reliable_house_modifier"] }, { key: "scale" }] }, { key: "valid_character", block: [{ key: "exists", choices: ["root.liege_or_court_owner", "liege", "liege_or_court_owner"] }] }, { key: "on_get_position", block: [{ key: "got_council_position_effect", choices: ["yes"] }, { key: "got_minister_position_effect", block: [] }] }, { key: "on_fired_from_position", block: [{ key: "fired_from_council_position_effect", choices: ["yes"] }] }, { key: "on_lose_position", block: [{ key: "fired_minister_position_effect", choices: ["yes"] }] }, { key: "portrait_animation" }, { key: "barbershop_data", block: [{ key: "position", block: [] }, { key: "click_to_front", choices: ["no", "yes"] }] }], blocks: { barbershop_data: { sampled: 15, keys: [{ key: "position", block: [] }, { key: "click_to_front", choices: ["no", "yes"] }] }, council_owner_modifier: { sampled: 34, keys: [{ key: "name", choices: ["learn_on_the_job_modifier", "reliable_house_modifier"] }, { key: "scale" }] }, modifier: { sampled: 45, keys: [{ key: "name" }, { key: "scale", choices: ["council_scaled_by_liege_tier", "council_scaled_monthly_income", "council_scaled_admin_value", "council_scaled_by_liege_tier_nomad", "council_scaled_by_liege_tier_not_nomad", "council_scaled_celestial_ministry_value", "council_scaled_by_liege_tier_not_admin", "council_scaled_celestial_ministry_favored_value"] }] }, on_fired_from_position: { sampled: 15, keys: [{ key: "fired_from_council_position_effect", choices: ["yes"] }] }, on_get_position: { sampled: 15, keys: [{ key: "got_council_position_effect", choices: ["yes"] }, { key: "got_minister_position_effect", block: [{ key: "MINISTER_TITLE" }, { key: "MINISTER_POSITION" }] }] }, on_lose_position: { sampled: 11, keys: [{ key: "fired_minister_position_effect", choices: ["yes"] }] }, valid_character: { sampled: 15, keys: [{ key: "exists", choices: ["root.liege_or_court_owner", "liege", "liege_or_court_owner"] }] } } }, council_task: { sampled: 72, keys: [{ key: "position" }, { key: "task_type", choices: ["task_type_general", "task_type_county", "task_type_court"] }, { key: "task_progress", choices: ["task_progress_infinite", "task_progress_value", "task_progress_percentage"] }, { key: "asset", block: [{ key: "icon" }, { key: "background" }, { key: "frame" }, { key: "glow" }] }, { key: "effect_desc", block: [{ key: "desc" }, { key: "triggered_desc", block: [] }] }, { key: "council_owner_modifier", block: [{ key: "name" }, { key: "scale" }] }, { key: "is_valid_showing_failures_only", block: [{ key: "tgp_natural_disaster_councillor_available_for_task_trigger", choices: ["yes"] }] }, { key: "monthly_on_action" }, { key: "ai_will_do", block: [{ key: "value", choices: ["0", "1", "500", "1000", "100", "250", "10", "2"] }, { key: "if", block: [] }] }], blocks: { ai_will_do: { sampled: 67, keys: [{ key: "value", choices: ["0", "1", "500", "1000", "100", "250", "10", "2"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add" }] }] }, asset: { sampled: 56, keys: [{ key: "icon" }, { key: "background" }, { key: "frame" }, { key: "glow" }] }, council_owner_modifier: { sampled: 84, keys: [{ key: "name" }, { key: "scale" }] }, effect_desc: { sampled: 55, keys: [{ key: "desc" }, { key: "triggered_desc", block: [{ key: "trigger", block: [] }, { key: "desc" }] }] }, is_valid_showing_failures_only: { sampled: 40, keys: [{ key: "tgp_natural_disaster_councillor_available_for_task_trigger", choices: ["yes"] }] } } }, court_position: { sampled: 81, keys: [{ key: "sort_order", placeholder: "1200" }, { key: "max_available_positions", choices: ["1", "2", "3"] }, { key: "skill", choices: ["learning", "diplomacy", "martial", "stewardship", "prowess", "intrigue"] }, { key: "court_position_asset", block: [{ key: "trigger", block: [] }, { key: "animation" }, { key: "background" }] }, { key: "opinion", block: [{ key: "value", choices: ["regular_court_position_opinion", "regular_camp_officer_opinion", "high_camp_officer_opinion", "ceremonial_court_position_opinion", "10", "-5", "20", "court_jester_position_opinion"] }] }, { key: "aptitude_level_breakpoints", block: [] }, { key: "aptitude", block: [{ key: "value", choices: ["1", "0", "25", "10", "15", "40"] }, { key: "add", choices: ["general_aptitude_bonus", "court_position_aptitude_high_penalty_value", "court_position_aptitude_low_penalty_value", "general_aptitude_bonus_exclude_other_court_position", "aptitude_commander_trait_value", "kurultai_task_value"] }, { key: "if", block: [] }] }, { key: "is_shown", block: [] }, { key: "valid_position", block: [] }, { key: "is_shown_character", block: [] }, { key: "valid_character", block: [] }, { key: "revoke_cost", block: [{ key: "prestige", block: [] }] }, { key: "salary", block: [{ key: "gold", block: [] }, { key: "treasury", block: [] }, { key: "prestige", block: [] }, { key: "round", choices: ["no"] }] }, { key: "scaling_employer_modifiers", block: [{ key: "terrible", block: [] }, { key: "poor", block: [] }, { key: "average", block: [] }, { key: "good", block: [] }, { key: "excellent", block: [] }] }, { key: "received_salary", block: [{ key: "gold", block: [] }, { key: "prestige", block: [] }, { key: "round", choices: ["no"] }] }, { key: "modifier", block: [] }, { key: "on_court_position_received", block: [] }, { key: "on_court_position_revoked", block: [] }, { key: "on_court_position_invalidated", block: [] }, { key: "on_court_position_vacated", block: [{ key: "court_position_vacated_event_effect", block: [] }] }, { key: "ai_candidate_score", block: [{ key: "value" }, { key: "add", choices: ["court_position_candidate_score_base_value", "court_position_candidate_aptitude_value", "scope:base_value", "adjust_court_position_score_for_unity", "court_position_debt_considerations_value"] }, { key: "if", block: [] }] }, { key: "ai_position_score", block: [{ key: "value" }, { key: "add", choices: ["court_position_debt_considerations_value", "court_position_seneschal_debt_considerations_value"] }] }], blocks: { ai_candidate_score: { sampled: 81, keys: [{ key: "value" }, { key: "add", choices: ["court_position_candidate_score_base_value", "court_position_candidate_aptitude_value", "scope:base_value", "adjust_court_position_score_for_unity", "court_position_debt_considerations_value"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", choices: ["1000", "100", "200"] }] }] }, ai_position_score: { sampled: 73, keys: [{ key: "value" }, { key: "add", choices: ["court_position_debt_considerations_value", "court_position_seneschal_debt_considerations_value"] }] }, aptitude: { sampled: 81, keys: [{ key: "value", choices: ["1", "0", "25", "10", "15", "40"] }, { key: "add", choices: ["general_aptitude_bonus", "court_position_aptitude_high_penalty_value", "court_position_aptitude_low_penalty_value", "general_aptitude_bonus_exclude_other_court_position", "aptitude_commander_trait_value", "kurultai_task_value"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", block: [] }] }] }, court_position_asset: { sampled: 164, keys: [{ key: "trigger", block: [] }, { key: "animation" }, { key: "background" }] }, on_court_position_vacated: { sampled: 71, keys: [{ key: "court_position_vacated_event_effect", block: [{ key: "COURT_POSITION_TYPE" }] }] }, opinion: { sampled: 81, keys: [{ key: "value", choices: ["regular_court_position_opinion", "regular_camp_officer_opinion", "high_camp_officer_opinion", "ceremonial_court_position_opinion", "10", "-5", "20", "court_jester_position_opinion"] }] }, received_salary: { sampled: 53, keys: [{ key: "gold", block: [{ key: "value" }] }, { key: "prestige", block: [{ key: "value" }] }, { key: "round", choices: ["no"] }] }, revoke_cost: { sampled: 81, keys: [{ key: "prestige", block: [{ key: "value", choices: ["major_court_position_prestige_revoke_cost", "minor_court_position_prestige_revoke_cost"] }, { key: "if", block: [] }] }] }, salary: { sampled: 81, keys: [{ key: "gold", block: [{ key: "value", choices: ["0"] }, { key: "if", block: [] }] }, { key: "treasury", block: [{ key: "value", choices: ["0"] }, { key: "if", block: [] }] }, { key: "prestige", block: [{ key: "value" }] }, { key: "round", choices: ["no"] }] }, scaling_employer_modifiers: { sampled: 78, keys: [{ key: "terrible", block: [] }, { key: "poor", block: [] }, { key: "average", block: [] }, { key: "good", block: [] }, { key: "excellent", block: [] }] } } }, court_position_task: { sampled: 85, keys: [{ key: "court_position_types", block: [] }, { key: "cost", block: [{ key: "round", choices: ["no"] }, { key: "gold", block: [] }, { key: "treasury", block: [] }] }, { key: "scaling_employer_modifiers", block: [{ key: "terrible", block: [] }, { key: "poor", block: [] }, { key: "average", block: [] }, { key: "good", block: [] }, { key: "excellent", block: [] }] }, { key: "on_start", block: [] }, { key: "ai_will_do", block: [{ key: "value" }, { key: "if", block: [] }] }], blocks: { ai_will_do: { sampled: 85, keys: [{ key: "value" }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add" }] }] }, cost: { sampled: 83, keys: [{ key: "round", choices: ["no"] }, { key: "gold", block: [{ key: "value", choices: ["0"] }, { key: "if", block: [] }] }, { key: "treasury", block: [{ key: "value", choices: ["0"] }, { key: "if", block: [] }] }] }, scaling_employer_modifiers: { sampled: 55, keys: [{ key: "terrible", block: [] }, { key: "poor", block: [] }, { key: "average", block: [] }, { key: "good", block: [] }, { key: "excellent", block: [] }] } } }, court_scene_culture: { sampled: 10, keys: [{ key: "trigger", block: [{ key: "NOT", block: [] }, { key: "capital_county", block: [] }, { key: "trigger_if", block: [] }] }], blocks: { trigger: { sampled: 10, keys: [{ key: "NOT", block: [{ key: "government_has_flag", choices: ["government_is_nomadic"] }] }, { key: "capital_county", block: [{ key: "OR", block: [] }] }, { key: "trigger_if", block: [{ key: "limit", block: [] }, { key: "NOT", block: [] }] }] } } }, court_scene_role: { sampled: 41, keys: [{ key: "effect", block: [] }, { key: "scripted_animation", block: [{ key: "triggered_animation", block: [] }] }], blocks: { scripted_animation: { sampled: 35, keys: [{ key: "triggered_animation", block: [{ key: "trigger", block: [] }, { key: "animation", block: [] }] }] } } }, culture: { sampled: 244, keys: [{ key: "color", block: [] }, { key: "ethos", choices: ["ethos_communal", "ethos_bellicose", "ethos_stoic", "ethos_spiritual", "ethos_courtly", "ethos_egalitarian", "ethos_bureaucratic"] }, { key: "heritage" }, { key: "language" }, { key: "martial_custom", choices: ["martial_custom_male_only", "martial_custom_equal"] }, { key: "head_determination", choices: ["head_determination_domain", "head_determination_herd"] }, { key: "traditions", block: [] }, { key: "name_list" }, { key: "coa_gfx", block: [] }, { key: "building_gfx", block: [] }, { key: "clothing_gfx", block: [] }, { key: "unit_gfx", block: [] }, { key: "house_coa_frame" }, { key: "house_coa_mask_offset", block: [] }, { key: "house_coa_mask_scale", block: [] }, { key: "ethnicities", block: [{ key: "100" }] }], blocks: { ethnicities: { sampled: 244, keys: [{ key: "100" }] } } }, culture_creation_name: { sampled: 137, keys: [{ key: "trigger", block: [{ key: "OR", block: [] }, { key: "any_sub_realm_county", block: [] }] }], blocks: { trigger: { sampled: 137, keys: [{ key: "OR", block: [{ key: "capital_county", block: [] }] }, { key: "any_sub_realm_county", block: [{ key: "OR", block: [] }] }] } } }, culture_pillar: { sampled: 162, keys: [{ key: "type", choices: ["language", "heritage", "ethos", "martial_custom", "head_determination"] }, { key: "is_shown", block: [{ key: "language_is_shown_trigger", block: [] }] }, { key: "ai_will_do", block: [{ key: "value", choices: ["10", "1", "0"] }, { key: "if", block: [] }] }, { key: "color" }], blocks: { ai_will_do: { sampled: 101, keys: [{ key: "value", choices: ["10", "1", "0"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "multiply", choices: ["10", "2", "0"] }] }] }, is_shown: { sampled: 150, keys: [{ key: "language_is_shown_trigger", block: [{ key: "LANGUAGE" }] }] } } }, culture_tradition: { sampled: 198, keys: [{ key: "category", choices: ["regional", "realm", "societal", "combat", "ritual"] }, { key: "layers", block: [{ key: "0", choices: ["martial", "diplo", "steward", "intrigue", "learning"] }, { key: "1", choices: ["mena", "mediterranean", "western", "indian", "asian", "steppe"] }, { key: "4" }] }, { key: "is_shown", block: [] }, { key: "can_pick", block: [] }, { key: "parameters", block: [] }, { key: "character_modifier", block: [] }, { key: "cost", block: [{ key: "prestige", block: [] }] }, { key: "ai_will_do", block: [{ key: "value", placeholder: "100" }, { key: "if", block: [] }] }], blocks: { ai_will_do: { sampled: 195, keys: [{ key: "value", placeholder: "100" }, { key: "if", block: [{ key: "limit", block: [] }, { key: "multiply" }] }] }, cost: { sampled: 197, keys: [{ key: "prestige", block: [{ key: "add", block: [] }, { key: "if", block: [] }, { key: "multiply", choices: ["tradition_replacement_cost_if_relevant"] }] }] }, layers: { sampled: 199, keys: [{ key: "0", choices: ["martial", "diplo", "steward", "intrigue", "learning"] }, { key: "1", choices: ["mena", "mediterranean", "western", "indian", "asian", "steppe"] }, { key: "4" }] } } }, customizable_localization: { sampled: 2651, keys: [{ key: "type" }, { key: "text", block: [{ key: "trigger", block: [] }, { key: "localization_key" }] }], blocks: { text: { sampled: 17486, keys: [{ key: "trigger", block: [] }, { key: "localization_key" }] } } }, death_reason: { sampled: 313, keys: [{ key: "public_knowledge", choices: ["yes"] }, { key: "icon", choices: ["death_murder.dds", "death_natural.dds", "death_disease.dds", "death_unknown.dds"] }] }, decision: { sampled: 431, keys: [{ key: "picture", block: [{ key: "reference" }] }, { key: "decision_group_type" }, { key: "desc" }, { key: "ai_check_interval_by_tier", block: [{ key: "barony", choices: ["0"] }, { key: "county", placeholder: "0" }, { key: "duchy", placeholder: "0" }, { key: "kingdom", placeholder: "120" }, { key: "empire", placeholder: "120" }, { key: "hegemony", placeholder: "0" }] }, { key: "selection_tooltip" }, { key: "is_shown", block: [] }, { key: "is_valid", block: [] }, { key: "is_valid_showing_failures_only", block: [] }, { key: "effect", block: [] }, { key: "cost", block: [{ key: "prestige" }] }, { key: "ai_potential", block: [] }, { key: "ai_will_do", block: [{ key: "base", placeholder: "100" }] }], blocks: { ai_check_interval_by_tier: { sampled: 353, keys: [{ key: "barony", choices: ["0"] }, { key: "county", placeholder: "0" }, { key: "duchy", placeholder: "0" }, { key: "kingdom", placeholder: "120" }, { key: "empire", placeholder: "120" }, { key: "hegemony", placeholder: "0" }] }, ai_will_do: { sampled: 393, keys: [{ key: "base", placeholder: "100" }] }, cost: { sampled: 264, keys: [{ key: "prestige" }] }, picture: { sampled: 526, keys: [{ key: "reference" }] } } }, decision_group_type: { sampled: 17, keys: [{ key: "sort_order", placeholder: "50" }, { key: "gui_tags", block: [] }] }, doctrine: { sampled: 183, keys: [{ key: "icon" }, { key: "piety_cost", block: [{ key: "value", choices: ["faith_doctrine_cost_mid", "faith_doctrine_cost_low", "faith_doctrine_cost_high", "faith_tenet_cost_low", "faith_tenet_cost_mid", "faith_doctrine_cost_massive", "faith_tenet_cost_high", "faith_tenet_cost_massive"] }, { key: "if", block: [] }, { key: "else_if", block: [] }] }, { key: "parameters", block: [] }], blocks: { piety_cost: { sampled: 157, keys: [{ key: "value", choices: ["faith_doctrine_cost_mid", "faith_doctrine_cost_low", "faith_doctrine_cost_high", "faith_tenet_cost_low", "faith_tenet_cost_mid", "faith_doctrine_cost_massive", "faith_tenet_cost_high", "faith_tenet_cost_massive"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "multiply", choices: ["faith_unchanged_doctrine_cost_mult", "0", "1.5", "3", "faith_changed_doctrine_cost_mult_three_step", "faith_tenet_discount_mountain_background_value"] }] }, { key: "else_if", block: [{ key: "limit", block: [] }, { key: "value", choices: ["faith_tenet_cost_high", "faith_tenet_cost_low", "faith_tenet_cost_mid", "faith_tenet_cost_massive"] }] }] } } }, doctrine_group: { sampled: 44, keys: [{ key: "category", choices: ["special", "main_group", "clergy", "crimes", "marriage", "not_creatable", "core_tenets"] }, { key: "doctrine_types", block: [] }] }, domicile_building: { sampled: 1620, keys: [{ key: "construction_time" }, { key: "allowed_domicile_types", block: [] }, { key: "slot_type", choices: ["internal", "main"] }, { key: "previous_building" }, { key: "can_construct", block: [{ key: "domicile", block: [] }] }, { key: "cost", block: [{ key: "gold", block: [] }] }, { key: "character_modifier", block: [] }, { key: "parameters", block: [] }, { key: "ai_value", block: [{ key: "value" }, { key: "add", choices: ["estate_building_ai_modifier_value", "japanese_manor_building_ai_modifier_value"] }] }, { key: "asset", block: [{ key: "icon" }, { key: "texture" }, { key: "intersectionmask_texture" }, { key: "soundeffect" }] }], blocks: { ai_value: { sampled: 1620, keys: [{ key: "value" }, { key: "add", choices: ["estate_building_ai_modifier_value", "japanese_manor_building_ai_modifier_value"] }] }, asset: { sampled: 2153, keys: [{ key: "icon" }, { key: "texture" }, { key: "intersectionmask_texture" }, { key: "soundeffect" }] }, can_construct: { sampled: 1068, keys: [{ key: "domicile", block: [{ key: "has_domicile_building_or_higher" }] }] }, cost: { sampled: 1619, keys: [{ key: "gold", block: [{ key: "value" }] }] } } }, dynasty: { sampled: 10338, keys: [{ key: "name" }, { key: "culture" }] }, dynasty_house: { sampled: 558, keys: [{ key: "name" }, { key: "dynasty" }] }, dynasty_legacy: { sampled: 21, keys: [{ key: "is_shown", block: [{ key: "has_dlc_feature" }, { key: "OR", block: [] }] }], blocks: { is_shown: { sampled: 14, keys: [{ key: "has_dlc_feature" }, { key: "OR", block: [{ key: "has_game_rule", choices: ["unrestricted_dynasty_legacies_all"] }, { key: "AND", block: [] }, { key: "dynasty", block: [] }, { key: "government_has_flag", choices: ["government_has_merit", "government_is_administrative", "government_is_japan_administrative", "government_is_japan_feudal", "government_is_mandala", "government_is_nomadic", "government_is_wanua"] }] }] } } }, dynasty_perk: { sampled: 105, keys: [{ key: "legacy" }, { key: "can_be_picked", block: [] }, { key: "effect", block: [{ key: "custom_description_no_bullet", block: [] }] }, { key: "character_modifier", block: [] }], blocks: { effect: { sampled: 82, keys: [{ key: "custom_description_no_bullet", block: [{ key: "text" }] }] } } }, effect_localization: { sampled: 989, keys: [{ key: "global" }, { key: "first" }, { key: "third" }] }, event: { sampled: 9791, keys: [{ key: "type", choices: ["character_event", "activity_event", "letter_event", "court_event"] }, { key: "title" }, { key: "desc" }, { key: "theme" }, { key: "left_portrait", block: [{ key: "character" }, { key: "animation" }] }, { key: "right_portrait", block: [{ key: "character" }, { key: "animation" }] }, { key: "trigger", block: [] }, { key: "immediate", block: [] }, { key: "option", block: [{ key: "name" }, { key: "ai_chance", block: [] }] }], nameFromHeader: "namespace", blocks: { left_portrait: { sampled: 7009, keys: [{ key: "character" }, { key: "animation" }] }, option: { sampled: 21957, keys: [{ key: "name" }, { key: "ai_chance", block: [{ key: "base" }] }] }, right_portrait: { sampled: 5097, keys: [{ key: "character" }, { key: "animation" }] } } }, event_background: { sampled: 298, keys: [{ key: "background", block: [{ key: "trigger", block: [] }, { key: "reference" }, { key: "environment" }, { key: "ambience" }] }], blocks: { background: { sampled: 1253, keys: [{ key: "trigger", block: [] }, { key: "reference" }, { key: "environment" }, { key: "ambience" }] } } }, event_theme: { sampled: 191, keys: [{ key: "icon", block: [{ key: "reference" }] }, { key: "header_background", block: [{ key: "reference" }] }, { key: "sound", block: [{ key: "reference" }] }, { key: "background", block: [{ key: "reference" }] }], blocks: { background: { sampled: 239, keys: [{ key: "reference" }] }, header_background: { sampled: 142, keys: [{ key: "reference" }] }, icon: { sampled: 204, keys: [{ key: "reference" }] }, sound: { sampled: 197, keys: [{ key: "reference" }] } } }, event_transition: { sampled: 33, keys: [{ key: "transition", block: [{ key: "reference" }, { key: "duration", choices: ["7", "5"] }] }], blocks: { transition: { sampled: 33, keys: [{ key: "reference" }, { key: "duration", choices: ["7", "5"] }] } } }, faction: { sampled: 12, keys: [{ key: "casus_belli" }, { key: "short_effect_desc", choices: ["claimant_faction_short_effect_desc", "escalated_peasant_faction_short_effect_desc", "imperial_policy_faction_short_effect_desc", "independence_faction_short_effect_desc", "nation_fracturing_faction_short_effect_desc", "nomadic_faction_short_effect_desc", "peasant_faction_short_effect_desc", "restore_ceremonial_liege_faction_short_effect_desc"] }, { key: "sort_order", choices: ["4", "3", "1", "0", "2", "5"] }, { key: "name", choices: ["FACTION_CEREMONIAL_CLAIMANT_DYNAMIC_NAME", "FACTION_CLAMAINT_DYNAMIC_NAME", "FACTION_ESCALATED_PEASANT_DYNAMIC_NAME", "FACTION_JAPANESE_REPLACE_REGENT_NAME_DYNAMIC", "FACTION_JAPANESE_RESTORE_EMPEROR_NAME_DYNAMIC", "FACTION_NOMAD_DYNAMIC_NAME", "FACTION_PEASANT_NAME", "FACTION_POPULIST_DYNAMIC_NAME"] }, { key: "discontent_progress", block: [{ key: "base" }, { key: "common_discontent_progress_modifier", choices: ["yes"] }] }, { key: "is_shown", block: [{ key: "NAND", block: [] }] }, { key: "power_threshold", block: [{ key: "base", choices: ["80"] }, { key: "modifier", block: [] }, { key: "dynamic_power_threshold_scripted_modifier", block: [] }] }, { key: "demand", block: [{ key: "save_scope_as", choices: ["faction"] }, { key: "faction_leader", block: [] }, { key: "faction_target", block: [] }, { key: "every_faction_member", block: [] }] }, { key: "is_valid", block: [{ key: "trigger_if", block: [] }] }, { key: "ai_demand_chance", block: [{ key: "base", choices: ["0", "100"] }, { key: "modifier", block: [] }, { key: "compare_modifier", block: [] }] }, { key: "is_character_valid", block: [{ key: "common_character_validity_trigger", block: [] }, { key: "has_valid_faction_members_trigger", choices: ["yes"] }] }, { key: "can_character_create_ui", block: [{ key: "base_faction_trigger", block: [] }, { key: "common_can_character_create_trigger", block: [] }, { key: "japan_faction_cohesion_trigger", choices: ["yes"] }] }, { key: "on_war_start", block: [{ key: "every_faction_member", block: [] }] }, { key: "is_county_valid", block: [{ key: "title_province", block: [] }] }, { key: "can_character_join", block: [{ key: "common_can_character_join_trigger", block: [] }] }, { key: "can_county_join", block: [{ key: "title_province", block: [] }] }, { key: "can_character_become_leader", block: [{ key: "can_become_leader_of_faction_trigger", choices: ["yes"] }] }, { key: "can_character_create", block: [{ key: "common_can_character_create_trigger", block: [] }, { key: "trigger_if", block: [] }] }, { key: "county_join_score", block: [{ key: "base", choices: ["0", "-80", "-120"] }, { key: "compare_modifier", block: [] }, { key: "modifier", block: [] }, { key: "legalism_virtue_and_sin_modifier", block: [] }] }, { key: "ai_join_score", block: [{ key: "base", choices: ["0", "-25", "-150"] }, { key: "common_join_faction_blockers", block: [] }, { key: "common_faction_modifiers", block: [] }, { key: "struggle_faction_modifiers", choices: ["yes"] }, { key: "modifier", block: [] }] }, { key: "ai_create_score", block: [{ key: "base", choices: ["0", "-25", "-10000", "-175", "-200"] }, { key: "common_create_faction_blockers", block: [] }, { key: "common_faction_modifiers", block: [] }, { key: "modifier", block: [] }] }, { key: "county_allow_join", choices: ["no", "yes"] }, { key: "county_power", choices: ["county_levies_to_raise", "county_horde_riders_to_raise_power"] }, { key: "on_creation", block: [{ key: "save_scope_as", choices: ["faction"] }, { key: "tgp_bloc_members_join_faction_effect", choices: ["yes"] }, { key: "if", block: [] }] }, { key: "county_allow_create", choices: ["no"] }, { key: "character_allow_create", choices: ["no", "yes"] }, { key: "special_character_title", choices: ["FACTIONS_WINDOW_LEADER", "FACTIONS_WINDOW_CLAIMANT", "FACTIONS_WINDOW_JAPANESE_REGENT", "FACTIONS_WINDOW_JAPANESE_RESTORE_EMPEROR"] }, { key: "multiple_targeting", choices: ["yes", "no"] }], blocks: { ai_demand_chance: { sampled: 12, keys: [{ key: "base", choices: ["0", "100"] }, { key: "modifier", block: [{ key: "add", choices: ["-1000", "-75", "100", "-50", "-500"] }, { key: "faction_target", block: [] }] }, { key: "compare_modifier", block: [{ key: "value", choices: ["faction_power"] }, { key: "trigger", block: [] }, { key: "multiplier", choices: ["0.375", "0.5", "0.75", "1"] }] }] }, ai_join_score: { sampled: 12, keys: [{ key: "base", choices: ["0", "-25", "-150"] }, { key: "common_join_faction_blockers", block: [{ key: "FACTION_TARGET", choices: ["scope:faction.faction_target"] }] }, { key: "common_faction_modifiers", block: [{ key: "FACTION_TARGET", choices: ["scope:faction.faction_target"] }, { key: "OPINION_MULTIPLIER", choices: ["-1", "-0.4", "-2"] }, { key: "MAX_OPINION", choices: ["0", "100"] }, { key: "POWER", choices: ["scope:faction.faction_power"] }, { key: "THRESHOLD", choices: ["scope:faction.faction_power_threshold"] }] }, { key: "struggle_faction_modifiers", choices: ["yes"] }, { key: "modifier", block: [{ key: "desc" }, { key: "add", placeholder: "25" }] }] }, can_character_become_leader: { sampled: 12, keys: [{ key: "can_become_leader_of_faction_trigger", choices: ["yes"] }] }, can_character_join: { sampled: 12, keys: [{ key: "common_can_character_join_trigger", block: [{ key: "FACTION_TARGET", choices: ["scope:faction.faction_target"] }] }] }, demand: { sampled: 12, keys: [{ key: "save_scope_as", choices: ["faction"] }, { key: "faction_leader", block: [{ key: "save_scope_as", choices: ["faction_leader"] }] }, { key: "faction_target", block: [{ key: "save_scope_as", choices: ["faction_target"] }, { key: "trigger_event", block: [] }] }, { key: "every_faction_member", block: [{ key: "limit", block: [] }, { key: "trigger_event", choices: ["faction_demand.0005", "faction_demand.0105", "faction_demand.0225", "faction_demand.1005", "faction_demand.2005", "faction_demand.2015", "tgp_faction_events.0105", "tgp_faction_events.0205"] }] }] }, discontent_progress: { sampled: 12, keys: [{ key: "base" }, { key: "common_discontent_progress_modifier", choices: ["yes"] }] }, is_character_valid: { sampled: 11, keys: [{ key: "common_character_validity_trigger", block: [{ key: "FACTION_TARGET", choices: ["scope:faction.faction_target"] }] }, { key: "has_valid_faction_members_trigger", choices: ["yes"] }] }, on_creation: { sampled: 12, keys: [{ key: "save_scope_as", choices: ["faction"] }, { key: "tgp_bloc_members_join_faction_effect", choices: ["yes"] }, { key: "if", block: [{ key: "limit", block: [] }] }] }, on_war_start: { sampled: 10, keys: [{ key: "every_faction_member", block: [{ key: "limit", block: [] }, { key: "spawn_army", block: [] }] }] } } }, flavorization: { sampled: 1274, keys: [{ key: "type", choices: ["character", "title", "domicile"] }, { key: "gender", choices: ["male", "female"] }, { key: "special", choices: ["holder", "ruler_child", "domicile", "queen_mother", "head_of_faith", "councillor"] }, { key: "tier", choices: ["duchy", "kingdom", "county", "empire", "barony", "hegemony"] }, { key: "priority", placeholder: "47" }, { key: "governments", block: [] }, { key: "flavourization_rules", block: [{ key: "top_liege", choices: ["no", "yes"] }] }], blocks: { flavourization_rules: { sampled: 1057, keys: [{ key: "top_liege", choices: ["no", "yes"] }] } } }, focus: { sampled: 28, keys: [{ key: "lifestyle", choices: ["diplomacy_lifestyle", "intrigue_lifestyle", "learning_lifestyle", "martial_lifestyle", "stewardship_lifestyle", "wanderer_lifestyle"] }, { key: "is_shown", block: [{ key: "NOT", block: [] }] }, { key: "is_valid", block: [{ key: "NOT", block: [] }] }, { key: "desc", block: [{ key: "desc" }] }, { key: "modifier", block: [] }, { key: "auto_selection_weight", block: [{ key: "value", choices: ["11", "100", "5000", "0"] }, { key: "if", block: [] }] }], blocks: { auto_selection_weight: { sampled: 28, keys: [{ key: "value", choices: ["11", "100", "5000", "0"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "multiply", choices: ["0", "2", "5", "0.1", "0.2", "1.5", "3", "7"] }] }] }, desc: { sampled: 28, keys: [{ key: "desc" }] }, is_shown: { sampled: 21, keys: [{ key: "NOT", block: [{ key: "government_has_flag", choices: ["government_is_landless_adventurer"] }] }] }, is_valid: { sampled: 21, keys: [{ key: "NOT", block: [{ key: "government_has_flag", choices: ["government_is_landless_adventurer"] }] }] } } }, game_concept: { sampled: 1047, keys: [{ key: "texture" }, { key: "alias", block: [] }, { key: "parent" }] }, game_rule: { sampled: 81, keys: [{ key: "categories", block: [] }, { key: "default" }] }, government: { sampled: 18, keys: [{ key: "government_rules", block: [{ key: "create_cadet_branches", choices: ["yes", "no"] }, { key: "rulers_should_have_dynasty", choices: ["yes", "no"] }, { key: "dynasty_named_realms", choices: ["no", "yes"] }, { key: "legitimacy", choices: ["yes"] }, { key: "use_as_base_on_landed", choices: ["yes"] }, { key: "inherit_from_dynastic_government", choices: ["no"] }, { key: "allow_accolades", choices: ["yes", "no"] }] }, { key: "royal_court", choices: ["any"] }, { key: "primary_holding", choices: ["castle_holding", "tribal_holding", "church_holding", "city_holding", "herder_holding", "nomad_holding", "temple_citadel_holding"] }, { key: "valid_holdings", block: [] }, { key: "required_county_holdings", block: [] }, { key: "ai", block: [{ key: "use_legends", choices: ["no", "yes"] }] }, { key: "vassal_contract_group" }, { key: "can_get_government", block: [{ key: "has_tgp_dlc_trigger", choices: ["yes"] }] }, { key: "mechanic_type" }, { key: "character_modifier", block: [{ key: "knight_limit", choices: ["-5", "2", "-100"] }, { key: "men_at_arms_limit", choices: ["-2"] }, { key: "vassal_limit", choices: ["20", "50", "100"] }, { key: "title_creation_cost_mult", choices: ["-0.5"] }] }, { key: "is_mechanic_type_default", choices: ["yes"] }, { key: "flags", block: [] }, { key: "color", block: [] }, { key: "realm_mask_offset", block: [] }, { key: "realm_mask_scale", block: [] }], blocks: { ai: { sampled: 11, keys: [{ key: "use_legends", choices: ["no", "yes"] }] }, can_get_government: { sampled: 10, keys: [{ key: "has_tgp_dlc_trigger", choices: ["yes"] }] }, character_modifier: { sampled: 12, keys: [{ key: "knight_limit", choices: ["-5", "2", "-100"] }, { key: "men_at_arms_limit", choices: ["-2"] }, { key: "vassal_limit", choices: ["20", "50", "100"] }, { key: "title_creation_cost_mult", choices: ["-0.5"] }] }, government_rules: { sampled: 18, keys: [{ key: "create_cadet_branches", choices: ["yes", "no"] }, { key: "rulers_should_have_dynasty", choices: ["yes", "no"] }, { key: "dynasty_named_realms", choices: ["no", "yes"] }, { key: "legitimacy", choices: ["yes"] }, { key: "use_as_base_on_landed", choices: ["yes"] }, { key: "inherit_from_dynastic_government", choices: ["no"] }, { key: "allow_accolades", choices: ["yes", "no"] }] } } }, great_project: { sampled: 20, keys: [{ key: "icon", block: [{ key: "reference" }] }, { key: "illustration", block: [{ key: "reference" }] }, { key: "name", block: [{ key: "desc" }] }, { key: "is_shown", block: [{ key: "has_tgp_dlc_trigger", choices: ["yes"] }, { key: "OR", block: [] }, { key: "NOT", block: [] }] }, { key: "can_start_planning", block: [{ key: "trigger_if", block: [] }] }, { key: "is_valid", block: [] }, { key: "cost", block: [{ key: "treasury_or_gold", block: [] }] }, { key: "construction_time", block: [{ key: "value", choices: ["great_project_base_construction_time", "1825", "3650"] }, { key: "multiply", choices: ["common_great_project_construction_time_multiplier_value", "7", "5"] }] }, { key: "contributor_cooldown", choices: ["standard_contributor_cooldown_value", "0"] }, { key: "allowed_contributor_filter", block: [{ key: "owner", choices: ["yes"] }, { key: "vassals", choices: ["yes"] }, { key: "tributaries", choices: ["yes"] }] }, { key: "on_complete", block: [] }, { key: "on_plan_build", block: [] }, { key: "on_start_build", block: [] }, { key: "on_cancel", block: [{ key: "every_contribution", block: [] }] }, { key: "project_contributions", block: [] }, { key: "ai_target_quick_trigger", block: [{ key: "adult", choices: ["yes"] }, { key: "rank", choices: ["empire", "county"] }] }, { key: "ai_check_interval_by_tier", block: [{ key: "barony", choices: ["0"] }, { key: "county", choices: ["0", "1"] }, { key: "duchy", choices: ["0", "1"] }, { key: "kingdom", choices: ["0", "1"] }, { key: "empire", choices: ["1", "10", "6", "0", "24", "5"] }, { key: "hegemony", choices: ["6", "1", "24", "3"] }] }, { key: "ai_will_do", block: [{ key: "value", choices: ["1000", "500", "30", "10", "100", "15"] }, { key: "if", block: [] }] }, { key: "completion_sound_effect" }], blocks: { ai_check_interval_by_tier: { sampled: 18, keys: [{ key: "barony", choices: ["0"] }, { key: "county", choices: ["0", "1"] }, { key: "duchy", choices: ["0", "1"] }, { key: "kingdom", choices: ["0", "1"] }, { key: "empire", choices: ["1", "10", "6", "0", "24", "5"] }, { key: "hegemony", choices: ["6", "1", "24", "3"] }] }, ai_target_quick_trigger: { sampled: 18, keys: [{ key: "adult", choices: ["yes"] }, { key: "rank", choices: ["empire", "county"] }] }, ai_will_do: { sampled: 18, keys: [{ key: "value", choices: ["1000", "500", "30", "10", "100", "15"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", placeholder: "10" }] }] }, allowed_contributor_filter: { sampled: 20, keys: [{ key: "owner", choices: ["yes"] }, { key: "vassals", choices: ["yes"] }, { key: "tributaries", choices: ["yes"] }] }, can_start_planning: { sampled: 20, keys: [{ key: "trigger_if", block: [{ key: "limit", block: [] }] }] }, construction_time: { sampled: 13, keys: [{ key: "value", choices: ["great_project_base_construction_time", "1825", "3650"] }, { key: "multiply", choices: ["common_great_project_construction_time_multiplier_value", "7", "5"] }] }, cost: { sampled: 18, keys: [{ key: "treasury_or_gold", block: [{ key: "value", choices: ["great_project_base_starting_cost", "great_project_base_contribution_cost"] }, { key: "multiply", choices: ["2", "0.2", "0.3", "1.5", "4"] }, { key: "if", block: [] }] }] }, icon: { sampled: 22, keys: [{ key: "reference" }] }, illustration: { sampled: 25, keys: [{ key: "reference" }] }, is_shown: { sampled: 20, keys: [{ key: "has_tgp_dlc_trigger", choices: ["yes"] }, { key: "OR", block: [{ key: "has_title", choices: ["title:h_china", "title:e_minister_of_works", "title:e_minister_grand_marshal", "title:e_minister_of_rites", "title:e_minister_of_war", "title:e_minister_of_justice", "title:e_minister_of_revenue"] }, { key: "AND", block: [] }] }, { key: "NOT", block: [{ key: "is_planning_great_project" }] }] }, name: { sampled: 18, keys: [{ key: "desc" }] }, on_cancel: { sampled: 11, keys: [{ key: "every_contribution", block: [{ key: "limit", block: [] }, { key: "contributor", block: [] }] }] } } }, guest_invite_rule: { sampled: 56, keys: [{ key: "effect", block: [] }] }, holy_site: { sampled: 326, keys: [{ key: "county" }, { key: "character_modifier", block: [{ key: "name" }] }], blocks: { character_modifier: { sampled: 321, keys: [{ key: "name" }] } } }, hook_type: { sampled: 44, keys: [{ key: "expiration_days", choices: ["3650", "7300", "-1", "1825", "7200"] }] }, house_aspiration: { sampled: 29, keys: [{ key: "show_in_main_hud", choices: ["yes"] }, { key: "is_shown", block: [{ key: "house_head", block: [] }] }, { key: "level", block: [{ key: "cost", block: [] }, { key: "powerful_family_member_modifier", block: [] }, { key: "any_house_member_modifier", block: [] }, { key: "parameters", block: [] }, { key: "ai_score", block: [] }] }, { key: "cooldown", block: [{ key: "years" }] }, { key: "illustration" }], blocks: { cooldown: { sampled: 28, keys: [{ key: "years" }] }, is_shown: { sampled: 29, keys: [{ key: "house_head", block: [{ key: "government_has_flag", choices: ["government_has_powerful_families", "government_is_mandala", "government_uses_merit_family_aspirations"] }] }] }, level: { sampled: 99, keys: [{ key: "cost", block: [{ key: "influence" }] }, { key: "powerful_family_member_modifier", block: [] }, { key: "any_house_member_modifier", block: [] }, { key: "parameters", block: [] }, { key: "ai_score", block: [{ key: "value" }] }] } } }, house_motto: { sampled: 74, keys: [{ key: "insert" }, { key: "weight", block: [{ key: "value", placeholder: "1500" }] }, { key: "trigger", block: [] }], blocks: { weight: { sampled: 74, keys: [{ key: "value", placeholder: "1500" }] } } }, house_motto_insert: { sampled: 23, keys: [] }, important_action: { sampled: 269, keys: [{ key: "check_create_action", block: [{ key: "if", block: [] }] }, { key: "effect", block: [] }], blocks: { check_create_action: { sampled: 269, keys: [{ key: "if", block: [{ key: "limit", block: [] }, { key: "try_create_important_action", block: [] }] }] } } }, innovation: { sampled: 108, keys: [{ key: "skill", choices: ["stewardship", "martial", "learning", "diplomacy", "intrigue"] }, { key: "group", choices: ["culture_group_civic", "culture_group_military"] }, { key: "culture_era", choices: ["culture_era_tribal", "culture_era_late_medieval", "culture_era_early_medieval", "culture_era_high_medieval"] }, { key: "icon" }, { key: "character_modifier", block: [] }, { key: "flag" }, { key: "ai_weight_for_fascination", block: [{ key: "value", choices: ["100"] }, { key: "if", block: [] }] }], blocks: { ai_weight_for_fascination: { sampled: 108, keys: [{ key: "value", choices: ["100"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "multiply", choices: ["0"] }] }] } } }, inspiration: { sampled: 11, keys: [{ key: "gold", block: [{ key: "value", choices: ["basic_fund_inspiration_cost"] }, { key: "if", block: [] }, { key: "round", choices: ["yes"] }] }, { key: "progress_chance", choices: ["75", "100", "adventure_progress_chance_svalue"] }, { key: "on_creation", block: [{ key: "hidden_effect", block: [] }] }, { key: "is_valid", block: [] }, { key: "is_sponsor_valid", block: [{ key: "ep1_is_sponsor_valid_inspiration_basic", choices: ["yes"] }] }, { key: "can_sponsor", block: [{ key: "ep1_can_sponsor_inspiration_basic", choices: ["yes"] }] }, { key: "on_monthly", block: [] }, { key: "on_complete", block: [] }, { key: "on_sponsor", block: [] }, { key: "on_owner_death", block: [{ key: "save_scope_value_as", block: [] }, { key: "if", block: [] }] }, { key: "on_sponsor_invalidated", block: [{ key: "save_scope_value_as", block: [] }, { key: "if", block: [] }] }], blocks: { on_owner_death: { sampled: 11, keys: [{ key: "save_scope_value_as", block: [{ key: "name" }, { key: "value", choices: ["yes"] }] }, { key: "if", block: [{ key: "limit", block: [] }] }] }, on_sponsor_invalidated: { sampled: 11, keys: [{ key: "save_scope_value_as", block: [{ key: "name" }, { key: "value", choices: ["yes"] }] }, { key: "if", block: [{ key: "limit", block: [] }] }] } } }, law_group: { sampled: 27, keys: [{ key: "default" }, { key: "cumulative", choices: ["no", "yes"] }, { key: "flag" }] }, legend_seed: { sampled: 38, keys: [{ key: "type", choices: ["legitimizing", "heroic", "holy"] }, { key: "quality", choices: ["famed"] }, { key: "is_shown", block: [{ key: "has_dlc_feature", choices: ["legends"] }, { key: "NOT", block: [] }] }, { key: "is_valid", block: [{ key: "is_playable_character", choices: ["yes"] }, { key: "prestige_level", choices: ["high_prestige_level", "medium_prestige_level", "very_high_prestige_level"] }] }, { key: "chronicle" }, { key: "chronicle_properties", block: [{ key: "title" }] }], blocks: { chronicle_properties: { sampled: 38, keys: [{ key: "title" }] }, is_shown: { sampled: 38, keys: [{ key: "has_dlc_feature", choices: ["legends"] }, { key: "NOT", block: [{ key: "has_global_variable" }] }] }, is_valid: { sampled: 38, keys: [{ key: "is_playable_character", choices: ["yes"] }, { key: "prestige_level", choices: ["high_prestige_level", "medium_prestige_level", "very_high_prestige_level"] }] } } }, men_at_arms: { sampled: 110, keys: [{ key: "type" }, { key: "damage", placeholder: "30" }, { key: "toughness", placeholder: "12" }, { key: "pursuit", placeholder: "0" }, { key: "screen", placeholder: "0" }, { key: "terrain_bonus", block: [{ key: "hills", block: [] }, { key: "mountains", block: [] }, { key: "desert_mountains", block: [] }] }, { key: "counters", block: [] }, { key: "can_recruit", block: [] }, { key: "buy_cost", block: [{ key: "gold" }] }, { key: "low_maintenance_cost", block: [{ key: "gold" }] }, { key: "high_maintenance_cost", block: [{ key: "gold" }] }, { key: "provision_cost" }, { key: "stack", choices: ["100", "50", "10", "25"] }, { key: "ai_quality", block: [{ key: "value" }] }, { key: "icon" }], blocks: { ai_quality: { sampled: 100, keys: [{ key: "value" }] }, buy_cost: { sampled: 109, keys: [{ key: "gold" }] }, high_maintenance_cost: { sampled: 109, keys: [{ key: "gold" }] }, low_maintenance_cost: { sampled: 109, keys: [{ key: "gold" }] }, terrain_bonus: { sampled: 90, keys: [{ key: "hills", block: [{ key: "damage", placeholder: "10" }, { key: "toughness", choices: ["4", "6", "8", "10", "5", "16", "20", "3"] }] }, { key: "mountains", block: [{ key: "damage", placeholder: "-50" }] }, { key: "desert_mountains", block: [{ key: "damage", placeholder: "-30" }] }] } } }, message: { sampled: 682, keys: [{ key: "icon" }, { key: "title" }, { key: "desc" }, { key: "style", choices: ["bad", "good", "neutral"] }, { key: "message_filter_type" }] }, message_filter_type: { sampled: 180, keys: [{ key: "display", choices: ["feed", "toast", "hidden", "popup"] }, { key: "group" }] }, message_group_type: { sampled: 31, keys: [{ key: "sort_order", placeholder: "0" }] }, modifier_definition_format: { sampled: 1952, keys: [{ key: "decimals", choices: ["0", "2", "1", "3"] }, { key: "prefix" }] }, name_equivalency: { sampled: 1433, keys: [] }, name_list: { sampled: 218, keys: [{ key: "cadet_dynasty_names", block: [] }, { key: "dynasty_names", block: [] }, { key: "male_names", block: [] }, { key: "female_names", block: [] }, { key: "dynasty_of_location_prefix" }] }, nickname: { sampled: 683, keys: [] }, on_action: { sampled: 880, keys: [] }, opinion_modifier: { sampled: 1532, keys: [{ key: "opinion", placeholder: "-20" }, { key: "decaying", choices: ["yes", "no"] }, { key: "years", placeholder: "10" }] }, perk: { sampled: 162, keys: [{ key: "lifestyle", choices: ["diplomacy_lifestyle", "intrigue_lifestyle", "learning_lifestyle", "martial_lifestyle", "stewardship_lifestyle", "wanderer_lifestyle"] }, { key: "tree" }, { key: "position", block: [] }, { key: "icon" }, { key: "parent" }, { key: "effect", block: [{ key: "if", block: [] }] }], blocks: { effect: { sampled: 138, keys: [{ key: "if", block: [{ key: "limit", block: [] }, { key: "custom_description_no_bullet", block: [] }] }] } } }, playable_difficulty_info: { sampled: 14, keys: [{ key: "is_shown", block: [] }] }, point_of_interest: { sampled: 17, keys: [{ key: "build_province_list", block: [{ key: "every_special_building_province", block: [] }] }, { key: "on_visit", block: [{ key: "send_interface_toast", block: [] }, { key: "visiting_poi_effect", choices: ["yes"] }] }], blocks: { build_province_list: { sampled: 15, keys: [{ key: "every_special_building_province", block: [{ key: "limit", block: [] }, { key: "add_to_list", choices: ["provinces"] }] }] }, on_visit: { sampled: 17, keys: [{ key: "send_interface_toast", block: [{ key: "title" }, { key: "left_icon", choices: ["root"] }, { key: "if", block: [] }, { key: "wanderer_lifestyle_destination_effect", choices: ["yes"] }, { key: "traveler_travel_xp_effect", block: [] }] }, { key: "visiting_poi_effect", choices: ["yes"] }] } } }, portrait_animation: { sampled: 272, keys: [{ key: "default", block: [{ key: "default", block: [] }, { key: "portrait_modifier", block: [] }] }], blocks: { default: { sampled: 270, keys: [{ key: "default", block: [{ key: "head" }, { key: "torso" }] }, { key: "portrait_modifier", block: [{ key: "animations" }] }] } } }, portrait_modifier_group: { sampled: 47, keys: [{ key: "usage", choices: ["game", "customization", "none"] }] }, province_history: { sampled: 10887, keys: [{ key: "holding", choices: ["none", "castle_holding", "city_holding", "church_holding", "tribal_holding", "nomad_holding", "temple_citadel_holding", "herder_holding"] }] }, religion: { sampled: 49, keys: [{ key: "family", choices: ["rf_pagan", "rf_abrahamic", "rf_eastern", "rf_sinitic"] }, { key: "graphical_faith" }, { key: "doctrine" }, { key: "pagan_roots", choices: ["yes"] }, { key: "traits", block: [{ key: "virtues", block: [] }, { key: "sins", block: [] }] }, { key: "custom_faith_icons", block: [] }, { key: "holy_order_names", block: [] }, { key: "localization", block: [{ key: "HighGodName" }, { key: "HighGodName2" }, { key: "HighGodNamePossessive" }, { key: "HighGodNameSheHe" }, { key: "HighGodHerselfHimself" }, { key: "HighGodHerHis" }, { key: "HighGodNameAlternate" }, { key: "HighGodNameAlternatePossessive" }, { key: "CreatorName" }, { key: "CreatorNamePossessive" }, { key: "CreatorSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY"] }, { key: "CreatorHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIM_THEM"] }, { key: "CreatorHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIS_THEIR"] }, { key: "HealthGodName" }, { key: "HealthGodNamePossessive" }, { key: "HealthGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_IT", "tani_high_god_shehe"] }, { key: "HealthGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_ITS", "tani_high_god_herselfhimself"] }, { key: "HealthGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_IT", "tani_high_god_herhis"] }, { key: "FertilityGodName" }, { key: "FertilityGodNamePossessive" }, { key: "FertilityGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_IT", "tani_high_god_shehe"] }, { key: "FertilityGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_ITS", "tani_high_god_herselfhimself"] }, { key: "FertilityGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_IT", "tani_high_god_herhis"] }, { key: "WealthGodName" }, { key: "WealthGodNamePossessive" }, { key: "WealthGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_SHE", "tani_high_god_shehe"] }, { key: "WealthGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_ITS", "tani_high_god_herselfhimself"] }, { key: "WealthGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_IT", "tani_high_god_herhis"] }, { key: "HouseholdGodName" }, { key: "HouseholdGodNamePossessive" }, { key: "HouseholdGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_THEY"] }, { key: "HouseholdGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_THEIR"] }, { key: "HouseholdGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_THEM"] }, { key: "FateGodName" }, { key: "FateGodNamePossessive" }, { key: "FateGodSheHe", choices: ["CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_SHE", "tani_high_god_shehe"] }, { key: "FateGodHerHis", choices: ["CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_HER", "tani_high_god_herselfhimself"] }, { key: "FateGodHerHim", choices: ["CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_HER", "tani_high_god_herhis"] }, { key: "KnowledgeGodName" }, { key: "KnowledgeGodNamePossessive" }, { key: "KnowledgeGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_IT", "tani_high_god_shehe"] }, { key: "KnowledgeGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_ITS", "tani_high_god_herselfhimself"] }, { key: "KnowledgeGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_IT", "tani_high_god_herhis"] }, { key: "WarGodName" }, { key: "WarGodNamePossessive" }, { key: "WarGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_THEY", "tani_high_god_shehe"] }, { key: "WarGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_THEIR", "tani_high_god_herselfhimself"] }, { key: "WarGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_THEM", "tani_high_god_herhis"] }, { key: "TricksterGodName" }, { key: "TricksterGodNamePossessive" }, { key: "TricksterGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_IT"] }, { key: "TricksterGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_ITS"] }, { key: "TricksterGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_IT"] }, { key: "NightGodName" }, { key: "NightGodNamePossessive" }, { key: "NightGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_IT", "tani_high_god_shehe"] }, { key: "NightGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_ITS", "tani_high_god_herselfhimself"] }, { key: "NightGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_IT", "tani_high_god_herhis"] }, { key: "WaterGodName" }, { key: "WaterGodNamePossessive" }, { key: "WaterGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_THEY", "biliku_high_god_shehe", "tani_high_god_shehe"] }, { key: "WaterGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_THEIR", "biliku_high_god_herselfhimself", "tani_high_god_herselfhimself"] }, { key: "WaterGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_THEM", "biliku_high_god_herhis", "tani_high_god_herhis"] }, { key: "PantheonTerm" }, { key: "PantheonTerm2" }, { key: "PantheonTerm3" }, { key: "PantheonTermHasHave", choices: ["pantheon_term_have", "pantheon_term_has"] }, { key: "GoodGodNames", block: [] }, { key: "DevilName" }, { key: "DevilNamePossessive" }, { key: "DevilSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY"] }, { key: "DevilHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR"] }, { key: "DevilHerselfHimself" }, { key: "EvilGodNames", block: [] }, { key: "HouseOfWorship" }, { key: "HouseOfWorship2" }, { key: "HouseOfWorship3" }, { key: "HouseOfWorshipPlural" }, { key: "ReligiousSymbol" }, { key: "ReligiousSymbol2" }, { key: "ReligiousSymbol3" }, { key: "ReligiousText" }, { key: "ReligiousText2" }, { key: "ReligiousText3" }, { key: "ReligiousHeadName" }, { key: "ReligiousHeadTitleName" }, { key: "DevoteeMale" }, { key: "DevoteeMalePlural" }, { key: "DevoteeFemale" }, { key: "DevoteeFemalePlural" }, { key: "DevoteeNeuter" }, { key: "DevoteeNeuterPlural" }, { key: "PriestMale" }, { key: "PriestMalePlural" }, { key: "PriestFemale" }, { key: "PriestFemalePlural" }, { key: "PriestNeuter" }, { key: "PriestNeuterPlural" }, { key: "AltPriestTermPlural" }, { key: "BishopMale" }, { key: "BishopMalePlural" }, { key: "BishopFemale" }, { key: "BishopFemalePlural" }, { key: "BishopNeuter" }, { key: "BishopNeuterPlural" }, { key: "DivineRealm" }, { key: "DivineRealm2" }, { key: "DivineRealm3" }, { key: "PositiveAfterLife" }, { key: "PositiveAfterLife2" }, { key: "PositiveAfterLife3" }, { key: "NegativeAfterLife" }, { key: "NegativeAfterLife2" }, { key: "NegativeAfterLife3" }, { key: "DeathDeityName" }, { key: "DeathDeityNamePossessive" }, { key: "DeathDeitySheHe" }, { key: "DeathDeityHerHis" }, { key: "DeathDeityHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_HER"] }, { key: "WitchGodName" }, { key: "WitchGodNamePossessive" }, { key: "WitchGodHerHis", choices: ["CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_THEIR", "witchgod_herhis_their"] }, { key: "WitchGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_THEY", "witchgod_shehe_they"] }, { key: "WitchGodHerHim", choices: ["CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_THEM", "witchgod_herhim_them"] }, { key: "WitchGodMistressMaster", choices: ["witch_spirit", "master", "mistress", "witch_master"] }, { key: "WitchGodMotherFather", choices: ["witch_source", "father", "mother", "witch_father"] }, { key: "GHWName", choices: ["ghw_great_holy_war", "ghw_purification", "ghw_crusade", "ghw_jihad"] }, { key: "GHWNamePlural", choices: ["ghw_great_holy_wars", "ghw_purifications", "ghw_crusades", "ghw_jihads"] }] }, { key: "faiths", block: [] }], blocks: { localization: { sampled: 49, keys: [{ key: "HighGodName" }, { key: "HighGodName2" }, { key: "HighGodNamePossessive" }, { key: "HighGodNameSheHe" }, { key: "HighGodHerselfHimself" }, { key: "HighGodHerHis" }, { key: "HighGodNameAlternate" }, { key: "HighGodNameAlternatePossessive" }, { key: "CreatorName" }, { key: "CreatorNamePossessive" }, { key: "CreatorSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY"] }, { key: "CreatorHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIM_THEM"] }, { key: "CreatorHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIS_THEIR"] }, { key: "HealthGodName" }, { key: "HealthGodNamePossessive" }, { key: "HealthGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_IT", "tani_high_god_shehe"] }, { key: "HealthGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_ITS", "tani_high_god_herselfhimself"] }, { key: "HealthGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_IT", "tani_high_god_herhis"] }, { key: "FertilityGodName" }, { key: "FertilityGodNamePossessive" }, { key: "FertilityGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_IT", "tani_high_god_shehe"] }, { key: "FertilityGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_ITS", "tani_high_god_herselfhimself"] }, { key: "FertilityGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_IT", "tani_high_god_herhis"] }, { key: "WealthGodName" }, { key: "WealthGodNamePossessive" }, { key: "WealthGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_SHE", "tani_high_god_shehe"] }, { key: "WealthGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_ITS", "tani_high_god_herselfhimself"] }, { key: "WealthGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_IT", "tani_high_god_herhis"] }, { key: "HouseholdGodName" }, { key: "HouseholdGodNamePossessive" }, { key: "HouseholdGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_THEY"] }, { key: "HouseholdGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_THEIR"] }, { key: "HouseholdGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_THEM"] }, { key: "FateGodName" }, { key: "FateGodNamePossessive" }, { key: "FateGodSheHe", choices: ["CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_SHE", "tani_high_god_shehe"] }, { key: "FateGodHerHis", choices: ["CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_HER", "tani_high_god_herselfhimself"] }, { key: "FateGodHerHim", choices: ["CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_HER", "tani_high_god_herhis"] }, { key: "KnowledgeGodName" }, { key: "KnowledgeGodNamePossessive" }, { key: "KnowledgeGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_IT", "tani_high_god_shehe"] }, { key: "KnowledgeGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_ITS", "tani_high_god_herselfhimself"] }, { key: "KnowledgeGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_IT", "tani_high_god_herhis"] }, { key: "WarGodName" }, { key: "WarGodNamePossessive" }, { key: "WarGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_THEY", "tani_high_god_shehe"] }, { key: "WarGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_THEIR", "tani_high_god_herselfhimself"] }, { key: "WarGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_THEM", "tani_high_god_herhis"] }, { key: "TricksterGodName" }, { key: "TricksterGodNamePossessive" }, { key: "TricksterGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_IT"] }, { key: "TricksterGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_ITS"] }, { key: "TricksterGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_IT"] }, { key: "NightGodName" }, { key: "NightGodNamePossessive" }, { key: "NightGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY", "CHARACTER_SHEHE_IT", "tani_high_god_shehe"] }, { key: "NightGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR", "CHARACTER_HERHIS_ITS", "tani_high_god_herselfhimself"] }, { key: "NightGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_THEM", "CHARACTER_HERHIM_IT", "tani_high_god_herhis"] }, { key: "WaterGodName" }, { key: "WaterGodNamePossessive" }, { key: "WaterGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_THEY", "biliku_high_god_shehe", "tani_high_god_shehe"] }, { key: "WaterGodHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_THEIR", "biliku_high_god_herselfhimself", "tani_high_god_herselfhimself"] }, { key: "WaterGodHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_THEM", "biliku_high_god_herhis", "tani_high_god_herhis"] }, { key: "PantheonTerm" }, { key: "PantheonTerm2" }, { key: "PantheonTerm3" }, { key: "PantheonTermHasHave", choices: ["pantheon_term_have", "pantheon_term_has"] }, { key: "GoodGodNames", block: [] }, { key: "DevilName" }, { key: "DevilNamePossessive" }, { key: "DevilSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_THEY"] }, { key: "DevilHerHis", choices: ["CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_THEIR"] }, { key: "DevilHerselfHimself" }, { key: "EvilGodNames", block: [] }, { key: "HouseOfWorship" }, { key: "HouseOfWorship2" }, { key: "HouseOfWorship3" }, { key: "HouseOfWorshipPlural" }, { key: "ReligiousSymbol" }, { key: "ReligiousSymbol2" }, { key: "ReligiousSymbol3" }, { key: "ReligiousText" }, { key: "ReligiousText2" }, { key: "ReligiousText3" }, { key: "ReligiousHeadName" }, { key: "ReligiousHeadTitleName" }, { key: "DevoteeMale" }, { key: "DevoteeMalePlural" }, { key: "DevoteeFemale" }, { key: "DevoteeFemalePlural" }, { key: "DevoteeNeuter" }, { key: "DevoteeNeuterPlural" }, { key: "PriestMale" }, { key: "PriestMalePlural" }, { key: "PriestFemale" }, { key: "PriestFemalePlural" }, { key: "PriestNeuter" }, { key: "PriestNeuterPlural" }, { key: "AltPriestTermPlural" }, { key: "BishopMale" }, { key: "BishopMalePlural" }, { key: "BishopFemale" }, { key: "BishopFemalePlural" }, { key: "BishopNeuter" }, { key: "BishopNeuterPlural" }, { key: "DivineRealm" }, { key: "DivineRealm2" }, { key: "DivineRealm3" }, { key: "PositiveAfterLife" }, { key: "PositiveAfterLife2" }, { key: "PositiveAfterLife3" }, { key: "NegativeAfterLife" }, { key: "NegativeAfterLife2" }, { key: "NegativeAfterLife3" }, { key: "DeathDeityName" }, { key: "DeathDeityNamePossessive" }, { key: "DeathDeitySheHe" }, { key: "DeathDeityHerHis" }, { key: "DeathDeityHerHim", choices: ["CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_HER"] }, { key: "WitchGodName" }, { key: "WitchGodNamePossessive" }, { key: "WitchGodHerHis", choices: ["CHARACTER_HERHIS_HER", "CHARACTER_HERHIS_HIS", "CHARACTER_HERHIS_ITS", "CHARACTER_HERHIS_THEIR", "witchgod_herhis_their"] }, { key: "WitchGodSheHe", choices: ["CHARACTER_SHEHE_HE", "CHARACTER_SHEHE_SHE", "CHARACTER_SHEHE_IT", "CHARACTER_SHEHE_THEY", "witchgod_shehe_they"] }, { key: "WitchGodHerHim", choices: ["CHARACTER_HERHIM_HER", "CHARACTER_HERHIM_HIM", "CHARACTER_HERHIM_IT", "CHARACTER_HERHIM_THEM", "witchgod_herhim_them"] }, { key: "WitchGodMistressMaster", choices: ["witch_spirit", "master", "mistress", "witch_master"] }, { key: "WitchGodMotherFather", choices: ["witch_source", "father", "mother", "witch_father"] }, { key: "GHWName", choices: ["ghw_great_holy_war", "ghw_purification", "ghw_crusade", "ghw_jihad"] }, { key: "GHWNamePlural", choices: ["ghw_great_holy_wars", "ghw_purifications", "ghw_crusades", "ghw_jihads"] }] }, traits: { sampled: 49, keys: [{ key: "virtues", block: [] }, { key: "sins", block: [] }] } } }, scheme_agent_type: { sampled: 65, keys: [{ key: "contribution_type", choices: ["success_chance_max", "speed", "secrecy", "success_chance", "success_chance_growth"] }, { key: "contribution", block: [{ key: "value", choices: ["scheme_agent_general_bonuses_contribution_score_value", "100", "-100", "10"] }, { key: "add", block: [] }, { key: "if", block: [] }, { key: "max", choices: ["agent_scheme_contributor_max"] }, { key: "min", choices: ["agent_scheme_contributor_min"] }] }], blocks: { contribution: { sampled: 65, keys: [{ key: "value", choices: ["scheme_agent_general_bonuses_contribution_score_value", "100", "-100", "10"] }, { key: "add", block: [{ key: "value", choices: ["intrigue", "diplomacy", "learning", "stewardship", "prowess", "martial"] }, { key: "multiply", choices: ["agent_3to1_3_skill_mult_value", "agent_3to1_1_skill_mult_value", "agent_1to1_1_skill_mult_value", "agent_2to1to1_1_skill_mult_value", "agent_2to1to1_2_skill_mult_value", "1.75"] }, { key: "ceiling", choices: ["yes"] }, { key: "max", choices: ["agent_max_skill_value", "political_agent_max_skill_value", "50"] }, { key: "desc", choices: ["scheme_agent_aptitude.skill.intrigue", "scheme_agent_aptitude.skill.diplomacy", "scheme_agent_aptitude.skill.learning", "scheme_agent_aptitude.skill.stewardship", "scheme_agent_aptitude.skill.prowess", "scheme_agent_aptitude.skill.martial", "court_position_skill_learning"] }] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", block: [] }] }, { key: "max", choices: ["agent_scheme_contributor_max"] }, { key: "min", choices: ["agent_scheme_contributor_min"] }] } } }, scheme_countermeasure: { sampled: 24, keys: [{ key: "frame" }, { key: "is_shown", block: [{ key: "scheme_countermeasure_access_select_best_tier_trigger", block: [] }] }, { key: "is_valid_showing_failures_only", block: [{ key: "can_set_own_countermeasures_trigger", choices: ["yes"] }] }, { key: "on_activate", block: [{ key: "inform_player_of_relevant_countermeasure_activated_effect", block: [] }] }, { key: "owner_modifier", block: [] }, { key: "ai_will_do", block: [{ key: "add", choices: ["ai_will_do_withdraw_from_view_value", "ai_will_do_arbitrary_arrests_value", "ai_will_do_bounties_for_whispers_value", "ai_will_do_redouble_guards_for_courtier_value", "ai_will_do_redouble_guards_value", "ai_will_do_strengthen_sentries_for_courtier_value", "ai_will_do_strengthen_sentries_value"] }] }, { key: "parameters", block: [{ key: "has_any_countermeasure_active", choices: ["yes"] }, { key: "has_preemptive_countermeasure_active", choices: ["yes"] }] }], blocks: { ai_will_do: { sampled: 23, keys: [{ key: "add", choices: ["ai_will_do_withdraw_from_view_value", "ai_will_do_arbitrary_arrests_value", "ai_will_do_bounties_for_whispers_value", "ai_will_do_redouble_guards_for_courtier_value", "ai_will_do_redouble_guards_value", "ai_will_do_strengthen_sentries_for_courtier_value", "ai_will_do_strengthen_sentries_value"] }] }, is_shown: { sampled: 24, keys: [{ key: "scheme_countermeasure_access_select_best_tier_trigger", block: [{ key: "COUNTERMEASURE", choices: ["arbitrary_arrests", "bounties_for_whispers", "redouble_guards", "strengthen_sentries", "withdraw_from_view", "bribe_officials"] }, { key: "TIER", choices: ["1", "2", "3", "4"] }] }] }, is_valid_showing_failures_only: { sampled: 23, keys: [{ key: "can_set_own_countermeasures_trigger", choices: ["yes"] }] }, on_activate: { sampled: 23, keys: [{ key: "inform_player_of_relevant_countermeasure_activated_effect", block: [{ key: "COUNTERMEASURE", choices: ["arbitrary_arrests", "bounties_for_whispers", "redouble_guards", "strengthen_sentries", "withdraw_from_view", "bribe_officials"] }] }] }, parameters: { sampled: 24, keys: [{ key: "has_any_countermeasure_active", choices: ["yes"] }, { key: "has_preemptive_countermeasure_active", choices: ["yes"] }] } } }, scheme_pulse_action: { sampled: 315, keys: [{ key: "icon", choices: ["intrigue_positive", "intrigue_negative"] }, { key: "is_valid", block: [{ key: "scheme_apa_apply_modifier_trigger", block: [] }] }, { key: "weight", choices: ["scheme_owner_aptitude_weight_up_positive_value", "scheme_owner_aptitude_weight_up_negative_value"] }, { key: "effect", block: [{ key: "custom_tooltip", block: [] }, { key: "scheme_pulse_action_sort_cooldown_effect", choices: ["yes"] }] }], blocks: { effect: { sampled: 315, keys: [{ key: "custom_tooltip", block: [{ key: "text", choices: ["scheme_apa.0000.effect_notice.positive.success_chance", "scheme_apa.0000.effect_notice.negative.success_chance", "scheme_apa.0000.effect_notice.negative.speed", "scheme_apa.0000.effect_notice.positive.speed", "scheme_apa.0000.effect_notice.positive.secrecy", "scheme_apa.0000.effect_notice.negative.secrecy"] }, { key: "add_scheme_modifier", block: [] }] }, { key: "scheme_pulse_action_sort_cooldown_effect", choices: ["yes"] }] }, is_valid: { sampled: 315, keys: [{ key: "scheme_apa_apply_modifier_trigger", block: [{ key: "MODIFIER" }] }] } } }, scheme_type: { sampled: 76, keys: [{ key: "skill", choices: ["intrigue", "diplomacy", "learning", "stewardship", "prowess", "martial"] }, { key: "desc" }, { key: "success_desc" }, { key: "icon" }, { key: "illustration" }, { key: "target_type", choices: ["character", "title"] }, { key: "category", choices: ["contract", "political", "hostile", "personal"] }, { key: "is_secret", choices: ["yes", "no"] }, { key: "speed_per_skill_point", choices: ["t2_spsp_owner_value", "-2.5", "t3_spsp_owner_value", "-2", "-1", "t1_spsp_owner_value"] }, { key: "phases_per_agent_charge" }, { key: "base_progress_goal" }, { key: "spymaster_speed_per_skill_point", choices: ["0", "t2_spsp_owner_spy_value", "t3_spsp_owner_spy_value", "t2_spsp_target_spy_value"] }, { key: "success_chance_growth_per_skill_point", choices: ["laamp_contract_scgpsp_value", "t2_scgpsp_value", "t3_scgpsp_value"] }, { key: "base_maximum_success", choices: ["t3_base_max_success_value", "t2_base_max_success_value", "95", "t1_base_max_success_value"] }, { key: "uses_resistance", choices: ["no"] }, { key: "agent_leave_threshold", choices: ["-25", "-10"] }, { key: "valid", block: [] }, { key: "agent_join_chance", block: [{ key: "base", choices: ["0"] }, { key: "ai_agent_join_chance_laamp_contract_modifier", choices: ["yes"] }] }, { key: "valid_agent", block: [{ key: "is_valid_agent_standard_trigger", choices: ["yes"] }] }, { key: "agent_groups_owner_perspective", block: [] }, { key: "allow", block: [{ key: "is_adult", choices: ["yes"] }, { key: "is_imprisoned", choices: ["no"] }] }, { key: "base_success_chance", block: [{ key: "base", choices: ["0", "5", "10", "-25", "15", "30"] }, { key: "scheme_type_skill_success_chance_modifier", block: [] }, { key: "modifier", block: [] }] }, { key: "on_phase_completed", block: [{ key: "suppress_scheme_follow_up_event_till_input_given_effect", choices: ["yes"] }, { key: "cap_schemes_and_fire_reminders_effect", choices: ["yes"] }] }, { key: "on_hud_click", block: [] }, { key: "on_monthly", block: [{ key: "fire_generic_contract_scheme_on_going_events_effect", choices: ["yes"] }] }, { key: "on_semiyearly", block: [{ key: "if", block: [] }] }, { key: "odds_prediction", block: [{ key: "add" }, { key: "min", choices: ["0"] }] }, { key: "on_invalidated", block: [{ key: "save_scope_as", choices: ["scheme"] }, { key: "scheme_owner", block: [] }] }, { key: "on_start", block: [{ key: "set_variable", block: [] }, { key: "if", block: [] }] }], blocks: { agent_join_chance: { sampled: 63, keys: [{ key: "base", choices: ["0"] }, { key: "ai_agent_join_chance_laamp_contract_modifier", choices: ["yes"] }] }, allow: { sampled: 40, keys: [{ key: "is_adult", choices: ["yes"] }, { key: "is_imprisoned", choices: ["no"] }] }, base_success_chance: { sampled: 76, keys: [{ key: "base", choices: ["0", "5", "10", "-25", "15", "30"] }, { key: "scheme_type_skill_success_chance_modifier", block: [{ key: "SKILL", choices: ["INTRIGUE", "DIPLOMACY", "LEARNING", "STEWARDSHIP", "PROWESS", "MARTIAL"] }] }, { key: "modifier", block: [{ key: "add" }, { key: "desc" }] }] }, odds_prediction: { sampled: 40, keys: [{ key: "add" }, { key: "min", choices: ["0"] }] }, on_invalidated: { sampled: 76, keys: [{ key: "save_scope_as", choices: ["scheme"] }, { key: "scheme_owner", block: [] }] }, on_monthly: { sampled: 68, keys: [{ key: "fire_generic_contract_scheme_on_going_events_effect", choices: ["yes"] }] }, on_phase_completed: { sampled: 75, keys: [{ key: "suppress_scheme_follow_up_event_till_input_given_effect", choices: ["yes"] }, { key: "cap_schemes_and_fire_reminders_effect", choices: ["yes"] }] }, on_semiyearly: { sampled: 63, keys: [{ key: "if", block: [{ key: "limit", block: [] }] }] }, on_start: { sampled: 45, keys: [{ key: "set_variable", block: [{ key: "name", choices: ["apply_countermeasures", "targets_movement", "secrets_found"] }, { key: "value", choices: ["flag:calculating", "flag:indirect", "flag:opportunistic", "flag:political", "scope:targets_movement", "0"] }] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add_agent_slot" }] }] }, valid_agent: { sampled: 63, keys: [{ key: "is_valid_agent_standard_trigger", choices: ["yes"] }] } } }, script_value: { sampled: 3477, keys: [{ key: "value" }] }, scripted_animation: { sampled: 10, keys: [{ key: "triggered_animation", block: [{ key: "trigger", block: [] }, { key: "animation" }] }, { key: "animation", choices: ["aggressive_sword", "celebrate_sword", "hunting_shortbow_aim_arrow_default", "hunting_shortbow_aim_bluntarrow_default", "hunting_shortbow_rest_arrow_default", "hunting_shortbow_rest_bluntarrow_default", "idle", "personality_bold"] }], blocks: { triggered_animation: { sampled: 54, keys: [{ key: "trigger", block: [] }, { key: "animation" }] } } }, scripted_character_template: { sampled: 403, keys: [{ key: "age", block: [] }, { key: "dynasty", choices: ["none", "generate"] }, { key: "random_traits", choices: ["yes", "no"] }, { key: "faith" }, { key: "culture" }, { key: "random_traits_list", block: [{ key: "count", choices: ["1", "3", "2", "squire_quality_bad_traits", "squire_quality_good_traits"] }] }, { key: "gender_female_chance" }, { key: "after_creation", block: [] }], blocks: { random_traits_list: { sampled: 761, keys: [{ key: "count", choices: ["1", "3", "2", "squire_quality_bad_traits", "squire_quality_good_traits"] }] } } }, scripted_cost: { sampled: 12, keys: [{ key: "prestige", block: [{ key: "value", block: [] }, { key: "if", block: [] }] }] }, scripted_effect: { sampled: 3465, keys: [] }, scripted_gui: { sampled: 33, keys: [{ key: "scope", choices: ["character", "innovation_type"] }, { key: "is_valid", block: [] }] }, scripted_illustration: { sampled: 18, keys: [{ key: "texture", block: [{ key: "reference" }, { key: "trigger", block: [] }] }], blocks: { texture: { sampled: 546, keys: [{ key: "reference" }, { key: "trigger", block: [] }] } } }, scripted_modifier: { sampled: 378, keys: [{ key: "modifier", block: [{ key: "add" }, { key: "desc" }] }], blocks: { modifier: { sampled: 2070, keys: [{ key: "add" }, { key: "desc" }] } } }, scripted_relation: { sampled: 38, keys: [{ key: "hidden", choices: ["yes"] }, { key: "corresponding" }] }, scripted_rule: { sampled: 62, keys: [] }, scripted_trigger: { sampled: 3152, keys: [] }, secret: { sampled: 18, keys: [{ key: "category", choices: ["deviancy", "murder", "adultery", "religious", "civil", "merit", "raid"] }, { key: "is_valid", block: [] }, { key: "is_shunned", block: [] }, { key: "is_criminal", block: [] }, { key: "on_discover", block: [] }, { key: "on_expose", block: [{ key: "save_scope_as", choices: ["secret"] }, { key: "secret_exposed_notification_effect", choices: ["yes"] }] }], blocks: { on_expose: { sampled: 18, keys: [{ key: "save_scope_as", choices: ["secret"] }, { key: "secret_exposed_notification_effect", choices: ["yes"] }] } } }, situation: { sampled: 11, keys: [{ key: "window", choices: ["the_great_steppe", "dynastic_cycle", "silk_road"] }, { key: "gui_window_name", choices: ["window_the_great_steppe", "window_tgp_natural_disaster", "window_silk_road", "window_situation", "window_tgp_dynastic_cycle"] }, { key: "illustration" }, { key: "situation_group_type", choices: ["major", "natural_disasters", "minor"] }, { key: "map_mode", choices: ["sub_regions", "dynastic_cycle", "silk_road"] }, { key: "is_unique", choices: ["yes", "no"] }, { key: "migration", choices: ["yes"] }, { key: "sub_regions", block: [] }, { key: "on_monthly", block: [] }, { key: "on_yearly", block: [{ key: "trigger_event", block: [] }] }, { key: "participant_groups", block: [{ key: "nomad_rulers_capital", block: [] }, { key: "nomad_rulers_realm", block: [] }, { key: "herders", block: [] }, { key: "settled_rulers", block: [] }] }, { key: "start_phase", choices: ["situation_steppe_abundant_grazing_season", "warning", "phase_steady_trading", "plentiful_harvest", "situation_dynastic_cycle_phase_instability"] }, { key: "phases", block: [{ key: "situation_steppe_abundant_grazing_season", block: [] }, { key: "situation_steppe_severe_drought_season", block: [] }, { key: "situation_steppe_warm_nights_season", block: [] }] }], blocks: { participant_groups: { sampled: 11, keys: [{ key: "nomad_rulers_capital", block: [{ key: "require_capital_in_sub_region", choices: ["yes"] }, { key: "is_character_valid", block: [] }, { key: "map_color", block: [] }] }, { key: "nomad_rulers_realm", block: [{ key: "require_capital_in_sub_region", choices: ["no"] }, { key: "require_realm_in_sub_region", choices: ["yes"] }, { key: "is_character_valid", block: [] }, { key: "map_color", block: [] }] }, { key: "herders", block: [{ key: "is_character_valid", block: [] }, { key: "map_color", block: [] }] }, { key: "settled_rulers", block: [{ key: "is_character_valid", block: [] }, { key: "map_color", block: [] }] }] }, phases: { sampled: 11, keys: [{ key: "situation_steppe_abundant_grazing_season", block: [{ key: "icon" }, { key: "illustration" }, { key: "max_duration", block: [] }, { key: "on_start", block: [] }, { key: "max_duration_next_phase", choices: ["random_non_takeover"] }, { key: "future_phases", block: [] }, { key: "modifier_sets", block: [] }] }, { key: "situation_steppe_severe_drought_season", block: [{ key: "icon" }, { key: "illustration" }, { key: "max_duration", block: [] }, { key: "map_province_effect", choices: ["drought"] }, { key: "on_start", block: [] }, { key: "max_duration_next_phase", choices: ["random_non_takeover"] }, { key: "future_phases", block: [] }, { key: "modifier_sets", block: [] }] }, { key: "situation_steppe_warm_nights_season", block: [{ key: "icon" }, { key: "illustration" }, { key: "max_duration", block: [] }, { key: "map_province_effect", choices: ["summer"] }, { key: "map_province_effect_intensity", choices: ["0.1", "0.6"] }, { key: "on_start", block: [] }, { key: "max_duration_next_phase", choices: ["random_non_takeover"] }, { key: "future_phases", block: [] }, { key: "modifier_sets", block: [] }] }] } } }, situation_catalyst: { sampled: 121, keys: [] }, static_modifier: { sampled: 6011, keys: [{ key: "icon" }] }, story_cycle: { sampled: 51, keys: [{ key: "on_setup", block: [{ key: "story_owner", block: [] }] }, { key: "on_owner_death", block: [] }, { key: "effect_group", block: [{ key: "days", block: [] }, { key: "trigger", block: [] }, { key: "triggered_effect", block: [] }] }, { key: "on_end", block: [] }], blocks: { effect_group: { sampled: 158, keys: [{ key: "days", block: [] }, { key: "trigger", block: [{ key: "story_owner", block: [] }] }, { key: "triggered_effect", block: [{ key: "trigger", block: [] }, { key: "effect", block: [] }] }] }, on_setup: { sampled: 49, keys: [{ key: "story_owner", block: [] }] } } }, struggle_catalyst: { sampled: 127, keys: [] }, subject_contract: { sampled: 64, keys: [{ key: "display_mode", choices: ["tree", "checkbox", "radiobutton", "hidden"] }, { key: "obligation_levels", block: [] }] }, subject_contract_group: { sampled: 23, keys: [{ key: "contracts", block: [] }] }, succession_appointment: { sampled: 11, keys: [{ key: "default_candidates", block: [] }, { key: "allow_same_tier_candidates", choices: ["yes"] }, { key: "candidate_score", block: [{ key: "value", block: [] }] }], blocks: { candidate_score: { sampled: 11, keys: [{ key: "value", block: [{ key: "add", block: [] }, { key: "if", block: [] }, { key: "else_if", block: [] }, { key: "save_temporary_value_as", choices: ["temp_total", "pre_gender_law_calc"] }] }] } } }, suggestion: { sampled: 13, keys: [{ key: "weight", block: [{ key: "base", choices: ["0", "10", "5"] }, { key: "modifier", block: [] }] }, { key: "check_create_suggestion", block: [] }, { key: "effect", block: [] }, { key: "score", block: [{ key: "base", choices: ["100", "50", "-200"] }, { key: "modifier", block: [] }] }, { key: "is_valid", block: [] }], blocks: { weight: { sampled: 13, keys: [{ key: "base", choices: ["0", "10", "5"] }, { key: "modifier", block: [{ key: "add", placeholder: "0.5" }] }] } } }, task_contract: { sampled: 159, keys: [{ key: "group" }, { key: "icon" }, { key: "travel", choices: ["no", "yes"] }, { key: "use_diplomatic_range", choices: ["no", "yes"] }, { key: "valid_to_create", block: [] }, { key: "valid_to_accept", block: [{ key: "is_available", choices: ["yes"] }] }, { key: "valid_to_continue", block: [{ key: "task_contract_taker", block: [] }] }, { key: "valid_to_keep", block: [{ key: "task_contract_taker", block: [] }] }, { key: "on_create", block: [] }, { key: "on_accepted", block: [{ key: "task_contract_taker", block: [] }, { key: "save_scope_as", choices: ["task_contract"] }] }, { key: "on_completed", block: [] }, { key: "on_invalidated", block: [{ key: "if", block: [] }] }, { key: "task_contract_reward", block: [{ key: "failure_standard", block: [] }] }], blocks: { on_accepted: { sampled: 159, keys: [{ key: "task_contract_taker", block: [{ key: "play_sound_effect" }] }, { key: "save_scope_as", choices: ["task_contract"] }] }, on_invalidated: { sampled: 120, keys: [{ key: "if", block: [{ key: "limit", block: [] }, { key: "governor_contract_invalidated_message_effect", choices: ["yes"] }] }] }, task_contract_reward: { sampled: 159, keys: [{ key: "failure_standard", block: [{ key: "visible", choices: ["no"] }, { key: "effect", block: [] }] }] }, valid_to_accept: { sampled: 158, keys: [{ key: "is_available", choices: ["yes"] }] }, valid_to_continue: { sampled: 158, keys: [{ key: "task_contract_taker", block: [{ key: "valid_governor_contract_trigger", choices: ["yes"] }] }] }, valid_to_keep: { sampled: 156, keys: [{ key: "task_contract_taker", block: [{ key: "valid_governor_contract_trigger", choices: ["yes"] }] }] } } }, terrain_type: { sampled: 17, keys: [{ key: "color", block: [] }, { key: "travel_danger_color", block: [] }, { key: "travel_danger_score" }, { key: "provision_cost" }, { key: "county_fertility", choices: ["20", "30", "15", "10", "25", "40"] }, { key: "province_modifier", block: [{ key: "supply_limit_mult", placeholder: "0" }, { key: "travel_danger" }, { key: "county_fertility_growth_add" }] }, { key: "county_capital_modifier", block: [{ key: "development_growth_factor", choices: ["-0.5", "-0.05", "-0.25", "0.1", "0.2", "-0.1", "-0.4"] }] }, { key: "movement_speed", choices: ["0.8", "0.5", "0.7", "1"] }, { key: "audio_parameter", placeholder: "1.0" }, { key: "combat_width", choices: ["0.8", "0.5", "0.6", "0.7", "0.75", "0.9"] }], blocks: { county_capital_modifier: { sampled: 13, keys: [{ key: "development_growth_factor", choices: ["-0.5", "-0.05", "-0.25", "0.1", "0.2", "-0.1", "-0.4"] }] }, province_modifier: { sampled: 17, keys: [{ key: "supply_limit_mult", placeholder: "0" }, { key: "travel_danger" }, { key: "county_fertility_growth_add" }] } } }, trait: { sampled: 301, keys: [{ key: "category" }, { key: "ruler_designer_cost", placeholder: "50" }, { key: "desc", block: [{ key: "first_valid", block: [] }] }], blocks: { desc: { sampled: 285, keys: [{ key: "first_valid", block: [{ key: "triggered_desc", block: [] }, { key: "desc" }] }] } } }, trait_portrait_modifier_group: { sampled: 24, keys: [] }, travel_option: { sampled: 29, keys: [{ key: "is_shown", block: [{ key: "is_ruler", choices: ["yes"] }] }, { key: "is_valid", block: [] }, { key: "travel_modifier", block: [{ key: "travel_speed", choices: ["5", "-5", "10", "20", "-10", "-20"] }, { key: "travel_safety", choices: ["-5", "-10", "10", "20", "-20", "5"] }] }, { key: "owner_modifier", block: [] }, { key: "ai_will_do", block: [{ key: "value", choices: ["0", "100", "50", "1", "90"] }] }, { key: "on_applied_effect", block: [{ key: "custom_tooltip" }] }], blocks: { ai_will_do: { sampled: 29, keys: [{ key: "value", choices: ["0", "100", "50", "1", "90"] }] }, is_shown: { sampled: 29, keys: [{ key: "is_ruler", choices: ["yes"] }] }, on_applied_effect: { sampled: 21, keys: [{ key: "custom_tooltip" }] }, travel_modifier: { sampled: 17, keys: [{ key: "travel_speed", choices: ["5", "-5", "10", "20", "-10", "-20"] }, { key: "travel_safety", choices: ["-5", "-10", "10", "20", "-20", "5"] }] } } }, trigger_localization: { sampled: 1640, keys: [{ key: "global" }] }, tutorial_lesson: { sampled: 111, keys: [{ key: "chain" }, { key: "delay", choices: ["0", "5"] }, { key: "start_automatically", choices: ["no", "yes"] }] }, tutorial_lesson_chain: { sampled: 21, keys: [{ key: "save_progress_in_gamestate", choices: ["yes"] }, { key: "trigger", block: [{ key: "is_tutorial_lesson_chain_completed" }] }], blocks: { trigger: { sampled: 21, keys: [{ key: "is_tutorial_lesson_chain_completed" }] } } } } };
|
|
31012
|
+
|
|
30801
31013
|
// src/games/ck3/index.ts
|
|
30802
31014
|
var ck3Profile = {
|
|
30803
31015
|
...ck3Meta,
|
|
@@ -30815,8 +31027,21 @@ var ck3Profile = {
|
|
|
30815
31027
|
scripted_gui: { key: "scope", default: "character" }
|
|
30816
31028
|
},
|
|
30817
31029
|
modifierPlaceholders: CK3_MODIFIER_PLACEHOLDERS,
|
|
31030
|
+
// The three triggers the measured condition shapes need. Over the game's own
|
|
31031
|
+
// 21 dynasty legacy tracks every `is_shown` opens with `has_dlc_feature`, and
|
|
31032
|
+
// over its 105 dynasty perks every `can_be_picked` is either
|
|
31033
|
+
// `has_dlc_feature = <feature>` (10) or `<scripted trigger> = yes` (44).
|
|
31034
|
+
conditionValues: {
|
|
31035
|
+
// triggers.log enumerates the whole set on the trigger itself.
|
|
31036
|
+
has_dlc_feature: { from: "docList" },
|
|
31037
|
+
// `has_game_rule = unrestricted_dynasty_legacies_all` names a SETTING, and
|
|
31038
|
+
// a setting is an inner block of a game_rule (00_game_rules.txt).
|
|
31039
|
+
has_game_rule: { from: "innerKeys", kind: "game_rule", except: ["categories", "default"] },
|
|
31040
|
+
scripted_trigger: { from: "kind", kind: "scripted_trigger" }
|
|
31041
|
+
},
|
|
30818
31042
|
bundledDataTypes: dataTypes_default,
|
|
30819
31043
|
guiSchema: guiSchema_default,
|
|
31044
|
+
skeletons: skeletons_default.kinds,
|
|
30820
31045
|
saveSchema: CK3_SAVE_SCHEMA,
|
|
30821
31046
|
wikiNote: "Source: CK3 wiki (may lag behind the current game version)",
|
|
30822
31047
|
diagnosticSource: "ck3-script"
|
|
@@ -30949,13 +31174,17 @@ var vic3Meta = {
|
|
|
30949
31174
|
engine: "jomini",
|
|
30950
31175
|
// Vic3 mods carry .metadata/metadata.json instead of a launcher .mod file.
|
|
30951
31176
|
descriptor: "metadata",
|
|
30952
|
-
configDirName: ".
|
|
31177
|
+
configDirName: ".px-toolkit",
|
|
31178
|
+
legacyConfigDirName: ".vic3modding",
|
|
30953
31179
|
docsFolderName: "Victoria 3",
|
|
30954
31180
|
// Vic3's `script_docs` writes to Documents/.../docs (like EU5), while
|
|
30955
31181
|
// `dump_data_types` writes to logs/data_types — verified on a live install.
|
|
30956
31182
|
scriptDocsSubdir: "docs",
|
|
30957
31183
|
dataTypesCommand: "dump_data_types",
|
|
30958
31184
|
steamAppId: 529340,
|
|
31185
|
+
// Verified on the live install: a different folder name from CK3's, and only
|
|
31186
|
+
// some DLC have a file there (the rest fall back to their thumbnail.png).
|
|
31187
|
+
dlcIconDir: "gfx/interface/icons/dlc_icons",
|
|
30959
31188
|
eventNamespaces: true,
|
|
30960
31189
|
scaffolds: VIC3_SCAFFOLDS,
|
|
30961
31190
|
// uiFont deliberately absent: this game ships no Gitan (its fonts/ holds
|
|
@@ -47417,6 +47646,9 @@ var guiSchema_default2 = {
|
|
|
47417
47646
|
]
|
|
47418
47647
|
};
|
|
47419
47648
|
|
|
47649
|
+
// data/vic3/skeletons.json
|
|
47650
|
+
var skeletons_default2 = { meta: { generated: "2026-09-03", sources: ["vanilla (2140 files)"], majority: 0.5 }, kinds: { achievement: { sampled: 141, keys: [{ key: "possible", block: [] }, { key: "happened", block: [] }] }, ai_strategy: { sampled: 35, keys: [{ key: "icon" }, { key: "type", choices: ["diplomatic", "political", "administrative"] }, { key: "undesirable_infamy_level", block: [{ key: "value", choices: ["50", "25", "10", "75"] }] }, { key: "unacceptable_infamy_level", block: [{ key: "value", choices: ["100", "50", "25", "75"] }] }, { key: "diplomatic_play_boldness", block: [{ key: "value", choices: ["50", "75", "-25", "25", "-10", "0", "-15"] }] }, { key: "recklessness", block: [{ key: "value", choices: ["0.5", "-0.25", "-0.5", "0.25", "-0.1", "0.1", "1", "1.0"] }] }, { key: "aggression", block: [{ key: "value", choices: ["0.25", "0.5", "1", "0", "-2.0"] }, { key: "if", block: [] }, { key: "multiply", block: [] }] }, { key: "building_group_weights", block: [{ key: "bg_army", choices: ["1.5", "1.25"] }] }, { key: "possible", block: [{ key: "is_subject", choices: ["no", "yes"] }] }, { key: "weight", block: [{ key: "value" }, { key: "if", block: [] }] }], blocks: { aggression: { sampled: 18, keys: [{ key: "value", choices: ["0.25", "0.5", "1", "0", "-2.0"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", placeholder: "10" }] }, { key: "multiply", block: [{ key: "value" }, { key: "multiply", choices: ["-0.1"] }, { key: "add", choices: ["1"] }, { key: "max", choices: ["2.0"] }, { key: "min", choices: ["0.5"] }] }] }, building_group_weights: { sampled: 24, keys: [{ key: "bg_army", choices: ["1.5", "1.25"] }] }, diplomatic_play_boldness: { sampled: 19, keys: [{ key: "value", choices: ["50", "75", "-25", "25", "-10", "0", "-15"] }] }, possible: { sampled: 34, keys: [{ key: "is_subject", choices: ["no", "yes"] }] }, recklessness: { sampled: 19, keys: [{ key: "value", choices: ["0.5", "-0.25", "-0.5", "0.25", "-0.1", "0.1", "1", "1.0"] }] }, unacceptable_infamy_level: { sampled: 19, keys: [{ key: "value", choices: ["100", "50", "25", "75"] }] }, undesirable_infamy_level: { sampled: 19, keys: [{ key: "value", choices: ["50", "25", "10", "75"] }] }, weight: { sampled: 35, keys: [{ key: "value" }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", placeholder: "10" }] }] } } }, alert_group: { sampled: 24, keys: [] }, alert_type: { sampled: 66, keys: [{ key: "script_context" }, { key: "texture" }, { key: "valid", block: [] }, { key: "open_panel" }, { key: "type", choices: ["alert", "important_action", "angry_important_action"] }, { key: "color", choices: ["red", "yellow", "green"] }] }, amendment: { sampled: 67, keys: [{ key: "parent" }, { key: "allowed_laws", block: [] }, { key: "modifier", block: [] }, { key: "possible", block: [{ key: "always", choices: ["yes"] }] }, { key: "would_sponsor", block: [] }, { key: "ai_will_revoke", block: [{ key: "always", choices: ["no", "yes"] }] }, { key: "can_repeal", block: [{ key: "legitimacy", choices: ["legitimacy_to_repeal_amendment"] }] }, { key: "amendment_activism_multiplier", choices: ["0.5", "0.25", "1", "0.75", "0", "0.1", "0.3", "0.50"] }], blocks: { ai_will_revoke: { sampled: 67, keys: [{ key: "always", choices: ["no", "yes"] }] }, can_repeal: { sampled: 67, keys: [{ key: "legitimacy", choices: ["legitimacy_to_repeal_amendment"] }] }, possible: { sampled: 67, keys: [{ key: "always", choices: ["yes"] }] } } }, battle_condition: { sampled: 21, keys: [{ key: "icon" }, { key: "modifier", block: [{ key: "unit_morale_loss_mult", placeholder: "-0.1" }] }, { key: "possible", block: [{ key: "exists", choices: ["scope:character"] }] }, { key: "weight", block: [{ key: "value", choices: ["1", "0.5", "100", "25", "50"] }, { key: "multiply", block: [] }, { key: "if", block: [] }] }], blocks: { modifier: { sampled: 21, keys: [{ key: "unit_morale_loss_mult", placeholder: "-0.1" }] }, possible: { sampled: 18, keys: [{ key: "exists", choices: ["scope:character"] }] }, weight: { sampled: 20, keys: [{ key: "value", choices: ["1", "0.5", "100", "25", "50"] }, { key: "multiply", block: [{ key: "value", choices: ["1"] }, { key: "min", choices: ["0"] }] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", choices: ["2", "1", "0.5"] }] }] } } }, building: { sampled: 115, keys: [{ key: "building_group" }, { key: "icon" }, { key: "city_type", choices: ["city", "farm", "mine", "port", "wood", "none"] }, { key: "expandable", choices: ["no"] }, { key: "levels_per_mesh", choices: ["50", "1", "0", "5"] }, { key: "downsizeable", choices: ["no"] }, { key: "unlocking_technologies", block: [] }, { key: "production_method_groups", block: [] }, { key: "required_construction" }, { key: "ownership_type", choices: ["self", "other"] }, { key: "background" }] }, building_group: { sampled: 69, keys: [{ key: "parent_group" }, { key: "default_building" }] }, buy_package: { sampled: 99, keys: [{ key: "political_strength", placeholder: "0.03" }, { key: "goods", block: [{ key: "popneed_heating", placeholder: "26" }, { key: "popneed_services", placeholder: "103468" }, { key: "popneed_intoxicants", placeholder: "216" }, { key: "popneed_luxury_drinks", placeholder: "101001" }, { key: "popneed_free_movement", placeholder: "101001" }, { key: "popneed_communication", placeholder: "101001" }, { key: "popneed_luxury_food", placeholder: "1009" }, { key: "popneed_luxury_items", placeholder: "107055" }, { key: "popneed_leisure", placeholder: "102" }] }], blocks: { goods: { sampled: 99, keys: [{ key: "popneed_heating", placeholder: "26" }, { key: "popneed_services", placeholder: "103468" }, { key: "popneed_intoxicants", placeholder: "216" }, { key: "popneed_luxury_drinks", placeholder: "101001" }, { key: "popneed_free_movement", placeholder: "101001" }, { key: "popneed_communication", placeholder: "101001" }, { key: "popneed_luxury_food", placeholder: "1009" }, { key: "popneed_luxury_items", placeholder: "107055" }, { key: "popneed_leisure", placeholder: "102" }] } } }, character_interaction: { sampled: 21, keys: [{ key: "clicksound" }, { key: "icon" }, { key: "potential", block: [{ key: "owner", choices: ["scope:actor"] }, { key: "is_ruler_of_own_country", choices: ["no", "yes"] }] }, { key: "possible", block: [{ key: "custom_tooltip", block: [] }] }, { key: "effect", block: [{ key: "owner", block: [] }] }, { key: "cooldown", block: [{ key: "days", choices: ["normal_modifier_time", "short_modifier_time", "long_modifier_time"] }] }, { key: "show_confirmation_box", choices: ["yes"] }, { key: "ai_chance", block: [{ key: "value", choices: ["-50", "0", "1", "-25", "-85", "25"] }, { key: "if", block: [] }] }], blocks: { ai_chance: { sampled: 21, keys: [{ key: "value", choices: ["-50", "0", "1", "-25", "-85", "25"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", placeholder: "25" }] }] }, cooldown: { sampled: 15, keys: [{ key: "days", choices: ["normal_modifier_time", "short_modifier_time", "long_modifier_time"] }] }, effect: { sampled: 21, keys: [{ key: "owner", block: [{ key: "add_modifier", block: [] }] }] }, possible: { sampled: 21, keys: [{ key: "custom_tooltip", block: [{ key: "text" }] }] }, potential: { sampled: 21, keys: [{ key: "owner", choices: ["scope:actor"] }, { key: "is_ruler_of_own_country", choices: ["no", "yes"] }] } } }, character_role: { sampled: 10, keys: [{ key: "texture" }, { key: "type" }, { key: "priority", choices: ["50", "10", "1", "100", "2", "25", "99"] }, { key: "auto_assigned", choices: ["yes"] }, { key: "title_format", choices: ["from_rank", "custom", "from_name", "heir", "ruler"] }, { key: "title_preposition", choices: ["PREP_IN", "PREP_OF"] }, { key: "career_length", block: [] }, { key: "character_modifier", block: [{ key: "character_prominence_add", choices: ["50", "-10", "10", "100", "25"] }] }] }, character_template: { sampled: 2010, keys: [{ key: "first_name" }, { key: "last_name" }, { key: "historical", choices: ["yes", "no"] }, { key: "culture" }, { key: "birth_date" }, { key: "interest_group" }, { key: "ideology" }, { key: "home_region" }, { key: "traits", block: [] }] }, character_trait: { sampled: 121, keys: [{ key: "type", choices: ["skill", "personality", "condition"] }, { key: "texture" }, { key: "character_modifier", block: [{ key: "character_popularity_add", placeholder: "25" }] }, { key: "command_modifier", block: [] }, { key: "country_modifier", block: [] }, { key: "agitator_modifier", block: [] }, { key: "interest_group_modifier", block: [] }, { key: "possible", block: [] }, { key: "replace", block: [] }, { key: "weight", block: [{ key: "value" }, { key: "if", block: [] }] }, { key: "value", choices: ["3", "2", "1"] }], blocks: { character_modifier: { sampled: 91, keys: [{ key: "character_popularity_add", placeholder: "25" }] }, weight: { sampled: 65, keys: [{ key: "value" }, { key: "if", block: [{ key: "limit", block: [] }, { key: "multiply", placeholder: "2" }] }] } } }, combat_unit_type: { sampled: 19, keys: [{ key: "group", choices: ["combat_unit_group_infantry", "combat_unit_group_artillery", "combat_unit_group_cavalry", "combat_unit_group_marines"] }, { key: "max_manpower", choices: ["1000"] }, { key: "supply_capacity", placeholder: "40" }, { key: "upkeep_modifier", block: [{ key: "goods_input_small_arms_add", choices: ["2", "3", "1", "1.5", "2.5", "4"] }, { key: "goods_input_ammunition_add", choices: ["3", "2", "4", "1", "1.5"] }] }, { key: "battle_modifier", block: [{ key: "unit_offense_add", placeholder: "25" }, { key: "unit_defense_add", placeholder: "25" }, { key: "unit_morale_loss_add", choices: ["10", "8", "6", "4", "15"] }, { key: "unit_naval_invasion_efficiency_mult", choices: ["-0.25"] }] }, { key: "unlocking_technologies", block: [] }, { key: "combat_unit_image", block: [{ key: "trigger", block: [] }, { key: "texture" }] }, { key: "upgrades", block: [] }], blocks: { battle_modifier: { sampled: 19, keys: [{ key: "unit_offense_add", placeholder: "25" }, { key: "unit_defense_add", placeholder: "25" }, { key: "unit_morale_loss_add", choices: ["10", "8", "6", "4", "15"] }, { key: "unit_naval_invasion_efficiency_mult", choices: ["-0.25"] }] }, combat_unit_image: { sampled: 77, keys: [{ key: "trigger", block: [{ key: "has_culture_graphics", choices: ["african", "arabic", "east_asian", "south_asian", "decentralised_americas", "polynesian"] }] }, { key: "texture" }] }, upkeep_modifier: { sampled: 19, keys: [{ key: "goods_input_small_arms_add", choices: ["2", "3", "1", "1.5", "2.5", "4"] }, { key: "goods_input_ammunition_add", choices: ["3", "2", "4", "1", "1.5"] }] } } }, commander_order: { sampled: 12, keys: [{ key: "texture" }, { key: "military_type", choices: ["army"] }, { key: "behavior", choices: ["advance", "defend"] }, { key: "visible", block: [{ key: "has_role_of_type", choices: ["general"] }] }, { key: "possible", block: [{ key: "has_role_of_type", choices: ["general"] }] }, { key: "modifier", block: [{ key: "character_advancement_speed_add", choices: ["2", "7", "3", "4", "5"] }] }, { key: "entity_animation", choices: ["advance", "defend"] }, { key: "clicksound" }, { key: "experience", choices: ["0.1"] }, { key: "ai_weight", block: [{ key: "value", choices: ["2", "1"] }] }], blocks: { ai_weight: { sampled: 12, keys: [{ key: "value", choices: ["2", "1"] }] }, modifier: { sampled: 12, keys: [{ key: "character_advancement_speed_add", choices: ["2", "7", "3", "4", "5"] }] }, possible: { sampled: 12, keys: [{ key: "has_role_of_type", choices: ["general"] }] }, visible: { sampled: 12, keys: [{ key: "has_role_of_type", choices: ["general"] }] } } }, company_type: { sampled: 221, keys: [{ key: "icon" }, { key: "background" }, { key: "flavored_company", choices: ["yes", "no"] }, { key: "preferred_headquarters", block: [] }, { key: "building_types", block: [] }, { key: "extension_building_types", block: [] }, { key: "possible_prestige_goods", block: [] }, { key: "potential", block: [{ key: "has_interest_marker_in_region" }] }, { key: "attainable", block: [{ key: "hidden_trigger", block: [] }] }, { key: "possible", block: [{ key: "any_scope_state", block: [] }] }, { key: "prosperity_modifier", block: [] }, { key: "ai_will_do", block: [{ key: "any_scope_state", block: [] }] }, { key: "ai_construction_targets", block: [] }, { key: "ai_weight", block: [{ key: "value", choices: ["3", "100"] }] }], blocks: { ai_weight: { sampled: 195, keys: [{ key: "value", choices: ["3", "100"] }] }, ai_will_do: { sampled: 221, keys: [{ key: "any_scope_state", block: [{ key: "state_region" }, { key: "is_incorporated", choices: ["yes"] }] }] }, attainable: { sampled: 181, keys: [{ key: "hidden_trigger", block: [{ key: "any_scope_state", block: [] }] }] }, possible: { sampled: 221, keys: [{ key: "any_scope_state", block: [{ key: "state_region" }, { key: "is_incorporated", choices: ["yes"] }, { key: "any_scope_building", block: [] }] }] }, potential: { sampled: 196, keys: [{ key: "has_interest_marker_in_region" }] } } }, country_definition: { sampled: 830, keys: [{ key: "color", block: [] }, { key: "country_type", choices: ["unrecognized", "recognized", "decentralized", "colonial", "company"] }, { key: "tier", choices: ["principality", "kingdom", "empire", "grand_principality", "city_state", "hegemony"] }, { key: "cultures", block: [] }, { key: "capital" }] }, culture: { sampled: 317, keys: [{ key: "color", block: [] }, { key: "religion" }, { key: "heritage" }, { key: "language" }, { key: "traditions", block: [] }, { key: "male_common_first_names", block: [] }, { key: "female_common_first_names", block: [] }, { key: "noble_last_names", block: [] }, { key: "common_last_names", block: [] }, { key: "ethnicities", block: [{ key: "1" }] }, { key: "graphics" }, { key: "seal_and_signature_texture" }], blocks: { ethnicities: { sampled: 317, keys: [{ key: "1" }] } } }, culture_graphics: { sampled: 10, keys: [] }, customizable_localization: { sampled: 480, keys: [{ key: "type" }, { key: "text", block: [{ key: "trigger", block: [] }, { key: "localization_key" }] }, { key: "log_loc_errors", choices: ["no"] }], blocks: { text: { sampled: 14256, keys: [{ key: "trigger", block: [] }, { key: "localization_key" }] } } }, decision: { sampled: 60, keys: [{ key: "is_shown", block: [{ key: "NOT", block: [] }] }, { key: "possible", block: [] }, { key: "when_taken", block: [] }, { key: "ai_chance", block: [{ key: "value", choices: ["0", "10", "1", "100", "-10", "5", "-100", "50"] }] }], blocks: { ai_chance: { sampled: 60, keys: [{ key: "value", choices: ["0", "10", "1", "100", "-10", "5", "-100", "50"] }] }, is_shown: { sampled: 60, keys: [{ key: "NOT", block: [{ key: "has_variable" }] }] } } }, decree: { sampled: 11, keys: [{ key: "texture" }, { key: "unlocking_technologies", block: [] }, { key: "state_trigger", block: [] }, { key: "modifier", block: [] }, { key: "cost", choices: ["100", "50"] }, { key: "ai_weight", block: [{ key: "value", choices: ["0", "100", "25"] }, { key: "if", block: [] }] }], blocks: { ai_weight: { sampled: 11, keys: [{ key: "value", choices: ["0", "100", "25"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", choices: ["50", "500", "100", "1000", "75", "25"] }] }] } } }, diplomatic_action: { sampled: 55, keys: [{ key: "groups", block: [] }, { key: "requires_approval", choices: ["no", "yes"] }, { key: "should_notify_third_parties", choices: ["yes", "no"] }, { key: "potential", block: [] }, { key: "selectable", block: [] }, { key: "pact", block: [{ key: "cost", choices: ["10", "0", "100", "50", "25", "150"] }, { key: "relations_progress_per_day", choices: ["1", "-1", "-3", "-4", "3"] }, { key: "actor_can_break", block: [] }, { key: "max_target_involvement", choices: ["1000", "5000", "8000", "2500"] }, { key: "requirement_to_maintain", block: [] }, { key: "target_involvement_applies_to", choices: ["source_country", "mutual"] }, { key: "second_modifier", block: [] }, { key: "manual_break_effect", block: [] }, { key: "auto_break_effect", block: [] }] }, { key: "possible", block: [] }, { key: "ai", block: [{ key: "evaluation_chance", block: [] }, { key: "propose_score", block: [] }, { key: "will_propose", block: [] }] }, { key: "accept_effect", block: [] }], blocks: { ai: { sampled: 52, keys: [{ key: "evaluation_chance", block: [{ key: "value", choices: ["0.25", "0", "0.0", "0.025", "0.1", "0.5", "0.01"] }] }, { key: "propose_score", block: [{ key: "value", choices: ["10", "100", "5", "0", "1", "20", "1000"] }] }, { key: "will_propose", block: [{ key: "OR", block: [] }] }] }, pact: { sampled: 30, keys: [{ key: "cost", choices: ["10", "0", "100", "50", "25", "150"] }, { key: "relations_progress_per_day", choices: ["1", "-1", "-3", "-4", "3"] }, { key: "actor_can_break", block: [{ key: "is_diplomatic_play_committed_participant", choices: ["no"] }] }, { key: "max_target_involvement", choices: ["1000", "5000", "8000", "2500"] }, { key: "requirement_to_maintain", block: [{ key: "trigger", block: [] }] }, { key: "target_involvement_applies_to", choices: ["source_country", "mutual"] }, { key: "second_modifier", block: [] }, { key: "manual_break_effect", block: [] }, { key: "auto_break_effect", block: [{ key: "create_bidirectional_truce", block: [] }] }] } } }, diplomatic_catalyst: { sampled: 77, keys: [{ key: "category" }, { key: "political_lobby_creation", block: [{ key: "lobby_anti_country", block: [] }] }, { key: "ai_country_goal_recalculation", block: [{ key: "type", choices: ["more_hostile", "more_friendly", "only_hostile", "all", "only_friendly", "not_hostile"] }, { key: "chance", block: [] }] }], blocks: { ai_country_goal_recalculation: { sampled: 60, keys: [{ key: "type", choices: ["more_hostile", "more_friendly", "only_hostile", "all", "only_friendly", "not_hostile"] }, { key: "chance", block: [{ key: "value" }, { key: "if", block: [] }, { key: "else_if", block: [] }] }] }, political_lobby_creation: { sampled: 44, keys: [{ key: "lobby_anti_country", block: [{ key: "value", placeholder: "0.05" }, { key: "if", block: [] }, { key: "else_if", block: [] }] }] } } }, diplomatic_catalyst_category: { sampled: 35, keys: [{ key: "lobby_formation_reason", choices: ["diplomacy", "aggression", "defense", "ideology", "economy", "funded"] }, { key: "duration", block: [{ key: "years", choices: ["5", "10", "2", "20", "1", "100"] }] }], blocks: { duration: { sampled: 35, keys: [{ key: "years", choices: ["5", "10", "2", "20", "1", "100"] }] } } }, diplomatic_play: { sampled: 52, keys: [{ key: "war_goal" }, { key: "texture" }, { key: "possible", block: [{ key: "NOT", block: [] }] }, { key: "ai_acceptance_max", choices: ["100", "90", "75"] }, { key: "selectable_in_lens", block: [{ key: "always", choices: ["no"] }] }, { key: "on_weekly_pulse", block: [] }, { key: "on_war_begins", block: [] }, { key: "on_war_end", block: [] }], blocks: { possible: { sampled: 52, keys: [{ key: "NOT", block: [{ key: "is_country_type", choices: ["decentralized"] }] }] }, selectable_in_lens: { sampled: 28, keys: [{ key: "always", choices: ["no"] }] } } }, discrimination_trait: { sampled: 324, keys: [{ key: "type", choices: ["language", "heritage", "tradition"] }, { key: "trait_group" }] }, discrimination_trait_group: { sampled: 89, keys: [{ key: "type", choices: ["language", "heritage"] }] }, dna: { sampled: 583, keys: [{ key: "portrait_info", block: [{ key: "genes", block: [] }] }, { key: "enabled", choices: ["yes"] }], blocks: { portrait_info: { sampled: 583, keys: [{ key: "genes", block: [{ key: "hair_color", block: [] }, { key: "skin_color", block: [] }, { key: "eye_color", block: [] }, { key: "gene_cheek_fat", block: [] }, { key: "gene_cheek_forward", block: [] }, { key: "gene_cheek_height", block: [] }, { key: "gene_cheek_prom", block: [] }, { key: "gene_cheek_width", block: [] }, { key: "gene_chin_forward", block: [] }, { key: "gene_chin_height", block: [] }, { key: "gene_chin_width", block: [] }, { key: "gene_ear_angle", block: [] }, { key: "gene_ear_inner_shape", block: [] }, { key: "gene_ear_lower_bend", block: [] }, { key: "gene_ear_out", block: [] }, { key: "gene_ear_size", block: [] }, { key: "gene_ear_upper_bend", block: [] }, { key: "gene_eye_angle", block: [] }, { key: "gene_eye_depth", block: [] }, { key: "gene_eye_distance", block: [] }, { key: "gene_eye_height", block: [] }, { key: "gene_eye_shut", block: [] }, { key: "gene_eye_corner_def", block: [] }, { key: "gene_eye_corner_depth_min", block: [] }, { key: "gene_eye_fold_droop", block: [] }, { key: "gene_eye_fold_shape", block: [] }, { key: "gene_eye_size", block: [] }, { key: "gene_eye_upper_lid_size", block: [] }, { key: "gene_forehead_angle", block: [] }, { key: "gene_forehead_brow_curve", block: [] }, { key: "gene_forehead_brow_forward", block: [] }, { key: "gene_forehead_brow_height", block: [] }, { key: "gene_forehead_brow_inner_height", block: [] }, { key: "gene_forehead_brow_outer_height", block: [] }, { key: "gene_forehead_brow_width", block: [] }, { key: "gene_forehead_height", block: [] }, { key: "gene_forehead_roundness", block: [] }, { key: "gene_forehead_width", block: [] }, { key: "gene_head_height", block: [] }, { key: "gene_head_profile", block: [] }, { key: "gene_head_top_height", block: [] }, { key: "gene_head_top_width", block: [] }, { key: "gene_head_width", block: [] }, { key: "gene_jaw_angle", block: [] }, { key: "gene_jaw_def", block: [] }, { key: "gene_jaw_forward", block: [] }, { key: "gene_jaw_height", block: [] }, { key: "gene_jaw_width", block: [] }, { key: "gene_mouth_corner_height", block: [] }, { key: "gene_mouth_forward", block: [] }, { key: "gene_mouth_height", block: [] }, { key: "gene_mouth_lower_lip_def", block: [] }, { key: "gene_mouth_lower_lip_full", block: [] }, { key: "gene_mouth_lower_lip_pads", block: [] }, { key: "gene_mouth_lower_lip_size", block: [] }, { key: "gene_mouth_lower_lip_width", block: [] }, { key: "gene_mouth_open", block: [] }, { key: "gene_mouth_philtrum_curve", block: [] }, { key: "gene_mouth_philtrum_def", block: [] }, { key: "gene_mouth_philtrum_width", block: [] }, { key: "gene_mouth_upper_lip_curve", block: [] }, { key: "gene_mouth_upper_lip_def", block: [] }, { key: "gene_mouth_upper_lip_full", block: [] }, { key: "gene_mouth_upper_lip_width", block: [] }, { key: "gene_mouth_upper_lip_size", block: [] }, { key: "gene_mouth_width", block: [] }, { key: "gene_nose_curve", block: [] }, { key: "gene_nose_forward", block: [] }, { key: "gene_nose_hawk", block: [] }, { key: "gene_nose_height", block: [] }, { key: "gene_nose_length", block: [] }, { key: "gene_nose_nostril_angle", block: [] }, { key: "gene_nose_nostril_height", block: [] }, { key: "gene_nose_nostril_width", block: [] }, { key: "gene_nose_ridge_angle", block: [] }, { key: "gene_nose_ridge_def", block: [] }, { key: "gene_nose_ridge_def_min", block: [] }, { key: "gene_nose_ridge_width", block: [] }, { key: "gene_nose_size", block: [] }, { key: "gene_nose_tip_angle", block: [] }, { key: "gene_nose_tip_forward", block: [] }, { key: "gene_nose_tip_width", block: [] }, { key: "gene_neck_length", block: [] }, { key: "gene_neck_width", block: [] }, { key: "gene_bs_body_type", block: [] }, { key: "gene_height", block: [] }, { key: "gene_age", block: [] }, { key: "gene_old_ears", block: [] }, { key: "gene_old_eyes", block: [] }, { key: "gene_old_forehead", block: [] }, { key: "gene_old_mouth", block: [] }, { key: "gene_old_nose", block: [] }, { key: "gene_complexion", block: [] }, { key: "gene_stubble", block: [] }, { key: "gene_crowfeet", block: [] }, { key: "gene_face_dacals", block: [] }, { key: "gene_frown", block: [] }, { key: "gene_surprise", block: [] }, { key: "gene_eyebrows_shape", block: [] }, { key: "gene_eyebrows_fullness", block: [] }, { key: "hairstyles", block: [] }, { key: "beards", block: [] }, { key: "mustaches", block: [] }, { key: "props", block: [] }, { key: "eye_accessory", block: [] }, { key: "eye_lashes_accessory", block: [] }, { key: "teeth_accessory", block: [] }] }] } } }, dynamic_company_name: { sampled: 10, keys: [{ key: "uses_plural_naming", choices: ["no", "yes"] }, { key: "use_for_flavored_companies", choices: ["no"] }, { key: "weight", block: [{ key: "value", choices: ["1"] }] }], blocks: { weight: { sampled: 10, keys: [{ key: "value", choices: ["1"] }] } } }, dynamic_country_map_color: { sampled: 75, keys: [{ key: "color" }, { key: "possible", block: [{ key: "exists" }] }], blocks: { possible: { sampled: 75, keys: [{ key: "exists" }] } } }, dynamic_treaty_name: { sampled: 34, keys: [{ key: "trigger", block: [{ key: "any_scope_article_option", block: [] }] }, { key: "weight", block: [{ key: "value", choices: ["10", "100", "300", "200", "10000"] }] }], blocks: { trigger: { sampled: 34, keys: [{ key: "any_scope_article_option", block: [{ key: "OR", block: [] }] }] }, weight: { sampled: 33, keys: [{ key: "value", choices: ["10", "100", "300", "200", "10000"] }] } } }, effect_localization: { sampled: 297, keys: [{ key: "global" }, { key: "third" }] }, ethnicity: { sampled: 36, keys: [{ key: "template", choices: ["ethnicity_template", "caucasian_base", "slavic", "caucasian_brown_hair", "caucasian_dark_hair", "caucasian_ginger", "indian"] }, { key: "skin_color", block: [{ key: "10", block: [] }] }, { key: "eye_color", block: [] }, { key: "hair_color", block: [] }, { key: "gene_chin_forward", block: [{ key: "84", block: [] }] }, { key: "gene_chin_height", block: [{ key: "84", block: [] }] }, { key: "gene_chin_width", block: [{ key: "64", block: [] }] }, { key: "gene_forehead_angle", block: [{ key: "64", block: [] }] }, { key: "gene_forehead_height", block: [{ key: "40", block: [] }] }, { key: "gene_head_top_width", block: [{ key: "5", block: [] }, { key: "25", block: [] }] }, { key: "gene_jaw_angle", block: [{ key: "64", block: [] }] }, { key: "gene_jaw_forward", block: [{ key: "84", block: [] }] }, { key: "gene_jaw_height", block: [{ key: "84", block: [] }] }, { key: "gene_jaw_width", block: [{ key: "64", block: [] }] }, { key: "gene_mouth_corner_height", block: [{ key: "74", block: [] }] }, { key: "gene_mouth_lower_lip_size", block: [{ key: "84", block: [] }] }, { key: "gene_mouth_upper_lip_size", block: [{ key: "84", block: [] }] }, { key: "gene_cheek_fat", block: [{ key: "64", block: [] }] }, { key: "gene_cheek_height", block: [{ key: "84", block: [] }] }, { key: "gene_cheek_width", block: [{ key: "84", block: [] }] }, { key: "gene_jaw_def", block: [{ key: "64", block: [] }] }, { key: "gene_mouth_lower_lip_def", block: [{ key: "64", block: [] }] }, { key: "gene_mouth_lower_lip_full", block: [] }, { key: "gene_mouth_lower_lip_pads", block: [{ key: "64", block: [] }] }, { key: "gene_mouth_lower_lip_width", block: [{ key: "84", block: [] }] }, { key: "gene_mouth_philtrum_curve", block: [{ key: "64", block: [] }] }, { key: "gene_mouth_philtrum_def", block: [{ key: "64", block: [] }] }, { key: "gene_mouth_philtrum_width", block: [{ key: "84", block: [] }] }, { key: "gene_mouth_upper_lip_curve", block: [{ key: "64", block: [] }] }, { key: "gene_mouth_upper_lip_def", block: [{ key: "64", block: [] }] }, { key: "gene_mouth_upper_lip_full", block: [] }, { key: "gene_nose_curve", block: [{ key: "74", block: [] }] }, { key: "gene_nose_forward", block: [{ key: "20", block: [] }] }, { key: "gene_nose_hawk", block: [{ key: "84", block: [] }] }, { key: "gene_nose_height", block: [{ key: "1", block: [] }] }, { key: "gene_nose_length", block: [{ key: "84", block: [] }] }, { key: "gene_nose_nostril_height", block: [{ key: "1", block: [] }, { key: "84", block: [] }] }, { key: "gene_nose_nostril_width", block: [] }, { key: "gene_nose_ridge_angle", block: [{ key: "1", block: [] }] }, { key: "gene_nose_ridge_def", block: [{ key: "84", block: [] }] }, { key: "gene_nose_ridge_width", block: [] }, { key: "gene_nose_size", block: [] }, { key: "gene_nose_tip_angle", block: [] }, { key: "gene_nose_tip_forward", block: [] }, { key: "gene_nose_tip_width", block: [{ key: "84", block: [] }] }, { key: "gene_bs_body_type", block: [{ key: "20", block: [] }] }, { key: "gene_height", block: [{ key: "84", block: [] }] }, { key: "gene_old_eyes", block: [{ key: "10", block: [] }] }, { key: "gene_old_forehead", block: [{ key: "10", block: [] }] }, { key: "gene_old_mouth", block: [{ key: "10", block: [] }] }, { key: "gene_complexion", block: [{ key: "10", block: [] }] }, { key: "gene_crowfeet", block: [{ key: "9", block: [] }, { key: "1", block: [] }] }, { key: "gene_eyebrows_shape", block: [{ key: "10", block: [] }, { key: "5", block: [] }] }, { key: "gene_frown", block: [{ key: "8", block: [] }, { key: "2", block: [] }] }, { key: "gene_eyebrows_fullness", block: [{ key: "10", block: [] }, { key: "15", block: [] }, { key: "5", block: [] }] }, { key: "gene_surprise", block: [{ key: "9", block: [] }, { key: "1", block: [] }] }, { key: "hairstyles", block: [{ key: "10", block: [] }] }, { key: "beards", block: [{ key: "10", block: [] }] }, { key: "mustaches", block: [{ key: "10", block: [] }] }], blocks: { beards: { sampled: 21, keys: [{ key: "10", block: [{ key: "name", choices: ["european_beards", "african_beards", "all_beards", "arabic_beards", "asian_beards", "no_beard", "frankenstein_scars", "indian_beards"] }, { key: "range", block: [] }] }] }, gene_bs_body_type: { sampled: 20, keys: [{ key: "20", block: [{ key: "name", choices: ["body_fat_head_fat_full", "body_fat_head_fat_low", "body_fat_head_fat_medium"] }, { key: "range", block: [] }] }] }, gene_cheek_fat: { sampled: 18, keys: [{ key: "64", block: [{ key: "name", choices: ["cheek_fat"] }, { key: "range", block: [] }] }] }, gene_cheek_height: { sampled: 18, keys: [{ key: "84", block: [{ key: "name", choices: ["cheek_height"] }, { key: "range", block: [] }] }] }, gene_cheek_width: { sampled: 18, keys: [{ key: "84", block: [{ key: "name", choices: ["cheek_width"] }, { key: "range", block: [] }] }] }, gene_chin_forward: { sampled: 18, keys: [{ key: "84", block: [{ key: "name", choices: ["chin_forward"] }, { key: "range", block: [] }] }] }, gene_chin_height: { sampled: 18, keys: [{ key: "84", block: [{ key: "name", choices: ["chin_height"] }, { key: "range", block: [] }] }] }, gene_chin_width: { sampled: 18, keys: [{ key: "64", block: [{ key: "name", choices: ["chin_width"] }, { key: "range", block: [] }] }] }, gene_complexion: { sampled: 20, keys: [{ key: "10", block: [{ key: "name", choices: ["complexion_01", "complexion_02", "complexion_03"] }, { key: "range", block: [] }] }] }, gene_crowfeet: { sampled: 20, keys: [{ key: "9", block: [{ key: "name", choices: ["crowfeet_01", "crowfeet_02", "crowfeet_03"] }, { key: "range", block: [] }] }, { key: "1", block: [{ key: "name", choices: ["crowfeet_01", "crowfeet_02", "crowfeet_03"] }, { key: "range", block: [] }] }] }, gene_eyebrows_fullness: { sampled: 29, keys: [{ key: "10", block: [{ key: "name", choices: ["layer_2_avg_thickness", "layer_2_low_thickness", "layer_2_lower_thickness"] }, { key: "range", block: [] }] }, { key: "15", block: [{ key: "name", choices: ["layer_2_avg_thickness", "layer_2_low_thickness", "layer_2_lower_thickness"] }, { key: "range", block: [] }] }, { key: "5", block: [{ key: "name", choices: ["layer_2_high_thickness"] }, { key: "range", block: [] }] }] }, gene_eyebrows_shape: { sampled: 29, keys: [{ key: "10", block: [{ key: "name" }, { key: "range", block: [] }] }, { key: "5", block: [{ key: "name", choices: ["avg_spacing_high_thickness", "far_spacing_high_thickness", "avg_spacing_low_thickness", "avg_spacing_lower_thickness", "close_spacing_avg_thickness", "far_spacing_lower_thickness", "avg_spacing_avg_thickness"] }, { key: "range", block: [] }] }] }, gene_forehead_angle: { sampled: 18, keys: [{ key: "64", block: [{ key: "name", choices: ["forehead_angle"] }, { key: "range", block: [] }] }] }, gene_forehead_height: { sampled: 20, keys: [{ key: "40", block: [{ key: "name", choices: ["forehead_height"] }, { key: "range", block: [] }] }] }, gene_frown: { sampled: 20, keys: [{ key: "8", block: [{ key: "name", choices: ["frown_01", "frown_02", "frown_03"] }, { key: "range", block: [] }] }, { key: "2", block: [{ key: "name", choices: ["frown_01", "frown_02", "frown_03"] }, { key: "range", block: [] }] }] }, gene_head_top_width: { sampled: 18, keys: [{ key: "5", block: [{ key: "name", choices: ["head_top_width"] }, { key: "range", block: [] }] }, { key: "25", block: [{ key: "name", choices: ["head_top_width"] }, { key: "range", block: [] }] }] }, gene_height: { sampled: 20, keys: [{ key: "84", block: [{ key: "name", choices: ["normal_height"] }, { key: "range", block: [] }] }] }, gene_jaw_angle: { sampled: 18, keys: [{ key: "64", block: [{ key: "name", choices: ["jaw_angle"] }, { key: "range", block: [] }] }] }, gene_jaw_def: { sampled: 18, keys: [{ key: "64", block: [{ key: "name", choices: ["jaw_def"] }, { key: "range", block: [] }] }] }, gene_jaw_forward: { sampled: 18, keys: [{ key: "84", block: [{ key: "name", choices: ["jaw_forward"] }, { key: "range", block: [] }] }] }, gene_jaw_height: { sampled: 18, keys: [{ key: "84", block: [{ key: "name", choices: ["jaw_height"] }, { key: "range", block: [] }] }] }, gene_jaw_width: { sampled: 18, keys: [{ key: "64", block: [{ key: "name", choices: ["jaw_width"] }, { key: "range", block: [] }] }] }, gene_mouth_corner_height: { sampled: 18, keys: [{ key: "74", block: [{ key: "name", choices: ["mouth_corner_height"] }, { key: "range", block: [] }] }] }, gene_mouth_lower_lip_def: { sampled: 18, keys: [{ key: "64", block: [{ key: "name", choices: ["mouth_lower_lip_def"] }, { key: "range", block: [] }] }] }, gene_mouth_lower_lip_pads: { sampled: 18, keys: [{ key: "64", block: [{ key: "name", choices: ["mouth_lower_lip_pads"] }, { key: "range", block: [] }] }] }, gene_mouth_lower_lip_size: { sampled: 19, keys: [{ key: "84", block: [{ key: "name", choices: ["mouth_lower_lip_size"] }, { key: "range", block: [] }] }] }, gene_mouth_lower_lip_width: { sampled: 18, keys: [{ key: "84", block: [{ key: "name", choices: ["mouth_lower_lip_width"] }, { key: "range", block: [] }] }] }, gene_mouth_philtrum_curve: { sampled: 18, keys: [{ key: "64", block: [{ key: "name", choices: ["mouth_philtrum_curve"] }, { key: "range", block: [] }] }] }, gene_mouth_philtrum_def: { sampled: 18, keys: [{ key: "64", block: [{ key: "name", choices: ["mouth_philtrum_def"] }, { key: "range", block: [] }] }] }, gene_mouth_philtrum_width: { sampled: 18, keys: [{ key: "84", block: [{ key: "name", choices: ["mouth_philtrum_width"] }, { key: "range", block: [] }] }] }, gene_mouth_upper_lip_curve: { sampled: 18, keys: [{ key: "64", block: [{ key: "name", choices: ["mouth_upper_lip_curve"] }, { key: "range", block: [] }] }] }, gene_mouth_upper_lip_def: { sampled: 18, keys: [{ key: "64", block: [{ key: "name", choices: ["mouth_upper_lip_def"] }, { key: "range", block: [] }] }] }, gene_mouth_upper_lip_size: { sampled: 19, keys: [{ key: "84", block: [{ key: "name", choices: ["mouth_upper_lip_size"] }, { key: "range", block: [] }] }] }, gene_nose_curve: { sampled: 18, keys: [{ key: "74", block: [{ key: "name", choices: ["nose_curve"] }, { key: "range", block: [] }] }] }, gene_nose_forward: { sampled: 18, keys: [{ key: "20", block: [{ key: "name", choices: ["nose_forward"] }, { key: "range", block: [] }] }] }, gene_nose_hawk: { sampled: 18, keys: [{ key: "84", block: [{ key: "name", choices: ["nose_hawk"] }, { key: "range", block: [] }] }] }, gene_nose_height: { sampled: 18, keys: [{ key: "1", block: [{ key: "name", choices: ["nose_height"] }, { key: "range", block: [] }] }] }, gene_nose_length: { sampled: 18, keys: [{ key: "84", block: [{ key: "name", choices: ["nose_length"] }, { key: "range", block: [] }] }] }, gene_nose_nostril_height: { sampled: 18, keys: [{ key: "1", block: [{ key: "name", choices: ["nose_nostril_height"] }, { key: "range", block: [] }] }, { key: "84", block: [{ key: "name", choices: ["nose_nostril_height"] }, { key: "range", block: [] }] }] }, gene_nose_ridge_angle: { sampled: 20, keys: [{ key: "1", block: [{ key: "name", choices: ["nose_ridge_angle"] }, { key: "range", block: [] }] }] }, gene_nose_ridge_def: { sampled: 20, keys: [{ key: "84", block: [{ key: "name", choices: ["nose_ridge_def"] }, { key: "range", block: [] }] }] }, gene_nose_tip_width: { sampled: 20, keys: [{ key: "84", block: [{ key: "name", choices: ["nose_tip_width"] }, { key: "range", block: [] }] }] }, gene_old_eyes: { sampled: 20, keys: [{ key: "10", block: [{ key: "name", choices: ["old_eyes_01", "old_eyes_02", "old_eyes_03"] }, { key: "range", block: [] }] }] }, gene_old_forehead: { sampled: 20, keys: [{ key: "10", block: [{ key: "name", choices: ["old_forehead_01", "old_forehead_02", "old_forehead_03"] }, { key: "range", block: [] }] }] }, gene_old_mouth: { sampled: 20, keys: [{ key: "10", block: [{ key: "name", choices: ["old_mouth_01", "old_mouth_02", "old_mouth_03"] }, { key: "range", block: [] }] }] }, gene_surprise: { sampled: 20, keys: [{ key: "9", block: [{ key: "name", choices: ["surprise_01", "surprise_02", "surprise_03"] }, { key: "range", block: [] }] }, { key: "1", block: [{ key: "name", choices: ["surprise_01", "surprise_02", "surprise_03"] }, { key: "range", block: [] }] }] }, hairstyles: { sampled: 22, keys: [{ key: "10", block: [{ key: "name" }, { key: "range", block: [] }] }] }, mustaches: { sampled: 20, keys: [{ key: "10", block: [{ key: "name", choices: ["european_mustaches", "asian_mustaches", "no_mustache", "african_mustaches", "arabic_mustaches", "indian_mustaches"] }, { key: "range", block: [] }] }] }, skin_color: { sampled: 21, keys: [{ key: "10", block: [] }] } } }, event: { sampled: 2264, keys: [{ key: "type", choices: ["country_event", "state_event"] }, { key: "placement" }, { key: "title" }, { key: "desc" }, { key: "flavor" }, { key: "duration", choices: ["3", "1", "6", "4", "2", "9"] }, { key: "event_image", block: [{ key: "video" }] }, { key: "on_created_soundeffect" }, { key: "icon" }, { key: "trigger", block: [] }, { key: "cooldown", block: [{ key: "days" }] }, { key: "immediate", block: [] }, { key: "option", block: [{ key: "name" }] }], nameFromHeader: "namespace", blocks: { cooldown: { sampled: 1403, keys: [{ key: "days" }] }, event_image: { sampled: 2156, keys: [{ key: "video" }] }, option: { sampled: 4840, keys: [{ key: "name" }] } } }, game_concept: { sampled: 613, keys: [] }, game_rule_category: { sampled: 15, keys: [{ key: "default" }] }, geographic_region: { sampled: 165, keys: [{ key: "short_key" }, { key: "state_regions", block: [] }] }, good: { sampled: 53, keys: [{ key: "texture" }, { key: "cost", placeholder: "30" }, { key: "category", choices: ["industrial", "luxury", "staple", "military"] }, { key: "prestige_factor", choices: ["4", "3", "5", "6", "10", "8", "2"] }, { key: "traded_quantity", placeholder: "5" }, { key: "convoy_cost_multiplier", choices: ["0.5", "0.15", "0.25", "1.0", "1.5", "0.05"] }] }, government_type: { sampled: 444, keys: [{ key: "transfer_of_power", choices: ["hereditary", "dictatorial", "presidential_elective", "parliamentary_elective"] }, { key: "male_ruler" }, { key: "female_ruler" }, { key: "male_heir" }, { key: "female_heir" }, { key: "possible", block: [{ key: "has_law", choices: ["law_type:law_social_monarchy", "law_type:law_monarchy", "law_type:law_colonial_administration", "law_type:law_corporate_state", "law_type:law_autocracy", "law_type:law_technocracy", "law_type:law_bakufu"] }, { key: "NOT", block: [] }, { key: "has_gov_regency", choices: ["no", "yes"] }] }, { key: "on_government_type_change", block: [{ key: "change_to_hereditary", choices: ["yes"] }] }, { key: "on_post_government_type_change", block: [{ key: "post_change_to_hereditary", choices: ["yes"] }] }], blocks: { on_government_type_change: { sampled: 443, keys: [{ key: "change_to_hereditary", choices: ["yes"] }] }, on_post_government_type_change: { sampled: 438, keys: [{ key: "post_change_to_hereditary", choices: ["yes"] }] }, possible: { sampled: 444, keys: [{ key: "has_law", choices: ["law_type:law_social_monarchy", "law_type:law_monarchy", "law_type:law_colonial_administration", "law_type:law_corporate_state", "law_type:law_autocracy", "law_type:law_technocracy", "law_type:law_bakufu"] }, { key: "NOT", block: [{ key: "is_subject_type", choices: ["subject_type_crown_land"] }] }, { key: "has_gov_regency", choices: ["no", "yes"] }] } } }, harvest_condition_type: { sampled: 22, keys: [{ key: "trigger", block: [] }, { key: "incompatible_with" }, { key: "range", block: [{ key: "integer_range", block: [] }] }, { key: "duration", block: [{ key: "fixed_range", block: [] }] }, { key: "modifier", block: [{ key: "building_group_bg_agriculture_throughput_add", choices: ["-0.05", "0.05"] }, { key: "building_group_bg_plantations_throughput_add", choices: ["-0.05", "0.05", "0.1"] }, { key: "building_group_bg_ranching_throughput_add", choices: ["-0.05", "-0.03", "0.03"] }, { key: "state_peasants_consumption_multiplier_add", choices: ["0.03", "0.025", "-0.01", "0.05"] }] }, { key: "intensity", block: [{ key: "fixed_range", block: [] }] }, { key: "chance", block: [{ key: "value", choices: ["0.0025", "0", "0.05", "0.003", "0.0008", "0.0015"] }, { key: "if", block: [] }] }, { key: "color", block: [] }, { key: "icon" }, { key: "map_texture" }, { key: "graphics" }], blocks: { chance: { sampled: 22, keys: [{ key: "value", choices: ["0.0025", "0", "0.05", "0.003", "0.0008", "0.0015"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "multiply", choices: ["1.5", "1.2", "1.3", "1.4", "1.1", "100", "25"] }] }] }, duration: { sampled: 22, keys: [{ key: "fixed_range", block: [{ key: "min", choices: ["36", "24", "12"] }, { key: "max", choices: ["104", "48", "96", "24", "78", "94"] }] }] }, intensity: { sampled: 22, keys: [{ key: "fixed_range", block: [{ key: "min", choices: ["2", "0.5", "3", "0.25", "0.1", "1", "4"] }, { key: "max", choices: ["1", "4", "5", "6", "7", "8"] }] }] }, modifier: { sampled: 22, keys: [{ key: "building_group_bg_agriculture_throughput_add", choices: ["-0.05", "0.05"] }, { key: "building_group_bg_plantations_throughput_add", choices: ["-0.05", "0.05", "0.1"] }, { key: "building_group_bg_ranching_throughput_add", choices: ["-0.05", "-0.03", "0.03"] }, { key: "state_peasants_consumption_multiplier_add", choices: ["0.03", "0.025", "-0.01", "0.05"] }] }, range: { sampled: 22, keys: [{ key: "integer_range", block: [{ key: "min", choices: ["1"] }, { key: "max", choices: ["2", "1", "5"] }] }] } } }, ideology: { sampled: 172, keys: [{ key: "icon" }] }, interest_group_trait: { sampled: 99, keys: [{ key: "icon" }, { key: "min_approval", choices: ["loyal", "happy"] }, { key: "modifier", block: [] }] }, journal_entry: { sampled: 419, keys: [{ key: "icon" }, { key: "group" }, { key: "immediate", block: [] }, { key: "complete", block: [] }, { key: "on_complete", block: [{ key: "trigger_event", block: [] }] }, { key: "weight", placeholder: "1000" }, { key: "should_be_pinned_by_default_uninvolved_or_context", choices: ["yes", "no"] }], blocks: { on_complete: { sampled: 368, keys: [{ key: "trigger_event", block: [{ key: "id" }] }] } } }, journal_entry_group: { sampled: 27, keys: [{ key: "context", choices: ["country", "none"] }, { key: "updates_strategic_region_stances", choices: ["yes"] }] }, law: { sampled: 138, keys: [{ key: "group" }, { key: "icon" }, { key: "progressiveness", placeholder: "0" }, { key: "modifier", block: [] }, { key: "ai_enact_weight_modifier", block: [{ key: "value", choices: ["0"] }, { key: "if", block: [] }] }], blocks: { ai_enact_weight_modifier: { sampled: 136, keys: [{ key: "value", choices: ["0"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", placeholder: "750" }] }] } } }, law_group: { sampled: 26, keys: [{ key: "law_group_category", choices: ["power_structure", "economy", "human_rights"] }, { key: "ideological_opinion_impact", choices: ["0.25", "0.5", "1.0", "2.0", "0.0"] }] }, map_interaction_type: { sampled: 32, keys: [{ key: "mapmode" }, { key: "clicksound" }, { key: "show_interaction_text_on_click", choices: ["yes", "no"] }] }, map_notification_type: { sampled: 23, keys: [{ key: "message" }] }, message: { sampled: 469, keys: [{ key: "type" }, { key: "texture" }, { key: "notification_type", choices: ["feed", "toast", "popup", "none"] }] }, military_formation_flag: { sampled: 30, keys: [{ key: "icon" }, { key: "type", choices: ["army", "navy"] }] }, mobilization_option: { sampled: 18, keys: [{ key: "texture" }, { key: "possible", block: [{ key: "market", block: [] }] }, { key: "on_activate_while_mobilized", block: [{ key: "custom_tooltip", block: [] }] }, { key: "on_deactivate", block: [{ key: "custom_tooltip", block: [] }] }, { key: "unlocking_technologies", block: [] }, { key: "upkeep_modifier", block: [] }, { key: "unit_modifier", block: [] }, { key: "ai_weight", block: [{ key: "value", choices: ["1", "0"] }] }, { key: "group", choices: ["supplements", "reconnaissance", "special_weapons", "supplies", "transport", "medic_support"] }], blocks: { ai_weight: { sampled: 18, keys: [{ key: "value", choices: ["1", "0"] }] }, on_activate_while_mobilized: { sampled: 11, keys: [{ key: "custom_tooltip", block: [{ key: "text", choices: ["mobilization_option_it_hurts_organization_when_you_adjust_equipment_tt", "mobilization_option_it_hurts_organization_to_add_medic_support_tt", "mobilization_option_it_hurts_morale_when_you_force_people_to_march_faster_while_in_combat_tt"] }, { key: "add_organization", block: [] }] }] }, on_deactivate: { sampled: 10, keys: [{ key: "custom_tooltip", block: [{ key: "text", choices: ["mobilization_option_it_hurts_organization_when_you_adjust_equipment_tt", "mobilization_option_it_hurts_morale_and_organization_when_you_remove_medic_support_tt"] }, { key: "add_organization", block: [] }] }] }, possible: { sampled: 17, keys: [{ key: "market", block: [] }] } } }, modifier_type: { sampled: 2362, keys: [{ key: "decimals", choices: ["1", "0", "2"] }, { key: "color", choices: ["good", "neutral", "bad"] }, { key: "game_data", block: [{ key: "ai_value", placeholder: "0" }] }], blocks: { game_data: { sampled: 2188, keys: [{ key: "ai_value", placeholder: "0" }] } } }, objective_subgoal: { sampled: 86, keys: [{ key: "category", choices: ["sgcat_tutorial", "sgcat_great_game", "sgcat_economic_dominance", "sgcat_hegemon", "sgcat_egalitarian_society"] }, { key: "is_repeatable", choices: ["no", "yes"] }, { key: "trigger", block: [] }, { key: "on_start", block: [{ key: "add_journal_entry", block: [] }] }], blocks: { on_start: { sampled: 86, keys: [{ key: "add_journal_entry", block: [{ key: "type" }, { key: "objective_subgoal" }] }] } } }, on_action: { sampled: 262, keys: [{ key: "effect", block: [] }] }, party: { sampled: 12, keys: [{ key: "color", block: [] }, { key: "name", block: [{ key: "first_valid", block: [] }] }, { key: "icon", block: [{ key: "default" }] }, { key: "unlocking_technologies", block: [] }, { key: "available_for_interest_group", block: [{ key: "owner", block: [] }] }, { key: "valid_for_country", block: [{ key: "always", choices: ["yes"] }] }, { key: "join_weight", block: [{ key: "value", block: [] }, { key: "if", block: [] }, { key: "else_if", block: [] }] }], blocks: { available_for_interest_group: { sampled: 12, keys: [{ key: "owner", block: [{ key: "country_has_voting_franchise", choices: ["yes"] }, { key: "OR", block: [] }] }] }, icon: { sampled: 12, keys: [{ key: "default" }] }, join_weight: { sampled: 12, keys: [{ key: "value", block: [{ key: "value", choices: ["-5"] }, { key: "desc", choices: ["base_value"] }] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", block: [] }] }, { key: "else_if", block: [{ key: "limit", block: [] }, { key: "multiply", block: [] }] }] }, name: { sampled: 12, keys: [{ key: "first_valid", block: [{ key: "triggered_desc", block: [] }] }] }, valid_for_country: { sampled: 11, keys: [{ key: "always", choices: ["yes"] }] } } }, political_lobby_appeasement: { sampled: 49, keys: [{ key: "duration_to_show", block: [{ key: "months", choices: ["60", "12"] }] }], blocks: { duration_to_show: { sampled: 49, keys: [{ key: "months", choices: ["60", "12"] }] } } }, political_movement: { sampled: 39, keys: [{ key: "category", choices: ["movement_category_ideological", "movement_category_pan_national", "movement_category_religious", "movement_category_cultural", "movement_category_cultural_majority"] }, { key: "ideology" }, { key: "character_ideologies", block: [] }, { key: "creation_trigger", block: [] }, { key: "creation_weight", block: [{ key: "value", choices: ["100", "1000", "10", "200", "50", "5000"] }, { key: "if", block: [] }] }, { key: "on_created", block: [{ key: "add_movement_enthusiasm_modifier", choices: ["yes"] }] }, { key: "disband_trigger", block: [] }, { key: "character_support_trigger", block: [{ key: "OR", block: [] }] }, { key: "character_support_weight", block: [{ key: "value", choices: ["200", "100", "50", "250"] }, { key: "if", block: [] }] }, { key: "pop_support_trigger", block: [] }, { key: "pop_support_factors", block: [] }, { key: "pop_support_weight", block: [{ key: "if", block: [] }, { key: "add", block: [] }, { key: "else_if", block: [] }, { key: "multiply", block: [] }] }, { key: "revolution", block: [{ key: "possible", block: [] }, { key: "weight", block: [] }, { key: "state_weight", block: [] }] }, { key: "secession", block: [{ key: "possible", block: [] }, { key: "weight", block: [] }, { key: "state_weight", block: [] }] }, { key: "additional_radicalism_factors", block: [{ key: "if", block: [] }] }], blocks: { additional_radicalism_factors: { sampled: 39, keys: [{ key: "if", block: [{ key: "limit", block: [] }, { key: "add", block: [] }] }] }, character_support_trigger: { sampled: 39, keys: [{ key: "OR", block: [{ key: "has_ideology" }] }] }, character_support_weight: { sampled: 39, keys: [{ key: "value", choices: ["200", "100", "50", "250"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "multiply", block: [] }] }] }, creation_weight: { sampled: 39, keys: [{ key: "value", choices: ["100", "1000", "10", "200", "50", "5000"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "multiply", block: [] }] }] }, on_created: { sampled: 38, keys: [{ key: "add_movement_enthusiasm_modifier", choices: ["yes"] }] }, pop_support_weight: { sampled: 39, keys: [{ key: "if", block: [{ key: "limit", block: [] }] }, { key: "add", block: [{ key: "desc", choices: ["URBAN_STATE", "POP_BASE_SUPPORT", "POP_LOYALISTS", "SLAVE_STATE"] }, { key: "value", choices: ["10", "0.5", "5", "1", "3", "9", "pop_loyalist_fraction"] }, { key: "multiply", choices: ["state.state_urbanization_rate", "10"] }] }, { key: "else_if", block: [{ key: "limit", block: [] }] }, { key: "multiply", block: [{ key: "desc", choices: ["POP_LITERACY", "POP_RADICALS", "POP_CULTURE_FERVOR", "ACCEPTANCE", "BACKWARDSNESS", "LOYALTY_OF_STATE_DAIMYO", "POP_ACCEPTANCE"] }, { key: "value" }, { key: "add", choices: ["0.10", "1", "0.2", "0.15", "0.20", "0.25", "0.50", "state.state_daimyo_loyalty"] }] }] }, revolution: { sampled: 35, keys: [{ key: "possible", block: [{ key: "political_movement_support", choices: ["0.05", "0.10"] }] }, { key: "weight", block: [{ key: "value", choices: ["100", "1000", "50"] }] }, { key: "state_weight", block: [{ key: "value", choices: ["1", "0.25", "state_urbanization_rate", "0.5", "0"] }, { key: "add", choices: ["scope:clout"] }, { key: "subtract", choices: ["this.loyalists", "state_urbanization_rate"] }, { key: "if", block: [] }] }] }, secession: { sampled: 36, keys: [{ key: "possible", block: [{ key: "political_movement_support", choices: ["0.05", "0.15"] }] }, { key: "weight", block: [{ key: "value", choices: ["1000", "50", "10", "150"] }] }, { key: "state_weight", block: [{ key: "value", choices: ["1", "state_urbanization_rate", "0", "0.25", "1.5"] }, { key: "if", block: [] }, { key: "subtract", choices: ["this.loyalists", "state_urbanization_rate"] }] }] } } }, political_movement_pop_support: { sampled: 60, keys: [{ key: "name" }] }, pop_need: { sampled: 15, keys: [{ key: "default" }, { key: "entry", block: [{ key: "goods" }, { key: "weight", placeholder: "1" }, { key: "max_supply_share", choices: ["0.75", "0.5", "1.0", "0.25", "0.9", "0.2", "0.33", "0.8"] }, { key: "min_supply_share", choices: ["0.0", "0.1", "0.10"] }] }], blocks: { entry: { sampled: 52, keys: [{ key: "goods" }, { key: "weight", placeholder: "1" }, { key: "max_supply_share", choices: ["0.75", "0.5", "1.0", "0.25", "0.9", "0.2", "0.33", "0.8"] }, { key: "min_supply_share", choices: ["0.0", "0.1", "0.10"] }] } } }, pop_type: { sampled: 15, keys: [{ key: "texture" }, { key: "color", block: [] }, { key: "start_quality_of_life", choices: ["10", "7", "20", "5", "1"] }, { key: "wage_weight", choices: ["1.5", "3", "5", "4", "0", "0.2", "1", "2"] }, { key: "paid_private_wage", choices: ["yes", "no"] }, { key: "literacy_target", choices: ["0.80", "0.20", "0.10", "0.40", "0.50", "0.60", "0.70"] }, { key: "dependent_wage", choices: ["0.5", "0.0", "0.25"] }, { key: "unemployment", choices: ["yes", "no"] }, { key: "political_engagement_base", choices: ["0.7", "0.1", "0.5", "0.20", "0.25", "0.3", "0.40"] }, { key: "political_engagement_literacy_factor", choices: ["0.3", "0.6", "0.5", "0.40", "0.7", "0.8", "1.0"] }, { key: "political_engagement_mult", block: [{ key: "value", choices: ["1", "1.0"] }, { key: "add", block: [] }] }, { key: "qualifications_growth_desc" }, { key: "qualifications", block: [{ key: "if", block: [] }, { key: "else_if", block: [] }, { key: "else", block: [] }] }, { key: "portrait_age", block: [{ key: "integer_range", block: [] }] }, { key: "portrait_pose", block: [{ key: "value", choices: ["0"] }] }, { key: "portrait_is_female", block: [{ key: "always", choices: ["yes"] }] }], blocks: { political_engagement_mult: { sampled: 15, keys: [{ key: "value", choices: ["1", "1.0"] }, { key: "add", block: [{ key: "desc", choices: ["POP_STARVATION"] }, { key: "if", block: [] }, { key: "else_if", block: [] }] }] }, portrait_age: { sampled: 15, keys: [{ key: "integer_range", block: [{ key: "min" }, { key: "max" }] }] }, portrait_is_female: { sampled: 15, keys: [{ key: "always", choices: ["yes"] }] }, portrait_pose: { sampled: 15, keys: [{ key: "value", choices: ["0"] }] }, qualifications: { sampled: 11, keys: [{ key: "if", block: [{ key: "limit", block: [] }, { key: "multiply", block: [] }] }, { key: "else_if", block: [{ key: "limit", block: [] }, { key: "value", block: [] }] }, { key: "else", block: [{ key: "value", block: [] }] }] } } }, power_bloc_map_texture: { sampled: 18, keys: [{ key: "texture" }] }, power_bloc_name: { sampled: 200, keys: [{ key: "trigger", block: [] }] }, power_bloc_principle: { sampled: 69, keys: [{ key: "icon" }, { key: "background" }, { key: "member_modifier", block: [] }, { key: "ai_weight", block: [{ key: "value", choices: ["1000", "100", "200", "0"] }] }], blocks: { ai_weight: { sampled: 69, keys: [{ key: "value", choices: ["1000", "100", "200", "0"] }] } } }, power_bloc_principle_group: { sampled: 23, keys: [{ key: "primary_for_identity", choices: ["identity_cultural", "identity_ideological_union", "identity_military_treaty_organization", "identity_religious", "identity_sovereign_empire", "identity_trade_league"] }, { key: "levels", block: [] }] }, prestige_good: { sampled: 72, keys: [{ key: "possible", block: [{ key: "has_dlc_feature", choices: ["mp1_content"] }] }, { key: "base_good" }, { key: "prestige_bonus", choices: ["0.1"] }, { key: "texture" }], blocks: { possible: { sampled: 72, keys: [{ key: "has_dlc_feature", choices: ["mp1_content"] }] } } }, production_method: { sampled: 436, keys: [{ key: "texture" }, { key: "building_modifiers", block: [{ key: "workforce_scaled", block: [] }, { key: "level_scaled", block: [] }] }], blocks: { building_modifiers: { sampled: 393, keys: [{ key: "workforce_scaled", block: [] }, { key: "level_scaled", block: [{ key: "building_employment_laborers_add", placeholder: "3000" }] }] } } }, production_method_group: { sampled: 197, keys: [{ key: "texture" }, { key: "production_methods", block: [] }] }, proposal_type: { sampled: 10, keys: [{ key: "has_dynamic_texture", choices: ["yes"] }, { key: "open_popup", choices: ["diplomatic_proposal", "diplomatic_proposal_break", "sway_offer", "diplomatic_demand", "treaty_proposal"] }, { key: "dynamic_texture_postfix", choices: ["break", "obligation", "break_obligation"] }, { key: "days" }] }, religion: { sampled: 17, keys: [{ key: "icon" }, { key: "heritage", choices: ["heritage_dharmic", "heritage_christian", "heritage_islamic", "heritage_taoic", "heritage_indigenous", "heritage_jewish", "heritage_materialist"] }, { key: "color", block: [] }] }, script_value: { sampled: 246, keys: [{ key: "value" }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add" }] }], blocks: { if: { sampled: 419, keys: [{ key: "limit", block: [] }, { key: "add" }] } } }, scripted_button: { sampled: 218, keys: [{ key: "name" }, { key: "desc" }, { key: "visible", block: [] }, { key: "possible", block: [] }, { key: "effect", block: [{ key: "custom_tooltip" }] }, { key: "ai_chance", block: [{ key: "value", placeholder: "10" }] }], blocks: { ai_chance: { sampled: 209, keys: [{ key: "value", placeholder: "10" }] }, effect: { sampled: 218, keys: [{ key: "custom_tooltip" }] } } }, scripted_effect: { sampled: 721, keys: [{ key: "if", block: [{ key: "limit", block: [] }] }], blocks: { if: { sampled: 1033, keys: [{ key: "limit", block: [] }] } } }, scripted_gui: { sampled: 22, keys: [{ key: "scope", choices: ["country", "character", "political_movement", "state"] }, { key: "effect", block: [{ key: "if", block: [] }] }], blocks: { effect: { sampled: 20, keys: [{ key: "if", block: [{ key: "limit", block: [] }] }] } } }, scripted_progress_bar: { sampled: 42, keys: [{ key: "name" }, { key: "desc" }, { key: "monthly_progress", block: [{ key: "if", block: [] }] }, { key: "start_value", placeholder: "10" }, { key: "min_value", choices: ["0", "1", "-10", "-40"] }, { key: "max_value", placeholder: "100" }], blocks: { monthly_progress: { sampled: 35, keys: [{ key: "if", block: [{ key: "limit", block: [] }, { key: "add", block: [] }] }] } } }, scripted_rule: { sampled: 18, keys: [] }, scripted_trigger: { sampled: 735, keys: [] }, ship_modification: { sampled: 259, keys: [{ key: "type", choices: ["ship_mod_slot_armor", "ship_mod_slot_propulsion", "ship_mod_slot_guns", "ship_mod_slot_range", "ship_mod_slot_utility_1"] }, { key: "icon" }, { key: "clicksound" }, { key: "modifier", block: [] }, { key: "construction_goods", block: [] }, { key: "ai_weight", block: [{ key: "value", choices: ["1", "2", "3", "10", "100"] }, { key: "multiply", choices: ["ship_mod_market_multiplier", "ship_mod_coastal_defence_doctrine", "ship_mod_jeune_ecole_doctrine", "ship_mod_power_projection_doctrine", "ship_mod_merchant_navy_doctrine", "ship_mod_capital_doctrine"] }] }], blocks: { ai_weight: { sampled: 251, keys: [{ key: "value", choices: ["1", "2", "3", "10", "100"] }, { key: "multiply", choices: ["ship_mod_market_multiplier", "ship_mod_coastal_defence_doctrine", "ship_mod_jeune_ecole_doctrine", "ship_mod_power_projection_doctrine", "ship_mod_merchant_navy_doctrine", "ship_mod_capital_doctrine"] }] } } }, ship_name_definition: { sampled: 86, keys: [{ key: "name" }, { key: "selection_weight", choices: ["10", "1", "15", "3", "4", "5", "9"] }, { key: "country" }, { key: "allowed_ship_types", block: [] }, { key: "properties", block: [] }] }, ship_type: { sampled: 21, keys: [{ key: "ship_group", choices: ["ship_group_capital_ships", "ship_group_cruisers", "ship_group_torpedo_craft", "ship_group_supply_ships"] }, { key: "modification_construction_cost", placeholder: "80" }, { key: "can_be_flagship", choices: ["yes"] }, { key: "is_obsolete", block: [{ key: "has_technology_researched", choices: ["pre_dreadnought_tech", "dreadnought_tech", "ironclad_tech", "monitor_tech", "sea_lane_strategies", "battleship_tech", "carrier_tech", "destroyer"] }] }, { key: "modifier", block: [{ key: "ship_construction_progress_max_add", choices: ["25", "5"] }, { key: "ship_hit_points_max_add", placeholder: "2200" }, { key: "ship_crew_max_add", placeholder: "200" }, { key: "ship_movement_speed_add", choices: ["4.5", "5", "4", "4.0", "8", "10", "3", "3.0"] }, { key: "ship_supply_capacity_add", placeholder: "40" }, { key: "ship_hull_damage_add", placeholder: "130" }, { key: "ship_crew_damage_add", placeholder: "30" }, { key: "ship_armor_add", placeholder: "20" }, { key: "ship_critical_hit_chance_add", choices: ["0.05", "0.15", "0.1", "0.10"] }, { key: "ship_critical_hit_multiplier_add", choices: ["0.25", "0.1", "0.5"] }, { key: "ship_vulnerability_add", placeholder: "100" }, { key: "ship_screening_add", placeholder: "10" }, { key: "ship_readiness_gain_add", choices: ["10"] }, { key: "ship_accuracy_add", choices: ["5", "15", "20", "6", "7"] }, { key: "ship_visibility_add", placeholder: "10" }, { key: "ship_detection_add", placeholder: "20" }, { key: "ship_blockade_strength_add", placeholder: "100" }, { key: "ship_carrying_capacity_add", choices: ["0.15", "0.3", "2.5", "1", "1.5", "1.8", "3"] }, { key: "ship_marine_capacity_add", placeholder: "0.075" }] }, { key: "is_very_obsolete", block: [{ key: "has_technology_researched", choices: ["battleship_tech", "dreadnought_tech", "monitor_tech", "pre_dreadnought_tech", "destroyer"] }] }, { key: "construction_goods", block: [{ key: "goods_input_steel_add", placeholder: "1300" }, { key: "goods_input_engines_add", placeholder: "650" }, { key: "goods_input_iron_add", choices: ["650", "2500", "2600", "900", "2000", "325", "780"] }] }, { key: "materiel_goods", block: [{ key: "goods_input_groceries_add", choices: ["1"] }, { key: "goods_input_coal_add", choices: ["1"] }, { key: "goods_input_steel_add", choices: ["0.1"] }] }, { key: "unlocking_technologies", block: [] }, { key: "icon" }, { key: "profile_texture" }, { key: "ai_weight", choices: ["2", "1.5", "0.1"] }, { key: "modifications", block: [{ key: "ship_mod_slot_armor", block: [] }, { key: "ship_mod_slot_guns", block: [] }, { key: "ship_mod_slot_propulsion", block: [] }, { key: "ship_mod_slot_range", block: [] }, { key: "ship_mod_slot_utility_1", block: [] }] }], blocks: { construction_goods: { sampled: 21, keys: [{ key: "goods_input_steel_add", placeholder: "1300" }, { key: "goods_input_engines_add", placeholder: "650" }, { key: "goods_input_iron_add", choices: ["650", "2500", "2600", "900", "2000", "325", "780"] }] }, is_obsolete: { sampled: 14, keys: [{ key: "has_technology_researched", choices: ["pre_dreadnought_tech", "dreadnought_tech", "ironclad_tech", "monitor_tech", "sea_lane_strategies", "battleship_tech", "carrier_tech", "destroyer"] }] }, is_very_obsolete: { sampled: 11, keys: [{ key: "has_technology_researched", choices: ["battleship_tech", "dreadnought_tech", "monitor_tech", "pre_dreadnought_tech", "destroyer"] }] }, materiel_goods: { sampled: 21, keys: [{ key: "goods_input_groceries_add", choices: ["1"] }, { key: "goods_input_coal_add", choices: ["1"] }, { key: "goods_input_steel_add", choices: ["0.1"] }] }, modifications: { sampled: 21, keys: [{ key: "ship_mod_slot_armor", block: [] }, { key: "ship_mod_slot_guns", block: [] }, { key: "ship_mod_slot_propulsion", block: [] }, { key: "ship_mod_slot_range", block: [] }, { key: "ship_mod_slot_utility_1", block: [] }] }, modifier: { sampled: 21, keys: [{ key: "ship_construction_progress_max_add", choices: ["25", "5"] }, { key: "ship_hit_points_max_add", placeholder: "2200" }, { key: "ship_crew_max_add", placeholder: "200" }, { key: "ship_movement_speed_add", choices: ["4.5", "5", "4", "4.0", "8", "10", "3", "3.0"] }, { key: "ship_supply_capacity_add", placeholder: "40" }, { key: "ship_hull_damage_add", placeholder: "130" }, { key: "ship_crew_damage_add", placeholder: "30" }, { key: "ship_armor_add", placeholder: "20" }, { key: "ship_critical_hit_chance_add", choices: ["0.05", "0.15", "0.1", "0.10"] }, { key: "ship_critical_hit_multiplier_add", choices: ["0.25", "0.1", "0.5"] }, { key: "ship_vulnerability_add", placeholder: "100" }, { key: "ship_screening_add", placeholder: "10" }, { key: "ship_readiness_gain_add", choices: ["10"] }, { key: "ship_accuracy_add", choices: ["5", "15", "20", "6", "7"] }, { key: "ship_visibility_add", placeholder: "10" }, { key: "ship_detection_add", placeholder: "20" }, { key: "ship_blockade_strength_add", placeholder: "100" }, { key: "ship_carrying_capacity_add", choices: ["0.15", "0.3", "2.5", "1", "1.5", "1.8", "3"] }, { key: "ship_marine_capacity_add", placeholder: "0.075" }] } } }, social_class: { sampled: 14, keys: [{ key: "social_hierarchy", choices: ["edo_system", "british_indian_caste_system", "default_social_hierarchy"] }, { key: "strata", choices: ["lower", "middle", "upper"] }, { key: "allowed_professions", block: [] }] }, state_trait: { sampled: 239, keys: [{ key: "icon" }, { key: "modifier", block: [] }] }, static_modifier: { sampled: 6127, keys: [{ key: "icon" }] }, strait_definition: { sampled: 12, keys: [{ key: "type", choices: ["natural", "artificial"] }, { key: "total_block_requires_full_control", choices: ["no", "yes"] }, { key: "military_block_requires_full_control", choices: ["no", "yes"] }, { key: "first_land_endpoint" }, { key: "second_land_endpoint" }, { key: "first_sea_endpoint" }, { key: "second_sea_endpoint" }] }, strategic_region: { sampled: 142, keys: [{ key: "states", block: [] }] }, technology: { sampled: 179, keys: [{ key: "era", choices: ["era_3", "era_1", "era_2", "era_4", "era_5"] }, { key: "texture" }, { key: "category", choices: ["society", "military", "production"] }, { key: "modifier", block: [] }, { key: "unlocking_technologies", block: [] }, { key: "ai_weight", block: [{ key: "value", choices: ["1", "2", "1.5", "3"] }] }], blocks: { ai_weight: { sampled: 179, keys: [{ key: "value", choices: ["1", "2", "1.5", "3"] }] } } }, terrain: { sampled: 25, keys: [{ key: "label", choices: ["label_developed", "label_flat", "label_hazardous", "label_travel_harsh_environment", "label_forested", "label_water", "label_elevated"] }, { key: "weight", choices: ["2", "1", "1.5"] }, { key: "textures", block: [] }, { key: "combat_width", choices: ["1.5", "0.5", "0.8", "0.6", "0.7", "1", "0.4"] }, { key: "risk", choices: ["0.1", "0.2", "0.5", "0.15", "0.3", "0.6"] }, { key: "debug_color", block: [] }, { key: "pollution_mask_strength", choices: ["1.0", "0.1", "0.25", "0.5"] }, { key: "devastation_mask_strength", choices: ["1.0", "0.0"] }] }, terrain_manipulator: { sampled: 14, keys: [{ key: "created_terrain" }, { key: "terrain_mask", choices: ["mask_dynamic_farmland", "mask_dynamic_forestry", "mask_dynamic_mining"] }, { key: "preferred_terrain", choices: ["plains", "forest", "hills"] }, { key: "city_type", choices: ["farm", "city", "mine", "port", "wood"] }, { key: "toggle_map_object_layers", block: [] }] }, theme: { sampled: 60, keys: [{ key: "category" }, { key: "dlc", choices: ["dlc004", "dlc011", "dlc016", "dlc018", "dlc007", "dlc014", "dlc010", "dlc013"] }, { key: "bulk_selection_group", choices: ["default", "ep2", "ip2", "votp", "ap1", "ip3", "ip4"] }, { key: "map_object", block: [{ key: "pdxmesh" }, { key: "locator" }] }, { key: "dynamic_weight", block: [{ key: "value", choices: ["0", "root.gdp"] }, { key: "if", block: [] }, { key: "else_if", block: [] }] }], blocks: { dynamic_weight: { sampled: 38, keys: [{ key: "value", choices: ["0", "root.gdp"] }, { key: "if", block: [{ key: "limit", block: [] }, { key: "add", choices: ["100", "250"] }] }, { key: "else_if", block: [{ key: "limit", block: [] }, { key: "add", choices: ["10"] }] }] }, map_object: { sampled: 64, keys: [{ key: "pdxmesh" }, { key: "locator" }] } } }, treaty_article: { sampled: 34, keys: [{ key: "kind", choices: ["directed", "mutual"] }, { key: "cost", choices: ["25", "10", "0", "50", "100", "150"] }, { key: "relations_progress_per_day", choices: ["0.5", "-0.25", "1", "-0.5", "1.5"] }, { key: "icon" }, { key: "max_target_involvement", choices: ["1000", "2000", "250", "500", "3000"] }, { key: "flags", block: [] }, { key: "target_involvement_applies_to", choices: ["source_country", "target_country", "mutual"] }, { key: "usage_limit", choices: ["once_per_side", "once_per_side_with_same_inputs", "once_per_treaty"] }, { key: "maintenance_paid_by", choices: ["target_country", "source_country"] }, { key: "visible", block: [] }, { key: "unlocked_by_technologies", block: [] }, { key: "possible", block: [] }, { key: "can_ratify", block: [{ key: "custom_tooltip", block: [] }] }, { key: "on_entry_into_force", block: [] }, { key: "on_withdrawal", block: [] }, { key: "on_break", block: [] }, { key: "ai", block: [{ key: "treaty_categories", block: [] }, { key: "evaluation_chance", block: [] }, { key: "article_ai_usage", block: [] }, { key: "inherent_accept_score", block: [] }] }, { key: "wargoal", block: [{ key: "execution_priority", choices: ["21", "71"] }, { key: "contestion_type", choices: ["control_any_target_country_state", "control_any_target_incorporated_state", "control_target_country_capital", "control_target_state"] }, { key: "maneuvers", block: [] }, { key: "infamy", block: [] }] }], blocks: { ai: { sampled: 34, keys: [{ key: "treaty_categories", block: [] }, { key: "evaluation_chance", block: [{ key: "value", choices: ["0.1", "0", "0.0", "0.25", "0.01", "0.025", "0.05", "0.2"] }, { key: "if", block: [] }] }, { key: "article_ai_usage", block: [] }, { key: "inherent_accept_score", block: [{ key: "value", choices: ["0"] }, { key: "if", block: [] }, { key: "else", block: [] }] }] }, can_ratify: { sampled: 34, keys: [{ key: "custom_tooltip", block: [{ key: "text", choices: ["DUPLICATE_ARTICLE_SAME_INPUTS_TREATY", "DUPLICATE_ARTICLE_SAME_INPUTS", "STATE_TRANSFER_NOT_OWNER", "TRANSFER_SUBJECT_NOT_OVERLORD", "TREATY_SHIP_IN_BATTLE", "alliance_multilateral_alliances_first_country_tt", "alliance_multilateral_alliances_second_country_tt", "military_assistance_limit_tt"] }, { key: "NOT", block: [] }] }] }, wargoal: { sampled: 21, keys: [{ key: "execution_priority", choices: ["21", "71"] }, { key: "contestion_type", choices: ["control_any_target_country_state", "control_any_target_incorporated_state", "control_target_country_capital", "control_target_state"] }, { key: "maneuvers", block: [{ key: "value", choices: ["0", "2.5"] }, { key: "add", block: [] }] }, { key: "infamy", block: [{ key: "value", choices: ["0", "0.25"] }, { key: "add", block: [] }] }] } } }, trigger_localization: { sampled: 1672, keys: [{ key: "global" }, { key: "global_not" }, { key: "third" }] }, tutorial_lesson: { sampled: 66, keys: [{ key: "start_automatically", choices: ["no"] }, { key: "chain", choices: ["lesson_chain_journal_guides", "lesson_chain_intro", "lesson_chain_pops"] }] }, war_goal_type: { sampled: 34, keys: [{ key: "icon" }, { key: "kind" }, { key: "settings", block: [] }, { key: "execution_priority", placeholder: "12" }, { key: "contestion_type", choices: ["control_half_target_country_states", "control_all_own_states", "control_any_target_incorporated_state", "control_target_state", "control_any_target_country_state", "control_all_target_country_claims", "control_any_releasable_state", "control_own_state"] }, { key: "target_type", choices: ["country", "treaty_article", "state"] }, { key: "possible", block: [] }, { key: "valid", block: [] }, { key: "maneuvers", block: [{ key: "value", choices: ["0"] }, { key: "add", block: [] }] }, { key: "infamy", block: [{ key: "value", choices: ["0", "5"] }, { key: "add", block: [] }] }, { key: "on_enforced", block: [] }, { key: "ai", block: [{ key: "is_significant_demand", choices: ["no", "yes"] }] }], blocks: { ai: { sampled: 34, keys: [{ key: "is_significant_demand", choices: ["no", "yes"] }] }, infamy: { sampled: 34, keys: [{ key: "value", choices: ["0", "5"] }, { key: "add", block: [{ key: "desc", choices: ["INFAMY_BASE_VALUE", "INFAMY_STATE_GDP_FACTOR"] }, { key: "value", choices: ["2", "0.25", "0.5", "0.10", "5", "0.1", "scope:target_state.gdp"] }] }] }, maneuvers: { sampled: 34, keys: [{ key: "value", choices: ["0"] }, { key: "add", block: [{ key: "desc", choices: ["MANEUVERS_BASE_VALUE"] }, { key: "value", choices: ["10", "1", "20", "2.5", "30", "5", "8"] }] }] } } } } };
|
|
47651
|
+
|
|
47420
47652
|
// src/games/vic3/index.ts
|
|
47421
47653
|
var vic3Profile = {
|
|
47422
47654
|
...vic3Meta,
|
|
@@ -47425,6 +47657,7 @@ var vic3Profile = {
|
|
|
47425
47657
|
prefixRefs: VIC3_PREFIX_REFS,
|
|
47426
47658
|
blockRefFields: VIC3_BLOCK_REF_FIELDS,
|
|
47427
47659
|
guiSchema: guiSchema_default2,
|
|
47660
|
+
skeletons: skeletons_default2.kinds,
|
|
47428
47661
|
// guiTextMetrics live on the meta (the client reads them too, for the GUI
|
|
47429
47662
|
// editor gate and its canvas line height).
|
|
47430
47663
|
// Vic3 keeps an authored size on an EMPTY container (px_probe_c C5: the
|
|
@@ -47458,6 +47691,9 @@ var vic3Profile = {
|
|
|
47458
47691
|
diagnosticSource: "vic3-script"
|
|
47459
47692
|
};
|
|
47460
47693
|
|
|
47694
|
+
// data/eu5/skeletons.json
|
|
47695
|
+
var skeletons_default3 = { meta: { generated: "2026-09-03", sources: [], majority: 0.5 }, kinds: {} };
|
|
47696
|
+
|
|
47461
47697
|
// src/games/eu5/scaffolds.ts
|
|
47462
47698
|
var EU5_SCAFFOLDS = [
|
|
47463
47699
|
{
|
|
@@ -47501,12 +47737,16 @@ var eu5Meta = {
|
|
|
47501
47737
|
// EU5 mods carry .metadata/metadata.json (plus a required thumbnail.png);
|
|
47502
47738
|
// descriptor.mod is at most a vestigial launcher artifact.
|
|
47503
47739
|
descriptor: "metadata",
|
|
47504
|
-
configDirName: ".
|
|
47740
|
+
configDirName: ".px-toolkit",
|
|
47741
|
+
legacyConfigDirName: ".eu5modding",
|
|
47505
47742
|
docsFolderName: "Europa Universalis V",
|
|
47506
47743
|
// EU5's `script_docs` console command writes to Documents/.../docs, not logs/.
|
|
47507
47744
|
scriptDocsSubdir: "docs",
|
|
47508
47745
|
dataTypesCommand: "dump_data_types",
|
|
47509
47746
|
steamAppId: 3450310,
|
|
47747
|
+
// dlcIconDir deliberately absent: no live install has been checked, so the
|
|
47748
|
+
// Workshop panel shows this game's DLC (read from `<gameDir>/dlc/`) with the
|
|
47749
|
+
// folder's own thumbnail.png, and falls back to Steam when there is none.
|
|
47510
47750
|
eventNamespaces: true,
|
|
47511
47751
|
scaffolds: EU5_SCAFFOLDS,
|
|
47512
47752
|
// uiFont and guiTextMetrics deliberately absent: neither the font file nor
|
|
@@ -48514,6 +48754,10 @@ var eu5Profile = {
|
|
|
48514
48754
|
blockRefFields: { ...JOMINI_VARIABLE_BLOCK_REFS },
|
|
48515
48755
|
// No `_*.info` docs ship with EU5, so the structures layer has no source.
|
|
48516
48756
|
structureSources: {},
|
|
48757
|
+
// Nobody here owns EU5, so its vanilla tree has never been measured and
|
|
48758
|
+
// data/eu5/skeletons.json is empty. Wired anyway: a harvest run on a machine
|
|
48759
|
+
// that has the game turns skeletons on with no code change.
|
|
48760
|
+
skeletons: skeletons_default3.kinds,
|
|
48517
48761
|
modifierPlaceholders: {},
|
|
48518
48762
|
// No bundled wiki tokens in the preview cut, so nothing ever renders this.
|
|
48519
48763
|
wikiNote: "",
|
|
@@ -48712,19 +48956,19 @@ var Parser = class {
|
|
|
48712
48956
|
if (after.kind === "op") {
|
|
48713
48957
|
return null;
|
|
48714
48958
|
}
|
|
48715
|
-
const
|
|
48959
|
+
const scalar3 = this.makeScalar(this.advance());
|
|
48716
48960
|
const next = this.peek();
|
|
48717
48961
|
if (next.kind === "lbrace") {
|
|
48718
48962
|
const block2 = this.parseBlock();
|
|
48719
48963
|
const tb = {
|
|
48720
48964
|
kind: "tagged-block",
|
|
48721
|
-
tag:
|
|
48965
|
+
tag: scalar3,
|
|
48722
48966
|
block: block2,
|
|
48723
|
-
range: { start:
|
|
48967
|
+
range: { start: scalar3.range.start, end: block2.range.end }
|
|
48724
48968
|
};
|
|
48725
48969
|
return tb;
|
|
48726
48970
|
}
|
|
48727
|
-
return
|
|
48971
|
+
return scalar3;
|
|
48728
48972
|
}
|
|
48729
48973
|
return null;
|
|
48730
48974
|
}
|
|
@@ -49085,7 +49329,7 @@ var STATE_BLOCKS = /* @__PURE__ */ new Set(["state", "animation", "attachanimati
|
|
|
49085
49329
|
function buildGuiTree(text) {
|
|
49086
49330
|
const result = parseScript(text);
|
|
49087
49331
|
const lineIndex = new LineIndex(text);
|
|
49088
|
-
let
|
|
49332
|
+
let count2 = 0;
|
|
49089
49333
|
const walk2 = (statements2) => {
|
|
49090
49334
|
const nodes2 = [];
|
|
49091
49335
|
let pendingDecl = null;
|
|
@@ -49123,14 +49367,14 @@ function buildGuiTree(text) {
|
|
|
49123
49367
|
else if (ck === "using") (node.using ??= []).push(child.value.text);
|
|
49124
49368
|
}
|
|
49125
49369
|
node.children = walk2(block2.statements);
|
|
49126
|
-
|
|
49370
|
+
count2++;
|
|
49127
49371
|
nodes2.push(node);
|
|
49128
49372
|
pendingDecl = null;
|
|
49129
49373
|
}
|
|
49130
49374
|
return nodes2;
|
|
49131
49375
|
};
|
|
49132
49376
|
const nodes = walk2(result.root.statements);
|
|
49133
|
-
return { nodes, count };
|
|
49377
|
+
return { nodes, count: count2 };
|
|
49134
49378
|
}
|
|
49135
49379
|
|
|
49136
49380
|
// src/gui/textResolve.ts
|
|
@@ -49764,8 +50008,8 @@ ${stmt.value.text}`
|
|
|
49764
50008
|
node.invisible = resolveVisibility(node.props.get("visible")?.text, ctx);
|
|
49765
50009
|
if (node.itemTemplate && node.itemTemplate.children.length > 0) {
|
|
49766
50010
|
markGhost(node.itemTemplate);
|
|
49767
|
-
const
|
|
49768
|
-
for (let i = 0; i <
|
|
50011
|
+
const count2 = ghostCount(node);
|
|
50012
|
+
for (let i = 0; i < count2; i++) node.children.push(node.itemTemplate);
|
|
49769
50013
|
}
|
|
49770
50014
|
return node;
|
|
49771
50015
|
}
|
|
@@ -50951,10 +51195,10 @@ async function scanBody(file, entry, schema2, loc, playerId) {
|
|
|
50951
51195
|
const closed = stack.pop();
|
|
50952
51196
|
if (capture && stack.length === capture.path.length - 1) {
|
|
50953
51197
|
const tail = line.slice(Math.max(captureStart, 0), i + 1);
|
|
50954
|
-
const { path:
|
|
51198
|
+
const { path: path37, lines } = capture;
|
|
50955
51199
|
capture = null;
|
|
50956
51200
|
captureStart = -1;
|
|
50957
|
-
|
|
51201
|
+
keep2(path37, [...lines, tail].join("\n"));
|
|
50958
51202
|
} else if (!capture && stack.length === 0 && registry && closed === registry.countryBlock) {
|
|
50959
51203
|
finishCountries();
|
|
50960
51204
|
}
|
|
@@ -50984,19 +51228,19 @@ async function scanBody(file, entry, schema2, loc, playerId) {
|
|
|
50984
51228
|
if (def) candidate.tag = def[1];
|
|
50985
51229
|
else if (mainLine.test(line)) candidate.main = true;
|
|
50986
51230
|
}
|
|
50987
|
-
function
|
|
50988
|
-
if (
|
|
51231
|
+
function keep2(path37, text) {
|
|
51232
|
+
if (path37[0] === META_BLOCK) {
|
|
50989
51233
|
out.meta = parseBlock(text);
|
|
50990
51234
|
if (!registry && !record) done = true;
|
|
50991
51235
|
return;
|
|
50992
51236
|
}
|
|
50993
|
-
if (record &&
|
|
51237
|
+
if (record && path37[0] === record.block) {
|
|
50994
51238
|
out.character = parseBlock(text);
|
|
50995
51239
|
done = true;
|
|
50996
51240
|
return;
|
|
50997
51241
|
}
|
|
50998
51242
|
if (!registry) return;
|
|
50999
|
-
if (
|
|
51243
|
+
if (path37[0] === registry.countryBlock) {
|
|
51000
51244
|
const name = scalar(out.meta, schema2.nameKey ?? DEFAULT_NAME_KEY);
|
|
51001
51245
|
const tag = candidate?.tag;
|
|
51002
51246
|
if (tag && (loc(tag) === name || tag === name)) playerCountry = text;
|
|
@@ -51005,7 +51249,7 @@ async function scanBody(file, entry, schema2, loc, playerId) {
|
|
|
51005
51249
|
return;
|
|
51006
51250
|
}
|
|
51007
51251
|
for (const link of registry.links) {
|
|
51008
|
-
if (link.block ===
|
|
51252
|
+
if (link.block === path37[0] && linkIds[link.slot] === path37[2]) out[link.slot] = parseBlock(text);
|
|
51009
51253
|
}
|
|
51010
51254
|
if (registry.links.every((l) => !linkIds[l.slot] || out[l.slot])) done = true;
|
|
51011
51255
|
}
|
|
@@ -51021,10 +51265,20 @@ function keyBefore(line, brace) {
|
|
|
51021
51265
|
}
|
|
51022
51266
|
|
|
51023
51267
|
// src/gui/sourceModel.ts
|
|
51268
|
+
var GUI_DIALECT = {
|
|
51269
|
+
declMarkers: DECL_MARKERS3,
|
|
51270
|
+
slotKeys: SLOT_KEYS,
|
|
51271
|
+
propertyBlocks: PROPERTY_BLOCKS2
|
|
51272
|
+
};
|
|
51273
|
+
var SCRIPT_DIALECT = {
|
|
51274
|
+
declMarkers: /* @__PURE__ */ new Set(),
|
|
51275
|
+
slotKeys: /* @__PURE__ */ new Set(),
|
|
51276
|
+
propertyBlocks: null
|
|
51277
|
+
};
|
|
51024
51278
|
var LINE_BLANK = 0;
|
|
51025
51279
|
var LINE_COMMENT = 1;
|
|
51026
51280
|
var LINE_CODE = 2;
|
|
51027
|
-
function parseGuiSource(text) {
|
|
51281
|
+
function parseGuiSource(text, dialect = GUI_DIALECT) {
|
|
51028
51282
|
const parsed = parseScript(text);
|
|
51029
51283
|
const lines = new LineIndex(text);
|
|
51030
51284
|
const commentsByLine = /* @__PURE__ */ new Map();
|
|
@@ -51038,7 +51292,8 @@ function parseGuiSource(text) {
|
|
|
51038
51292
|
lines,
|
|
51039
51293
|
lineKind: classifyLines(text, lines, commentsByLine),
|
|
51040
51294
|
commentsByLine,
|
|
51041
|
-
entries: []
|
|
51295
|
+
entries: [],
|
|
51296
|
+
dialect
|
|
51042
51297
|
};
|
|
51043
51298
|
const root = buildBody(parsed.root.statements, -1, null, { start: 0, end: text.length }, null, ctx);
|
|
51044
51299
|
return {
|
|
@@ -51072,7 +51327,7 @@ function buildBody(statements2, open, close, inner, owner, ctx) {
|
|
|
51072
51327
|
let marker = null;
|
|
51073
51328
|
for (const stmt of statements2) {
|
|
51074
51329
|
if (stmt.kind === "value") {
|
|
51075
|
-
marker = stmt.value.kind === "scalar" &&
|
|
51330
|
+
marker = stmt.value.kind === "scalar" && ctx.dialect.declMarkers.has(stmt.value.text.toLowerCase()) ? { text: stmt.value.text.toLowerCase(), span: stmt.value.range } : null;
|
|
51076
51331
|
continue;
|
|
51077
51332
|
}
|
|
51078
51333
|
const own = marker;
|
|
@@ -51125,7 +51380,7 @@ function appendPoint(children, close, closeLine2, closeOwnLine, ctx) {
|
|
|
51125
51380
|
function buildEntry(stmt, declMarker, parent, ctx) {
|
|
51126
51381
|
const { text, lines } = ctx;
|
|
51127
51382
|
const opSpan = operatorSpan(text, stmt);
|
|
51128
|
-
const slot = slotForm(stmt, declMarker);
|
|
51383
|
+
const slot = slotForm(stmt, declMarker, ctx.dialect);
|
|
51129
51384
|
const marker = slot?.marker ?? declMarker;
|
|
51130
51385
|
const key = slot?.key ?? stmt.key;
|
|
51131
51386
|
const value = slot?.value ?? stmt.value;
|
|
@@ -51152,7 +51407,7 @@ function buildEntry(stmt, declMarker, parent, ctx) {
|
|
|
51152
51407
|
}
|
|
51153
51408
|
const ownLine = startsLine && endsLine;
|
|
51154
51409
|
const entry = {
|
|
51155
|
-
kind: classify2(key, marker, block2),
|
|
51410
|
+
kind: classify2(key, marker, block2, ctx.dialect),
|
|
51156
51411
|
key: key.text,
|
|
51157
51412
|
keyLower: key.text.toLowerCase(),
|
|
51158
51413
|
keySpan: key.range,
|
|
@@ -51202,17 +51457,18 @@ function buildEntry(stmt, declMarker, parent, ctx) {
|
|
|
51202
51457
|
}
|
|
51203
51458
|
return entry;
|
|
51204
51459
|
}
|
|
51205
|
-
function classify2(key, marker, block2) {
|
|
51460
|
+
function classify2(key, marker, block2, dialect) {
|
|
51206
51461
|
if (marker) return "decl";
|
|
51207
51462
|
if (!block2) return "property";
|
|
51463
|
+
if (!dialect.propertyBlocks) return "property";
|
|
51208
51464
|
const lower = key.text.toLowerCase();
|
|
51209
|
-
if (
|
|
51465
|
+
if (dialect.propertyBlocks.has(lower) || lower.startsWith("@")) return "property";
|
|
51210
51466
|
return "widget";
|
|
51211
51467
|
}
|
|
51212
|
-
function slotForm(stmt, marker) {
|
|
51468
|
+
function slotForm(stmt, marker, dialect) {
|
|
51213
51469
|
if (marker || stmt.value?.kind !== "tagged-block") return null;
|
|
51214
51470
|
const lower = stmt.key.text.toLowerCase();
|
|
51215
|
-
if (!
|
|
51471
|
+
if (!dialect.slotKeys.has(lower)) return null;
|
|
51216
51472
|
return {
|
|
51217
51473
|
marker: { text: lower, span: stmt.key.range },
|
|
51218
51474
|
key: stmt.value.tag,
|
|
@@ -53443,15 +53699,15 @@ function blockStackFromParse(parse, offset) {
|
|
|
53443
53699
|
function blockPathFromParse(parse, offset) {
|
|
53444
53700
|
const hit = nodeAtOffset(parse.root, offset);
|
|
53445
53701
|
if (!hit) return [];
|
|
53446
|
-
const
|
|
53702
|
+
const path37 = [];
|
|
53447
53703
|
for (const stmt of hit.path) {
|
|
53448
53704
|
const block2 = childBlock2(stmt);
|
|
53449
53705
|
if (!block2) continue;
|
|
53450
53706
|
if (offset <= block2.openBrace) continue;
|
|
53451
53707
|
if (block2.closeBrace !== null && offset > block2.closeBrace) continue;
|
|
53452
|
-
|
|
53708
|
+
path37.push(stmt.kind === "assignment" ? stmt : null);
|
|
53453
53709
|
}
|
|
53454
|
-
return
|
|
53710
|
+
return path37;
|
|
53455
53711
|
}
|
|
53456
53712
|
function detectContextFromParse(parse, offset) {
|
|
53457
53713
|
const stack = blockStackFromParse(parse, offset);
|
|
@@ -53592,7 +53848,7 @@ function valueScopeType(valueText) {
|
|
|
53592
53848
|
return "value";
|
|
53593
53849
|
}
|
|
53594
53850
|
function inferScopeAt(parse, offset, model, rootScopes, savedScopes, ctx) {
|
|
53595
|
-
const
|
|
53851
|
+
const path37 = blockPathFromParse(parse, offset);
|
|
53596
53852
|
const chain = [];
|
|
53597
53853
|
const effectiveRoot = rootScopesAt(parse, offset, rootScopes, ctx);
|
|
53598
53854
|
const rootSet = effectiveRoot ? new Set(effectiveRoot) : null;
|
|
@@ -53691,7 +53947,7 @@ function inferScopeAt(parse, offset, model, rootScopes, savedScopes, ctx) {
|
|
|
53691
53947
|
}
|
|
53692
53948
|
if (isScopeTransparent(lower)) return;
|
|
53693
53949
|
};
|
|
53694
|
-
for (const node of
|
|
53950
|
+
for (const node of path37) {
|
|
53695
53951
|
apply(node && node.kind === "assignment" ? node.key.text : "<anon>", node);
|
|
53696
53952
|
}
|
|
53697
53953
|
return { scopes: current2, chain };
|
|
@@ -53776,8 +54032,8 @@ function fmt2(scopes) {
|
|
|
53776
54032
|
var scriptCache = /* @__PURE__ */ new Map();
|
|
53777
54033
|
var locCache = /* @__PURE__ */ new Map();
|
|
53778
54034
|
function getParse(document) {
|
|
53779
|
-
const
|
|
53780
|
-
if (
|
|
54035
|
+
const cached2 = scriptCache.get(document.uri);
|
|
54036
|
+
if (cached2 && cached2.version === document.version) return cached2;
|
|
53781
54037
|
const text = document.getText();
|
|
53782
54038
|
const entry = {
|
|
53783
54039
|
version: document.version,
|
|
@@ -53788,8 +54044,8 @@ function getParse(document) {
|
|
|
53788
54044
|
return entry;
|
|
53789
54045
|
}
|
|
53790
54046
|
function getLocParse(document) {
|
|
53791
|
-
const
|
|
53792
|
-
if (
|
|
54047
|
+
const cached2 = locCache.get(document.uri);
|
|
54048
|
+
if (cached2 && cached2.version === document.version) return cached2;
|
|
53793
54049
|
const text = document.getText();
|
|
53794
54050
|
const entry = {
|
|
53795
54051
|
version: document.version,
|
|
@@ -54107,8 +54363,8 @@ function inferenceContextFor(data2, entry) {
|
|
|
54107
54363
|
var callSiteCache = /* @__PURE__ */ new WeakMap();
|
|
54108
54364
|
function callSiteScopes(data2, rootScopesForFile2) {
|
|
54109
54365
|
const revision = `${data2.index.revision}:${data2.refIndex.revision}`;
|
|
54110
|
-
const
|
|
54111
|
-
if (
|
|
54366
|
+
const cached2 = callSiteCache.get(data2);
|
|
54367
|
+
if (cached2 && cached2.revision === revision) return cached2.map;
|
|
54112
54368
|
const map = buildCallSiteScopes(data2.refIndex.chainedCalls(), data2.scopeModel, rootScopesForFile2);
|
|
54113
54369
|
callSiteCache.set(data2, { revision, map });
|
|
54114
54370
|
return map;
|
|
@@ -54140,8 +54396,8 @@ function buildCallSiteScopes(refs, model, rootScopesForFile2) {
|
|
|
54140
54396
|
return map;
|
|
54141
54397
|
}
|
|
54142
54398
|
function variableTypes(data2, rootScopesForFile2) {
|
|
54143
|
-
const
|
|
54144
|
-
if (
|
|
54399
|
+
const cached2 = cache2.get(data2);
|
|
54400
|
+
if (cached2 && cached2.index === data2.index && cached2.revision === data2.index.revision) return cached2.info;
|
|
54145
54401
|
const info = buildVariableTypes(
|
|
54146
54402
|
data2.index.entries(
|
|
54147
54403
|
(d) => d.kind in VAR_KIND_PREFIX || d.kind in LIST_KIND_PREFIX || d.kind === "list" || d.kind === "saved_scope"
|
|
@@ -54398,18 +54654,67 @@ function blockTemplateFor(token) {
|
|
|
54398
54654
|
}
|
|
54399
54655
|
var KEY = /^[a-z_][a-z0-9_]*$/;
|
|
54400
54656
|
var TRUNCATE = ["(optional)", "..."];
|
|
54657
|
+
var OPTIONAL_COMMENT = /^#[ \t]*optional/i;
|
|
54658
|
+
var WRAPPER_HEAD = /^\s*<[^>]+>\s*=\s*\{/;
|
|
54401
54659
|
function extractBlockTemplate(name, usage) {
|
|
54402
54660
|
if (!usage) return null;
|
|
54403
|
-
const
|
|
54404
|
-
if (
|
|
54405
|
-
|
|
54661
|
+
const stripped = stripOptionalComments(usage.replace(/\r/g, ""));
|
|
54662
|
+
if (!stripped) return null;
|
|
54663
|
+
let { text } = stripped;
|
|
54664
|
+
const { optionalLines } = stripped;
|
|
54665
|
+
const wrapper = WRAPPER_HEAD.test(text) ? unwrap(text) : text;
|
|
54666
|
+
if (wrapper === null) return null;
|
|
54667
|
+
text = wrapper;
|
|
54668
|
+
const head = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*\{/.exec(text);
|
|
54406
54669
|
if (!head || head[1] !== name) return null;
|
|
54407
54670
|
const open = text.indexOf("{");
|
|
54408
54671
|
const close = matchingBrace(text, open);
|
|
54409
54672
|
if (close < 0 || text.slice(close + 1).trim() !== "") return null;
|
|
54410
|
-
const
|
|
54673
|
+
const parser = new BodyParser(text, open + 1, optionalLines);
|
|
54674
|
+
const body = parser.parseBody();
|
|
54411
54675
|
if (body === null) return null;
|
|
54412
|
-
|
|
54676
|
+
for (const line of optionalLines) if (!parser.markedLines.has(line)) return null;
|
|
54677
|
+
const minimal = { snippet: render(name, body, true, false), plain: render(name, body, false, false) };
|
|
54678
|
+
if (!hasOptional(body)) return minimal;
|
|
54679
|
+
return {
|
|
54680
|
+
...minimal,
|
|
54681
|
+
full: { snippet: render(name, body, true, true), plain: render(name, body, false, true) }
|
|
54682
|
+
};
|
|
54683
|
+
}
|
|
54684
|
+
function stripOptionalComments(text) {
|
|
54685
|
+
const lines = text.split("\n");
|
|
54686
|
+
const out = [];
|
|
54687
|
+
const optionalLines = /* @__PURE__ */ new Set();
|
|
54688
|
+
let wrapping = false;
|
|
54689
|
+
for (let i = 0; i < lines.length; i++) {
|
|
54690
|
+
const hash = lines[i].indexOf("#");
|
|
54691
|
+
if (hash < 0) {
|
|
54692
|
+
out.push(lines[i]);
|
|
54693
|
+
wrapping = false;
|
|
54694
|
+
continue;
|
|
54695
|
+
}
|
|
54696
|
+
const before = lines[i].slice(0, hash);
|
|
54697
|
+
if (wrapping && before.trim() === "") {
|
|
54698
|
+
out.push("");
|
|
54699
|
+
continue;
|
|
54700
|
+
}
|
|
54701
|
+
if (!OPTIONAL_COMMENT.test(lines[i].slice(hash))) return null;
|
|
54702
|
+
if (before.trim() === "") return null;
|
|
54703
|
+
out.push(before.trimEnd());
|
|
54704
|
+
optionalLines.add(i);
|
|
54705
|
+
wrapping = true;
|
|
54706
|
+
}
|
|
54707
|
+
return { text: out.join("\n"), optionalLines };
|
|
54708
|
+
}
|
|
54709
|
+
function hasOptional(body) {
|
|
54710
|
+
return body.items.some((item) => item.optional || "items" in item.value && hasOptional(item.value));
|
|
54711
|
+
}
|
|
54712
|
+
function unwrap(text) {
|
|
54713
|
+
const open = text.indexOf("{");
|
|
54714
|
+
const close = matchingBrace(text, open);
|
|
54715
|
+
if (close < 0 || text.slice(close + 1).trim() !== "") return null;
|
|
54716
|
+
const blank = (s2) => s2.replace(/[^\n]/g, " ");
|
|
54717
|
+
return blank(text.slice(0, open + 1)) + text.slice(open + 1, close) + blank(text.slice(close));
|
|
54413
54718
|
}
|
|
54414
54719
|
function matchingBrace(text, open) {
|
|
54415
54720
|
let depth = 0;
|
|
@@ -54420,15 +54725,33 @@ function matchingBrace(text, open) {
|
|
|
54420
54725
|
return -1;
|
|
54421
54726
|
}
|
|
54422
54727
|
var BodyParser = class {
|
|
54423
|
-
constructor(text, i) {
|
|
54728
|
+
constructor(text, i, optionalLines = /* @__PURE__ */ new Set()) {
|
|
54424
54729
|
this.text = text;
|
|
54425
54730
|
this.i = i;
|
|
54731
|
+
this.optionalLines = optionalLines;
|
|
54732
|
+
this.lineAt = new Array(text.length);
|
|
54733
|
+
let line = 0;
|
|
54734
|
+
for (let n = 0; n < text.length; n++) {
|
|
54735
|
+
this.lineAt[n] = line;
|
|
54736
|
+
if (text[n] === "\n") line++;
|
|
54737
|
+
}
|
|
54426
54738
|
}
|
|
54427
54739
|
text;
|
|
54428
54740
|
i;
|
|
54741
|
+
optionalLines;
|
|
54742
|
+
/** Lines of `optionalLines` an item actually ended on. */
|
|
54743
|
+
markedLines = /* @__PURE__ */ new Set();
|
|
54744
|
+
/** Line number per character offset, so an item can be tied to its comment. */
|
|
54745
|
+
lineAt;
|
|
54429
54746
|
/** Items of the block whose `{` was just consumed; null rejects the example. */
|
|
54430
54747
|
parseBody() {
|
|
54431
54748
|
const items = [];
|
|
54749
|
+
const push = (item, end = this.i) => {
|
|
54750
|
+
const line = this.lineAt[end - 1] ?? 0;
|
|
54751
|
+
const optional = this.optionalLines.has(line);
|
|
54752
|
+
if (optional) this.markedLines.add(line);
|
|
54753
|
+
items.push({ ...item, optional });
|
|
54754
|
+
};
|
|
54432
54755
|
for (; ; ) {
|
|
54433
54756
|
this.skipSpace();
|
|
54434
54757
|
if (this.i >= this.text.length) return null;
|
|
@@ -54444,10 +54767,11 @@ var BodyParser = class {
|
|
|
54444
54767
|
}
|
|
54445
54768
|
const first = this.readLeaf();
|
|
54446
54769
|
if (!first) return null;
|
|
54770
|
+
const firstEnd = this.i;
|
|
54447
54771
|
this.skipSpace();
|
|
54448
54772
|
if (this.text[this.i] !== "=") {
|
|
54449
54773
|
if (!first.placeholder) return null;
|
|
54450
|
-
|
|
54774
|
+
push({ key: null, value: first }, firstEnd);
|
|
54451
54775
|
continue;
|
|
54452
54776
|
}
|
|
54453
54777
|
if (first.placeholder) return null;
|
|
@@ -54458,12 +54782,12 @@ var BodyParser = class {
|
|
|
54458
54782
|
this.i++;
|
|
54459
54783
|
const nested = this.parseBody();
|
|
54460
54784
|
if (nested === null) return null;
|
|
54461
|
-
|
|
54785
|
+
push({ key: first, value: nested });
|
|
54462
54786
|
continue;
|
|
54463
54787
|
}
|
|
54464
54788
|
const value = this.readLeaf();
|
|
54465
54789
|
if (!value) return null;
|
|
54466
|
-
|
|
54790
|
+
push({ key: first, value });
|
|
54467
54791
|
}
|
|
54468
54792
|
}
|
|
54469
54793
|
/** Start of the innermost still-open `{` at or before the cursor. */
|
|
@@ -54494,13 +54818,14 @@ var BodyParser = class {
|
|
|
54494
54818
|
return { text: raw, placeholder: false, alts: parts.length > 1 ? parts : null };
|
|
54495
54819
|
}
|
|
54496
54820
|
};
|
|
54497
|
-
function render(name, body, snippet) {
|
|
54821
|
+
function render(name, body, snippet, all) {
|
|
54498
54822
|
return `${name} = {
|
|
54499
|
-
${renderBody(body, " ", snippet, { n: 0 }).join("")}}`;
|
|
54823
|
+
${renderBody(body, " ", snippet, { n: 0 }, all).join("")}}`;
|
|
54500
54824
|
}
|
|
54501
|
-
function renderBody(body, indent, snippet, counter) {
|
|
54825
|
+
function renderBody(body, indent, snippet, counter, all) {
|
|
54502
54826
|
const lines = [];
|
|
54503
54827
|
for (const item of body.items) {
|
|
54828
|
+
if (item.optional && !all) continue;
|
|
54504
54829
|
if (item.key === null) {
|
|
54505
54830
|
lines.push(`${indent}${leaf(item.value, snippet, counter)}
|
|
54506
54831
|
`);
|
|
@@ -54510,7 +54835,7 @@ function renderBody(body, indent, snippet, counter) {
|
|
|
54510
54835
|
if ("items" in item.value) {
|
|
54511
54836
|
lines.push(`${indent}${key} = {
|
|
54512
54837
|
`);
|
|
54513
|
-
lines.push(...renderBody(item.value, indent + " ", snippet, counter));
|
|
54838
|
+
lines.push(...renderBody(item.value, indent + " ", snippet, counter, all));
|
|
54514
54839
|
lines.push(`${indent}}
|
|
54515
54840
|
`);
|
|
54516
54841
|
continue;
|
|
@@ -54531,6 +54856,110 @@ function escapeSnippet(text) {
|
|
|
54531
54856
|
return text.replace(/[\\$}]/g, "\\$&");
|
|
54532
54857
|
}
|
|
54533
54858
|
|
|
54859
|
+
// src/schema/skeletons.ts
|
|
54860
|
+
function escapeSnippet2(text) {
|
|
54861
|
+
return text.replace(/[\\$}]/g, "\\$&");
|
|
54862
|
+
}
|
|
54863
|
+
function leafValue(spec, snippet, c2) {
|
|
54864
|
+
const filled = spec.choices?.[0] ?? spec.placeholder ?? spec.key;
|
|
54865
|
+
if (!snippet) return filled;
|
|
54866
|
+
if (spec.choices && spec.choices.length > 1) return `\${${++c2.n}|${spec.choices.join(",")}|}`;
|
|
54867
|
+
return `\${${++c2.n}:${escapeSnippet2(filled)}}`;
|
|
54868
|
+
}
|
|
54869
|
+
function renderKeys(keys, indent, snippet, c2) {
|
|
54870
|
+
let out = "";
|
|
54871
|
+
for (const spec of keys) {
|
|
54872
|
+
if (spec.block) {
|
|
54873
|
+
out += `${indent}${spec.key} = {
|
|
54874
|
+
`;
|
|
54875
|
+
out += spec.block.length > 0 ? renderKeys(spec.block, indent + " ", snippet, c2) : `${indent} ${snippet ? `$${++c2.n}` : ""}
|
|
54876
|
+
`;
|
|
54877
|
+
out += `${indent}}
|
|
54878
|
+
`;
|
|
54879
|
+
continue;
|
|
54880
|
+
}
|
|
54881
|
+
out += `${indent}${spec.key} = ${leafValue(spec, snippet, c2)}
|
|
54882
|
+
`;
|
|
54883
|
+
}
|
|
54884
|
+
return out;
|
|
54885
|
+
}
|
|
54886
|
+
function renderDefinitionSkeleton(kind, skel, opts = {}) {
|
|
54887
|
+
const one = (snippet) => {
|
|
54888
|
+
const c2 = { n: 0 };
|
|
54889
|
+
const mirrored = skel.nameFromHeader !== void 0 && opts.headerValue === void 0;
|
|
54890
|
+
if (mirrored) c2.n = 1;
|
|
54891
|
+
const prefix = mirrored ? snippet ? `\${1:my_${escapeSnippet2(skel.nameFromHeader)}}` : `my_${skel.nameFromHeader}` : opts.headerValue;
|
|
54892
|
+
const out = opts.withHeader && skel.nameFromHeader ? `${skel.nameFromHeader} = ${prefix}
|
|
54893
|
+
|
|
54894
|
+
` : "";
|
|
54895
|
+
const name = skel.nameFromHeader ? snippet ? `${prefix}.\${${++c2.n}:1}` : `${prefix}.1` : snippet ? `\${${++c2.n}:my_${escapeSnippet2(kind)}}` : `my_${kind}`;
|
|
54896
|
+
const body = skel.keys.length > 0 ? renderKeys(skel.keys, " ", snippet, c2) : ` ${snippet ? `$${++c2.n}` : ""}
|
|
54897
|
+
`;
|
|
54898
|
+
return `${out}${name} = {
|
|
54899
|
+
${body}}`;
|
|
54900
|
+
};
|
|
54901
|
+
return { snippet: one(true), plain: one(false) };
|
|
54902
|
+
}
|
|
54903
|
+
function renderBlockSkeleton(name, block2) {
|
|
54904
|
+
const one = (snippet) => {
|
|
54905
|
+
const body = block2.keys.length > 0 ? renderKeys(block2.keys, " ", snippet, { n: 0 }) : ` ${snippet ? "$1" : ""}
|
|
54906
|
+
`;
|
|
54907
|
+
return `${name} = {
|
|
54908
|
+
${body}}`;
|
|
54909
|
+
};
|
|
54910
|
+
return { snippet: one(true), plain: one(false) };
|
|
54911
|
+
}
|
|
54912
|
+
|
|
54913
|
+
// src/features/definitionSkeletons.ts
|
|
54914
|
+
function definitionDepth(parse, offset) {
|
|
54915
|
+
return blockStackFromParse(parse, offset).filter((s2) => s2 !== "<anon>").length;
|
|
54916
|
+
}
|
|
54917
|
+
function count(n) {
|
|
54918
|
+
return n.toLocaleString("en-US");
|
|
54919
|
+
}
|
|
54920
|
+
function headerValue(parse, key) {
|
|
54921
|
+
for (const stmt of parse.root.statements) {
|
|
54922
|
+
if (stmt.kind !== "assignment" || stmt.key.quoted || stmt.key.text !== key) continue;
|
|
54923
|
+
if (stmt.value?.kind === "scalar") return stmt.value.text;
|
|
54924
|
+
}
|
|
54925
|
+
return void 0;
|
|
54926
|
+
}
|
|
54927
|
+
function skeletonsAt(parse, offset, kind, skeletons) {
|
|
54928
|
+
const skel = skeletons?.[kind];
|
|
54929
|
+
if (!skel) return [];
|
|
54930
|
+
const depth = definitionDepth(parse, offset);
|
|
54931
|
+
if (depth === 0) return [definitionOffer(parse, kind, skel)];
|
|
54932
|
+
if (depth !== 1) return [];
|
|
54933
|
+
return blockOffers(kind, skel);
|
|
54934
|
+
}
|
|
54935
|
+
function skeletonsFor(parse, kind, skeletons) {
|
|
54936
|
+
const skel = skeletons?.[kind];
|
|
54937
|
+
if (!skel) return [];
|
|
54938
|
+
return [definitionOffer(parse, kind, skel), ...blockOffers(kind, skel)];
|
|
54939
|
+
}
|
|
54940
|
+
function definitionOffer(parse, kind, skel) {
|
|
54941
|
+
const existing = skel.nameFromHeader ? headerValue(parse, skel.nameFromHeader) : void 0;
|
|
54942
|
+
return {
|
|
54943
|
+
id: kind,
|
|
54944
|
+
label: `new ${kind.replace(/_/g, " ")}`,
|
|
54945
|
+
detail: `skeleton measured over ${count(skel.sampled)} vanilla definitions`,
|
|
54946
|
+
form: "definition",
|
|
54947
|
+
text: renderDefinitionSkeleton(kind, skel, {
|
|
54948
|
+
headerValue: existing,
|
|
54949
|
+
withHeader: skel.nameFromHeader !== void 0 && existing === void 0
|
|
54950
|
+
})
|
|
54951
|
+
};
|
|
54952
|
+
}
|
|
54953
|
+
function blockOffers(kind, skel) {
|
|
54954
|
+
return Object.entries(skel.blocks ?? {}).map(([name, block2]) => ({
|
|
54955
|
+
id: `${kind}.${name}`,
|
|
54956
|
+
label: `${name} block`,
|
|
54957
|
+
detail: `skeleton measured over ${count(block2.sampled)} vanilla ${name} blocks`,
|
|
54958
|
+
form: "block",
|
|
54959
|
+
text: renderBlockSkeleton(name, block2)
|
|
54960
|
+
}));
|
|
54961
|
+
}
|
|
54962
|
+
|
|
54534
54963
|
// src/features/completion.ts
|
|
54535
54964
|
var MAX_ITEMS = 1e3;
|
|
54536
54965
|
function itemKind(kind) {
|
|
@@ -54544,9 +54973,9 @@ var TIER_OTHER = "4";
|
|
|
54544
54973
|
var SRC_MOD = "0";
|
|
54545
54974
|
var SRC_OTHER = "1";
|
|
54546
54975
|
var SNIPPET_KINDS = /* @__PURE__ */ new Set(["scripted_effect", "scripted_trigger", "scripted_modifier"]);
|
|
54547
|
-
function freqBucket(
|
|
54548
|
-
if (!
|
|
54549
|
-
const b = 99 - Math.min(99, Math.round(Math.log2(
|
|
54976
|
+
function freqBucket(count2) {
|
|
54977
|
+
if (!count2 || count2 <= 0) return "99";
|
|
54978
|
+
const b = 99 - Math.min(99, Math.round(Math.log2(count2 + 1) * 6));
|
|
54550
54979
|
return String(Math.max(0, b)).padStart(2, "0");
|
|
54551
54980
|
}
|
|
54552
54981
|
function rankBucket(rank3) {
|
|
@@ -54793,7 +55222,10 @@ var CompletionFeature = class {
|
|
|
54793
55222
|
}
|
|
54794
55223
|
ranked.push(out);
|
|
54795
55224
|
}
|
|
54796
|
-
const
|
|
55225
|
+
const lead = [...structureItems, ...this.skeletonItems(result, offset, entry, lineSuffix)].filter(
|
|
55226
|
+
(s2) => matchesTypedWord(wordLow, s2.label)
|
|
55227
|
+
);
|
|
55228
|
+
const structured = lead.length > 0 ? [...lead, ...ranked] : ranked;
|
|
54797
55229
|
return finalize(
|
|
54798
55230
|
structured,
|
|
54799
55231
|
typedWord,
|
|
@@ -54802,6 +55234,33 @@ var CompletionFeature = class {
|
|
|
54802
55234
|
true
|
|
54803
55235
|
);
|
|
54804
55236
|
}
|
|
55237
|
+
/**
|
|
55238
|
+
* Definition and child-block skeletons (schema/skeletons.ts) as items of their
|
|
55239
|
+
* own kind, ranked right after the block's structure keys.
|
|
55240
|
+
*
|
|
55241
|
+
* Gated on a BLANK line tail: a multi-line insert must not land inside an
|
|
55242
|
+
* existing statement, and half a definition pasted over `= { … }` is worse
|
|
55243
|
+
* than no offer. That gate also keeps these items out of every rank-eval
|
|
55244
|
+
* sample, which always leaves the `= …` in place when it strips a key, so the
|
|
55245
|
+
* ranking of existing items is unchanged by construction.
|
|
55246
|
+
*/
|
|
55247
|
+
skeletonItems(result, offset, entry, lineSuffix) {
|
|
55248
|
+
if (!entry?.kind || lineSuffix.trim() !== "") return [];
|
|
55249
|
+
return skeletonsAt(result, offset, entry.kind, activeProfile().skeletons).map((offer) => {
|
|
55250
|
+
const item = {
|
|
55251
|
+
label: offer.label,
|
|
55252
|
+
kind: import_node2.CompletionItemKind.Snippet,
|
|
55253
|
+
detail: offer.detail,
|
|
55254
|
+
// Structure tier, coldest rank: after every structure key of the block
|
|
55255
|
+
// and ahead of the token list. At a file's top level there are no
|
|
55256
|
+
// structure keys, so the skeleton leads a list that otherwise has
|
|
55257
|
+
// nothing to offer outside a definition body.
|
|
55258
|
+
sortText: TIER_STRUCTURE + rankBucket(99) + SRC_MOD + offer.label
|
|
55259
|
+
};
|
|
55260
|
+
setInsert(item, offer.text.snippet, offer.text.plain);
|
|
55261
|
+
return item;
|
|
55262
|
+
});
|
|
55263
|
+
}
|
|
54805
55264
|
/**
|
|
54806
55265
|
* Completing a scripted effect/trigger/modifier inserts a ready-to-fill
|
|
54807
55266
|
* block: one `PARAM = <tabstop>` line per $PARAM$ the definition's body
|
|
@@ -54880,8 +55339,8 @@ ${plain}
|
|
|
54880
55339
|
this.cache.clear();
|
|
54881
55340
|
this.cacheRevision = this.data.index.revision;
|
|
54882
55341
|
}
|
|
54883
|
-
const
|
|
54884
|
-
if (
|
|
55342
|
+
const cached2 = this.cache.get(context);
|
|
55343
|
+
if (cached2) return cached2;
|
|
54885
55344
|
const items = [];
|
|
54886
55345
|
const tokens = [];
|
|
54887
55346
|
const sources = [];
|
|
@@ -55428,11 +55887,11 @@ function insertMember(data2, map, name, member) {
|
|
|
55428
55887
|
data2.count++;
|
|
55429
55888
|
return;
|
|
55430
55889
|
}
|
|
55431
|
-
const
|
|
55432
|
-
const other =
|
|
55433
|
-
if (!
|
|
55434
|
-
if (!
|
|
55435
|
-
map.set(name,
|
|
55890
|
+
const keep2 = prev.ret !== null && member.ret === null ? prev : member;
|
|
55891
|
+
const other = keep2 === prev ? member : prev;
|
|
55892
|
+
if (!keep2.desc && other.desc) keep2.desc = other.desc;
|
|
55893
|
+
if (!keep2.args && other.args) keep2.args = other.args;
|
|
55894
|
+
map.set(name, keep2);
|
|
55436
55895
|
}
|
|
55437
55896
|
function dumpFilesIn(dir) {
|
|
55438
55897
|
const files = [];
|
|
@@ -56113,16 +56572,16 @@ function openLiteralPrefix(expr) {
|
|
|
56113
56572
|
}
|
|
56114
56573
|
return open === -1 ? null : expr.slice(open + 1);
|
|
56115
56574
|
}
|
|
56116
|
-
function freq3(
|
|
56117
|
-
return String(999 - Math.min(998, Math.round(Math.log2(1 +
|
|
56575
|
+
function freq3(count2) {
|
|
56576
|
+
return String(999 - Math.min(998, Math.round(Math.log2(1 + count2) * 55))).padStart(3, "0");
|
|
56118
56577
|
}
|
|
56119
56578
|
function memberDetail(member, owner) {
|
|
56120
56579
|
const args = member.args && member.args.length > 0 ? `( ${member.args.join(", ")} )` : "";
|
|
56121
56580
|
const ret = member.ret ? ` \u2192 ${member.ret}` : "";
|
|
56122
56581
|
return `${owner ? owner + " " : ""}${member.kind}${args}${ret}`;
|
|
56123
56582
|
}
|
|
56124
|
-
function usesSuffix(
|
|
56125
|
-
return
|
|
56583
|
+
function usesSuffix(count2) {
|
|
56584
|
+
return count2 > 0 ? ` \xB7 ${count2.toLocaleString("en-US")}\xD7 in vanilla` : "";
|
|
56126
56585
|
}
|
|
56127
56586
|
var SOURCE_LABEL = {
|
|
56128
56587
|
dump: "your DumpDataTypes log",
|
|
@@ -56189,14 +56648,14 @@ function provideDataFnCompletion(data2, usage, linePrefix, index, cursor) {
|
|
|
56189
56648
|
}
|
|
56190
56649
|
const lits = usage.literals.get(fn);
|
|
56191
56650
|
if (lits) {
|
|
56192
|
-
for (const [value,
|
|
56651
|
+
for (const [value, count2] of lits) {
|
|
56193
56652
|
if (seen.has(value)) continue;
|
|
56194
56653
|
seen.add(value);
|
|
56195
56654
|
items2.push({
|
|
56196
56655
|
label: value,
|
|
56197
56656
|
kind: import_node3.CompletionItemKind.Value,
|
|
56198
|
-
detail: `argument of ${fn}${usesSuffix(
|
|
56199
|
-
sortText: "1" + freq3(
|
|
56657
|
+
detail: `argument of ${fn}${usesSuffix(count2)}`,
|
|
56658
|
+
sortText: "1" + freq3(count2) + value,
|
|
56200
56659
|
data: { t: "dfn" }
|
|
56201
56660
|
});
|
|
56202
56661
|
}
|
|
@@ -56205,11 +56664,11 @@ function provideDataFnCompletion(data2, usage, linePrefix, index, cursor) {
|
|
|
56205
56664
|
}
|
|
56206
56665
|
const fmt3 = /\|([A-Za-z0-9+\-=*%.]*)$/.exec(expr);
|
|
56207
56666
|
if (fmt3) {
|
|
56208
|
-
const items2 = [...usage.formats.entries()].filter(([,
|
|
56667
|
+
const items2 = [...usage.formats.entries()].filter(([, count2]) => count2 >= 3).map(([suffix, count2]) => ({
|
|
56209
56668
|
label: suffix,
|
|
56210
56669
|
kind: import_node3.CompletionItemKind.EnumMember,
|
|
56211
|
-
detail: `format suffix${usesSuffix(
|
|
56212
|
-
sortText: freq3(
|
|
56670
|
+
detail: `format suffix${usesSuffix(count2)}`,
|
|
56671
|
+
sortText: freq3(count2) + suffix,
|
|
56213
56672
|
data: { t: "dfn" }
|
|
56214
56673
|
}));
|
|
56215
56674
|
return finish(items2, fmt3[1]);
|
|
@@ -56221,30 +56680,30 @@ function provideDataFnCompletion(data2, usage, linePrefix, index, cursor) {
|
|
|
56221
56680
|
const seen = /* @__PURE__ */ new Set();
|
|
56222
56681
|
for (const type of data2.types.keys()) {
|
|
56223
56682
|
seen.add(type);
|
|
56224
|
-
const
|
|
56683
|
+
const count2 = usage.starts.get(type) ?? 0;
|
|
56225
56684
|
items.push({
|
|
56226
56685
|
label: type,
|
|
56227
56686
|
kind: import_node3.CompletionItemKind.Class,
|
|
56228
|
-
detail: `data type${usesSuffix(
|
|
56229
|
-
sortText: freq3(
|
|
56687
|
+
detail: `data type${usesSuffix(count2)}`,
|
|
56688
|
+
sortText: freq3(count2) + type,
|
|
56230
56689
|
data: { t: "dfn" }
|
|
56231
56690
|
});
|
|
56232
56691
|
}
|
|
56233
56692
|
for (const [name, member] of data2.globals) {
|
|
56234
56693
|
if (seen.has(name)) continue;
|
|
56235
56694
|
seen.add(name);
|
|
56236
|
-
const
|
|
56695
|
+
const count2 = usage.starts.get(name) ?? 0;
|
|
56237
56696
|
const doc = member.desc ?? describeDataFn(name, member);
|
|
56238
56697
|
items.push({
|
|
56239
56698
|
label: name,
|
|
56240
56699
|
kind: member.kind === "promote" ? import_node3.CompletionItemKind.Variable : import_node3.CompletionItemKind.Function,
|
|
56241
|
-
detail: `global ${memberDetail(member)}${usesSuffix(
|
|
56700
|
+
detail: `global ${memberDetail(member)}${usesSuffix(count2)}`,
|
|
56242
56701
|
...doc ? { documentation: doc } : {},
|
|
56243
|
-
sortText: freq3(
|
|
56702
|
+
sortText: freq3(count2) + name,
|
|
56244
56703
|
data: { t: "dfn" }
|
|
56245
56704
|
});
|
|
56246
56705
|
}
|
|
56247
|
-
for (const [name,
|
|
56706
|
+
for (const [name, count2] of usage.starts) {
|
|
56248
56707
|
if (seen.has(name)) continue;
|
|
56249
56708
|
const called = usage.argCounts.has(name);
|
|
56250
56709
|
const hasMembers = usage.pairs.has(name);
|
|
@@ -56252,9 +56711,9 @@ function provideDataFnCompletion(data2, usage, linePrefix, index, cursor) {
|
|
|
56252
56711
|
items.push({
|
|
56253
56712
|
label: name,
|
|
56254
56713
|
kind: hasMembers && !called ? import_node3.CompletionItemKind.Class : import_node3.CompletionItemKind.Function,
|
|
56255
|
-
detail: `vanilla usage${usesSuffix(
|
|
56714
|
+
detail: `vanilla usage${usesSuffix(count2)} (not in the data-type tables)`,
|
|
56256
56715
|
...doc ? { documentation: doc } : {},
|
|
56257
|
-
sortText: freq3(
|
|
56716
|
+
sortText: freq3(count2) + name,
|
|
56258
56717
|
data: { t: "dfn" }
|
|
56259
56718
|
});
|
|
56260
56719
|
}
|
|
@@ -56279,15 +56738,15 @@ function provideDataFnCompletion(data2, usage, linePrefix, index, cursor) {
|
|
|
56279
56738
|
});
|
|
56280
56739
|
}
|
|
56281
56740
|
const harvested = usage.pairs.get(ownerType) ?? (pairOwner ? usage.pairs.get(pairOwner) : void 0);
|
|
56282
|
-
for (const [name,
|
|
56741
|
+
for (const [name, count2] of harvested ?? []) {
|
|
56283
56742
|
if (seen.has(name)) continue;
|
|
56284
56743
|
const doc = describeDataFn(name, null);
|
|
56285
56744
|
items.push({
|
|
56286
56745
|
label: name,
|
|
56287
56746
|
kind: import_node3.CompletionItemKind.Method,
|
|
56288
|
-
detail: `vanilla usage on ${pairOwner ?? ownerType}${usesSuffix(
|
|
56747
|
+
detail: `vanilla usage on ${pairOwner ?? ownerType}${usesSuffix(count2)}`,
|
|
56289
56748
|
...doc ? { documentation: doc } : {},
|
|
56290
|
-
sortText: freq3(
|
|
56749
|
+
sortText: freq3(count2) + name,
|
|
56291
56750
|
data: { t: "dfn" }
|
|
56292
56751
|
});
|
|
56293
56752
|
}
|
|
@@ -56295,25 +56754,25 @@ function provideDataFnCompletion(data2, usage, linePrefix, index, cursor) {
|
|
|
56295
56754
|
}
|
|
56296
56755
|
const harvestedPairs = pairOwner ? usage.pairs.get(pairOwner) : void 0;
|
|
56297
56756
|
if (harvestedPairs && harvestedPairs.size > 0) {
|
|
56298
|
-
for (const [name,
|
|
56757
|
+
for (const [name, count2] of harvestedPairs) {
|
|
56299
56758
|
const doc = describeDataFn(name, null);
|
|
56300
56759
|
items.push({
|
|
56301
56760
|
label: name,
|
|
56302
56761
|
kind: import_node3.CompletionItemKind.Method,
|
|
56303
|
-
detail: `vanilla usage on ${pairOwner}${usesSuffix(
|
|
56762
|
+
detail: `vanilla usage on ${pairOwner}${usesSuffix(count2)}`,
|
|
56304
56763
|
...doc ? { documentation: doc } : {},
|
|
56305
|
-
sortText: freq3(
|
|
56764
|
+
sortText: freq3(count2) + name,
|
|
56306
56765
|
data: { t: "dfn" }
|
|
56307
56766
|
});
|
|
56308
56767
|
}
|
|
56309
56768
|
return finish(items, typed);
|
|
56310
56769
|
}
|
|
56311
|
-
for (const [name,
|
|
56770
|
+
for (const [name, count2] of usage.memberPool) {
|
|
56312
56771
|
items.push({
|
|
56313
56772
|
label: name,
|
|
56314
56773
|
kind: import_node3.CompletionItemKind.Method,
|
|
56315
|
-
detail: `vanilla usage${usesSuffix(
|
|
56316
|
-
sortText: freq3(
|
|
56774
|
+
detail: `vanilla usage${usesSuffix(count2)} (chain not resolved)`,
|
|
56775
|
+
sortText: freq3(count2) + name,
|
|
56317
56776
|
data: { t: "dfn" }
|
|
56318
56777
|
});
|
|
56319
56778
|
}
|
|
@@ -56551,10 +57010,10 @@ function provideDataFnSignature(data2, usage, lineText, character) {
|
|
|
56551
57010
|
if (!arities || arities.size === 0) return null;
|
|
56552
57011
|
let best = 0;
|
|
56553
57012
|
let bestCount = -1;
|
|
56554
|
-
for (const [arity,
|
|
56555
|
-
if (
|
|
57013
|
+
for (const [arity, count2] of arities) {
|
|
57014
|
+
if (count2 > bestCount) {
|
|
56556
57015
|
best = arity;
|
|
56557
|
-
bestCount =
|
|
57016
|
+
bestCount = count2;
|
|
56558
57017
|
}
|
|
56559
57018
|
}
|
|
56560
57019
|
if (best === 0) return null;
|
|
@@ -56821,13 +57280,13 @@ function provideGuiCompletion(data2, document, offset, settings2) {
|
|
|
56821
57280
|
const typeInfo = enclosing ? guiSchema().types[enclosing] : null;
|
|
56822
57281
|
const props = typeInfo?.props ?? (enclosing ? guiSchema().globalProps : {});
|
|
56823
57282
|
const ranked = Object.entries(props).sort((a, b) => b[1] - a[1]);
|
|
56824
|
-
ranked.forEach(([key,
|
|
57283
|
+
ranked.forEach(([key, count2], i) => {
|
|
56825
57284
|
seen.add(key);
|
|
56826
57285
|
const alsoType = key in guiSchema().types;
|
|
56827
57286
|
items.push({
|
|
56828
57287
|
label: key,
|
|
56829
57288
|
kind: itemKind(alsoType ? "gui_type" : "gui_property"),
|
|
56830
|
-
detail: typeInfo ? `${alsoType ? "child widget" : "property"} of ${enclosing} \xB7 ${
|
|
57289
|
+
detail: typeInfo ? `${alsoType ? "child widget" : "property"} of ${enclosing} \xB7 ${count2}\xD7 in vanilla` : `gui ${alsoType ? "widget" : "property"} \xB7 ${count2}\xD7 in vanilla`,
|
|
56831
57290
|
sortText: TIER_PROP + rank2(i) + key
|
|
56832
57291
|
});
|
|
56833
57292
|
});
|
|
@@ -57020,14 +57479,14 @@ function computeEventDetail(data2, schema2, id) {
|
|
|
57020
57479
|
for (const child of block2.statements) {
|
|
57021
57480
|
if (child.kind !== "assignment") continue;
|
|
57022
57481
|
const key = child.key.text.toLowerCase();
|
|
57023
|
-
const
|
|
57482
|
+
const scalar3 = child.value?.kind === "scalar" ? child.value.text : null;
|
|
57024
57483
|
const sub = childBlock4(child);
|
|
57025
|
-
if (key === "type" &&
|
|
57026
|
-
else if (key === "hidden" &&
|
|
57027
|
-
else if (key === "theme" &&
|
|
57028
|
-
else if (key === "title") detail2.title =
|
|
57029
|
-
else if (key === "desc") detail2.desc =
|
|
57030
|
-
else if (key === "flavor") detail2.flavor =
|
|
57484
|
+
if (key === "type" && scalar3) detail2.type = scalar3;
|
|
57485
|
+
else if (key === "hidden" && scalar3) detail2.hidden = scalar3 === "yes";
|
|
57486
|
+
else if (key === "theme" && scalar3) detail2.theme = scalar3;
|
|
57487
|
+
else if (key === "title") detail2.title = scalar3 ? locField(data2, scalar3) : { key: "", dynamic: true };
|
|
57488
|
+
else if (key === "desc") detail2.desc = scalar3 ? locField(data2, scalar3) : { key: "", dynamic: true };
|
|
57489
|
+
else if (key === "flavor") detail2.flavor = scalar3 ? locField(data2, scalar3) : { key: "", dynamic: true };
|
|
57031
57490
|
else if (SECTION_KEYS.has(key) && sub)
|
|
57032
57491
|
detail2.sections.push(section(data2, schema2, child.key.text, sub, lineOf));
|
|
57033
57492
|
else if (key === "option" && sub) detail2.options.push(option(data2, schema2, sub, lineOf));
|
|
@@ -57484,7 +57943,9 @@ function buildExampleWikiIndex(src) {
|
|
|
57484
57943
|
}
|
|
57485
57944
|
}
|
|
57486
57945
|
entries.sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
|
|
57487
|
-
const sources = [
|
|
57946
|
+
const sources = [
|
|
57947
|
+
`Triggers, effects, event targets and modifiers come from ${src.tokenSource.replace(/\.$/, "")}.`
|
|
57948
|
+
];
|
|
57488
57949
|
sources.push(
|
|
57489
57950
|
src.dataTypes.source === "data_types.log" ? "Datafunctions and data types come from your own DumpDataTypes output." : "Datafunctions and data types come from the bundled wiki tables. Run DumpDataTypes in the game console for the list your game version really has."
|
|
57490
57951
|
);
|
|
@@ -57521,11 +57982,11 @@ function memberProvenance(member) {
|
|
|
57521
57982
|
function usageBlock(token) {
|
|
57522
57983
|
return token.usage && token.usage.trim() !== "" ? token.usage : void 0;
|
|
57523
57984
|
}
|
|
57524
|
-
function emptyDetail(name, kind,
|
|
57985
|
+
function emptyDetail(name, kind, count2) {
|
|
57525
57986
|
return {
|
|
57526
57987
|
name,
|
|
57527
57988
|
kind,
|
|
57528
|
-
count,
|
|
57989
|
+
count: count2,
|
|
57529
57990
|
doc: "",
|
|
57530
57991
|
scopes: [],
|
|
57531
57992
|
literals: [],
|
|
@@ -57661,8 +58122,8 @@ function dataFnDetail(src, name, kind, lines) {
|
|
|
57661
58122
|
const short2 = owner ? name.slice(dot + 1) : name;
|
|
57662
58123
|
const member = owner ? membersOf(src.dataTypes, owner)?.get(short2) : src.dataTypes.globals.get(short2);
|
|
57663
58124
|
if (!member) return null;
|
|
57664
|
-
const
|
|
57665
|
-
const detail2 = emptyDetail(name, kind,
|
|
58125
|
+
const count2 = owner ? memberCount(src.usage, owner, short2) : src.usage.starts.get(short2) ?? 0;
|
|
58126
|
+
const detail2 = emptyDetail(name, kind, count2);
|
|
57666
58127
|
if (owner) detail2.owner = owner;
|
|
57667
58128
|
detail2.doc = member.desc ?? "";
|
|
57668
58129
|
if (member.ret) detail2.ret = member.ret;
|
|
@@ -57860,12 +58321,14 @@ var SYNTAX_LINE = /^(?:<[^>]+>|[A-Za-z_][A-Za-z0-9_]*)\s*(?:[<>]=?|!=|=)/;
|
|
|
57860
58321
|
var TAG_LINE = /^Tag:\s*([A-Za-z0-9_.$]+)\s*(?:,\s*(.*))?$/;
|
|
57861
58322
|
var SCOPE_LINE = /^(Supported [Ss]copes|Input [Ss]copes|Output [Ss]copes):\s*(.*)$/;
|
|
57862
58323
|
var META_LINE = /^(Supported [Tt]argets|Targets?|Traits|Categories|Use [Aa]reas|Requires [Dd]ata|Wild[ _]?[Cc]ard|Global [Ll]ink):\s*(.*)$/;
|
|
58324
|
+
var braceDelta = (s2) => (s2.match(/\{/g) ?? []).length - (s2.match(/\}/g) ?? []).length;
|
|
57863
58325
|
function parseLog(content, kind) {
|
|
57864
58326
|
const tokens = [];
|
|
57865
58327
|
const seen = /* @__PURE__ */ new Set();
|
|
57866
58328
|
const lines = content.split(/\r?\n/);
|
|
57867
58329
|
let current2 = null;
|
|
57868
58330
|
let inUsage = false;
|
|
58331
|
+
let openBraces = 0;
|
|
57869
58332
|
const flush = () => {
|
|
57870
58333
|
if (current2 && current2.name && !seen.has(current2.name)) {
|
|
57871
58334
|
current2.doc = current2.doc.trim();
|
|
@@ -57877,6 +58340,7 @@ function parseLog(content, kind) {
|
|
|
57877
58340
|
}
|
|
57878
58341
|
current2 = null;
|
|
57879
58342
|
inUsage = false;
|
|
58343
|
+
openBraces = 0;
|
|
57880
58344
|
};
|
|
57881
58345
|
for (const rawLine of lines) {
|
|
57882
58346
|
const line = rawLine.trimEnd();
|
|
@@ -57886,7 +58350,7 @@ function parseLog(content, kind) {
|
|
|
57886
58350
|
}
|
|
57887
58351
|
const trimmed = line.trim();
|
|
57888
58352
|
if (trimmed === "") {
|
|
57889
|
-
if (current2 && inUsage && current2.usage) current2.usage += "\n";
|
|
58353
|
+
if (current2 && (inUsage || openBraces > 0) && current2.usage) current2.usage += "\n";
|
|
57890
58354
|
continue;
|
|
57891
58355
|
}
|
|
57892
58356
|
if (trimmed.startsWith("Tag:")) {
|
|
@@ -57914,6 +58378,15 @@ function parseLog(content, kind) {
|
|
|
57914
58378
|
}
|
|
57915
58379
|
continue;
|
|
57916
58380
|
}
|
|
58381
|
+
if (openBraces > 0) {
|
|
58382
|
+
if (applyMetaLine(current2, trimmed)) {
|
|
58383
|
+
openBraces = 0;
|
|
58384
|
+
continue;
|
|
58385
|
+
}
|
|
58386
|
+
current2.usage += "\n" + line;
|
|
58387
|
+
openBraces += braceDelta(line);
|
|
58388
|
+
continue;
|
|
58389
|
+
}
|
|
57917
58390
|
if (applyMetaLine(current2, trimmed)) {
|
|
57918
58391
|
inUsage = false;
|
|
57919
58392
|
continue;
|
|
@@ -57928,6 +58401,7 @@ function parseLog(content, kind) {
|
|
|
57928
58401
|
}
|
|
57929
58402
|
if (current2.usage === void 0 && SYNTAX_LINE.test(trimmed)) {
|
|
57930
58403
|
current2.usage = trimmed;
|
|
58404
|
+
openBraces = Math.max(0, braceDelta(trimmed));
|
|
57931
58405
|
continue;
|
|
57932
58406
|
}
|
|
57933
58407
|
current2.doc = current2.doc === "" ? trimmed : current2.doc + "\n" + trimmed;
|
|
@@ -57957,7 +58431,6 @@ var MD_BOLD_LABEL = /^\*\*([^*]+)\*\*\s*:/;
|
|
|
57957
58431
|
var MASKED_NAME = /^([A-Za-z0-9_.$]+):\s*$/;
|
|
57958
58432
|
var MASKED_FIELD = /^(Mask|Name|Description):\s*(.*)$/;
|
|
57959
58433
|
var SECTION_BANNER = /^-{3,}/;
|
|
57960
|
-
var braceDelta = (s2) => (s2.match(/\{/g) ?? []).length - (s2.match(/\}/g) ?? []).length;
|
|
57961
58434
|
function parseMarkdownLog(content, kind) {
|
|
57962
58435
|
const tokens = [];
|
|
57963
58436
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -58127,13 +58600,13 @@ function loadTokenData(logsDir, cacheFile, forceReparse = false) {
|
|
|
58127
58600
|
return result;
|
|
58128
58601
|
};
|
|
58129
58602
|
if (forceReparse) return fresh();
|
|
58130
|
-
let
|
|
58603
|
+
let cached2;
|
|
58131
58604
|
try {
|
|
58132
|
-
|
|
58605
|
+
cached2 = JSON.parse(fs12.readFileSync(cacheFile, "utf8"));
|
|
58133
58606
|
} catch {
|
|
58134
58607
|
return fresh();
|
|
58135
58608
|
}
|
|
58136
|
-
if (
|
|
58609
|
+
if (cached2.cacheFormat !== DOCS_CACHE_FORMAT || !cached2.tokens || !cached2.templates || !cached2.mtimes)
|
|
58137
58610
|
return fresh();
|
|
58138
58611
|
const currentMtimes = {};
|
|
58139
58612
|
const missing = [];
|
|
@@ -58144,14 +58617,14 @@ function loadTokenData(logsDir, cacheFile, forceReparse = false) {
|
|
|
58144
58617
|
missing.push(file);
|
|
58145
58618
|
}
|
|
58146
58619
|
}
|
|
58147
|
-
const cachedKeys = Object.keys(
|
|
58620
|
+
const cachedKeys = Object.keys(cached2.mtimes).sort().join(",");
|
|
58148
58621
|
const currentKeys = Object.keys(currentMtimes).sort().join(",");
|
|
58149
|
-
const same = cachedKeys === currentKeys && Object.entries(currentMtimes).every(([f, t]) =>
|
|
58622
|
+
const same = cachedKeys === currentKeys && Object.entries(currentMtimes).every(([f, t]) => cached2.mtimes[f] === t);
|
|
58150
58623
|
if (!same) return fresh();
|
|
58151
58624
|
return {
|
|
58152
|
-
tokens:
|
|
58153
|
-
templates:
|
|
58154
|
-
mtimes:
|
|
58625
|
+
tokens: cached2.tokens,
|
|
58626
|
+
templates: cached2.templates,
|
|
58627
|
+
mtimes: cached2.mtimes,
|
|
58155
58628
|
missing,
|
|
58156
58629
|
fromCache: true
|
|
58157
58630
|
};
|
|
@@ -58676,18 +59149,18 @@ function scanRoots(gamePath, locLanguage) {
|
|
|
58676
59149
|
}
|
|
58677
59150
|
var CACHE_VERSION = 1;
|
|
58678
59151
|
function usageStamp(gamePath, locLanguage) {
|
|
58679
|
-
let
|
|
59152
|
+
let count2 = 0;
|
|
58680
59153
|
let size = 0;
|
|
58681
59154
|
for (const [root, ext] of scanRoots(gamePath, locLanguage)) {
|
|
58682
59155
|
for (const file of listFiles(root, ext)) {
|
|
58683
|
-
|
|
59156
|
+
count2++;
|
|
58684
59157
|
try {
|
|
58685
59158
|
size += fs16.statSync(file).size;
|
|
58686
59159
|
} catch {
|
|
58687
59160
|
}
|
|
58688
59161
|
}
|
|
58689
59162
|
}
|
|
58690
|
-
return `${CACHE_VERSION}:${gamePath}:${locLanguage}:${
|
|
59163
|
+
return `${CACHE_VERSION}:${gamePath}:${locLanguage}:${count2}:${size}`;
|
|
58691
59164
|
}
|
|
58692
59165
|
function toObj(map) {
|
|
58693
59166
|
return Object.fromEntries(map);
|
|
@@ -58714,29 +59187,29 @@ function serialize(usage, stamp) {
|
|
|
58714
59187
|
exprs: usage.exprs
|
|
58715
59188
|
};
|
|
58716
59189
|
}
|
|
58717
|
-
function deserialize(
|
|
59190
|
+
function deserialize(cache6) {
|
|
58718
59191
|
return {
|
|
58719
|
-
starts: toMap(
|
|
58720
|
-
pairs: new Map(Object.entries(
|
|
58721
|
-
memberPool: toMap(
|
|
59192
|
+
starts: toMap(cache6.starts),
|
|
59193
|
+
pairs: new Map(Object.entries(cache6.pairs ?? {}).map(([k, v]) => [k, toMap(v)])),
|
|
59194
|
+
memberPool: toMap(cache6.memberPool),
|
|
58722
59195
|
argCounts: new Map(
|
|
58723
|
-
Object.entries(
|
|
59196
|
+
Object.entries(cache6.argCounts ?? {}).map(([k, v]) => [
|
|
58724
59197
|
k,
|
|
58725
59198
|
new Map(Object.entries(v).map(([n, c2]) => [Number(n), c2]))
|
|
58726
59199
|
])
|
|
58727
59200
|
),
|
|
58728
|
-
literals: new Map(Object.entries(
|
|
58729
|
-
formats: toMap(
|
|
58730
|
-
examples: toMap(
|
|
58731
|
-
files:
|
|
58732
|
-
exprs:
|
|
59201
|
+
literals: new Map(Object.entries(cache6.literals ?? {}).map(([k, v]) => [k, toMap(v)])),
|
|
59202
|
+
formats: toMap(cache6.formats),
|
|
59203
|
+
examples: toMap(cache6.examples),
|
|
59204
|
+
files: cache6.files ?? 0,
|
|
59205
|
+
exprs: cache6.exprs ?? 0
|
|
58733
59206
|
};
|
|
58734
59207
|
}
|
|
58735
59208
|
async function loadDataFnUsageAsync(gamePath, locLanguage, cacheFile, force = false) {
|
|
58736
59209
|
if (!gamePath) return { usage: emptyUsage(), fromCache: false };
|
|
58737
59210
|
const stamp = usageStamp(gamePath, locLanguage);
|
|
58738
|
-
const
|
|
58739
|
-
if (
|
|
59211
|
+
const cached2 = readCache(cacheFile, stamp, force);
|
|
59212
|
+
if (cached2) return { usage: cached2, fromCache: true };
|
|
58740
59213
|
const usage = emptyUsage();
|
|
58741
59214
|
const yieldNow3 = () => new Promise((resolve2) => setImmediate(resolve2));
|
|
58742
59215
|
for (const [root, ext] of scanRoots(gamePath, locLanguage)) {
|
|
@@ -58751,8 +59224,8 @@ async function loadDataFnUsageAsync(gamePath, locLanguage, cacheFile, force = fa
|
|
|
58751
59224
|
function readCache(cacheFile, stamp, force) {
|
|
58752
59225
|
if (!cacheFile || force) return null;
|
|
58753
59226
|
try {
|
|
58754
|
-
const
|
|
58755
|
-
if (
|
|
59227
|
+
const cache6 = JSON.parse(fs16.readFileSync(cacheFile, "utf8"));
|
|
59228
|
+
if (cache6.version === CACHE_VERSION && cache6.stamp === stamp) return deserialize(cache6);
|
|
58756
59229
|
} catch {
|
|
58757
59230
|
}
|
|
58758
59231
|
return null;
|
|
@@ -59457,16 +59930,16 @@ function extractReferencesParsed(root, lines, file, source, schema2, isEngineTok
|
|
|
59457
59930
|
if (chain !== void 0) ref.chain = chain;
|
|
59458
59931
|
references.push(ref);
|
|
59459
59932
|
};
|
|
59460
|
-
const scanValueScalar = (
|
|
59461
|
-
if (
|
|
59462
|
-
const text =
|
|
59933
|
+
const scanValueScalar = (scalar3) => {
|
|
59934
|
+
if (scalar3.quoted) return;
|
|
59935
|
+
const text = scalar3.text;
|
|
59463
59936
|
const m = PREFIX_VALUE.exec(text);
|
|
59464
59937
|
if (!m) return;
|
|
59465
59938
|
const prefix = m[1];
|
|
59466
59939
|
let name = m[2];
|
|
59467
59940
|
const dot = name.indexOf(".");
|
|
59468
59941
|
if (dot >= 0) name = name.slice(0, dot);
|
|
59469
|
-
const offset =
|
|
59942
|
+
const offset = scalar3.range.start + prefix.length + 1;
|
|
59470
59943
|
if (VAR_PREFIXES.has(prefix)) {
|
|
59471
59944
|
pushRef(name, VAR_PREFIX_KINDS[prefix], offset);
|
|
59472
59945
|
} else if (prefix === "scope") {
|
|
@@ -60202,8 +60675,20 @@ var ModOriginResolver = class {
|
|
|
60202
60675
|
};
|
|
60203
60676
|
|
|
60204
60677
|
// src/schema/loader.ts
|
|
60678
|
+
var fs23 = __toESM(require("fs"));
|
|
60679
|
+
var path26 = __toESM(require("path"));
|
|
60680
|
+
|
|
60681
|
+
// ../protocol/src/configDir.ts
|
|
60205
60682
|
var fs22 = __toESM(require("fs"));
|
|
60206
60683
|
var path25 = __toESM(require("path"));
|
|
60684
|
+
function resolveConfigDir(root, names) {
|
|
60685
|
+
const current2 = path25.join(root, names.configDirName);
|
|
60686
|
+
if (!names.legacyConfigDirName || fs22.existsSync(current2)) return current2;
|
|
60687
|
+
const legacy = path25.join(root, names.legacyConfigDirName);
|
|
60688
|
+
return fs22.existsSync(legacy) ? legacy : current2;
|
|
60689
|
+
}
|
|
60690
|
+
|
|
60691
|
+
// src/schema/loader.ts
|
|
60207
60692
|
function buildStructureIndex(profile, entries) {
|
|
60208
60693
|
const keysByKindBlock = /* @__PURE__ */ new Map();
|
|
60209
60694
|
const ambientByKind = /* @__PURE__ */ new Map();
|
|
@@ -60240,13 +60725,13 @@ function loadSchema(modPath, log2) {
|
|
|
60240
60725
|
const prefixRefs = { ...profile.prefixRefs };
|
|
60241
60726
|
const roots = modPath === null ? [] : Array.isArray(modPath) ? modPath : [modPath];
|
|
60242
60727
|
for (const root of roots) {
|
|
60243
|
-
const overlayFile =
|
|
60728
|
+
const overlayFile = path26.join(resolveConfigDir(root, profile), "schema.json");
|
|
60244
60729
|
try {
|
|
60245
|
-
if (!
|
|
60246
|
-
const overlay = JSON.parse(
|
|
60730
|
+
if (!fs23.existsSync(overlayFile)) continue;
|
|
60731
|
+
const overlay = JSON.parse(fs23.readFileSync(overlayFile, "utf8"));
|
|
60247
60732
|
for (const e of overlay.entries ?? []) {
|
|
60248
60733
|
if (typeof e?.path !== "string" || typeof e?.kind !== "string") continue;
|
|
60249
|
-
if (
|
|
60734
|
+
if (path26.isAbsolute(e.path) || e.path.includes("\\") || e.path.split("/").some((s2) => s2 === ".." || s2 === "")) {
|
|
60250
60735
|
log2?.(`schema overlay entry ignored (unsafe path): ${e.path}`);
|
|
60251
60736
|
continue;
|
|
60252
60737
|
}
|
|
@@ -60457,16 +60942,16 @@ var ServerData = class {
|
|
|
60457
60942
|
|
|
60458
60943
|
// src/features/hover.ts
|
|
60459
60944
|
var import_node6 = __toESM(require_main3());
|
|
60460
|
-
var
|
|
60945
|
+
var path27 = __toESM(require("path"));
|
|
60461
60946
|
|
|
60462
60947
|
// src/features/definitionBody.ts
|
|
60463
|
-
var
|
|
60948
|
+
var fs24 = __toESM(require("fs"));
|
|
60464
60949
|
var CACHE_MAX = 32;
|
|
60465
60950
|
var cache3 = /* @__PURE__ */ new Map();
|
|
60466
60951
|
function entryFor(file) {
|
|
60467
60952
|
let stat;
|
|
60468
60953
|
try {
|
|
60469
|
-
stat =
|
|
60954
|
+
stat = fs24.statSync(file);
|
|
60470
60955
|
} catch {
|
|
60471
60956
|
return null;
|
|
60472
60957
|
}
|
|
@@ -60474,7 +60959,7 @@ function entryFor(file) {
|
|
|
60474
60959
|
if (hit && hit.mtimeMs === stat.mtimeMs) return hit;
|
|
60475
60960
|
let text;
|
|
60476
60961
|
try {
|
|
60477
|
-
text =
|
|
60962
|
+
text = fs24.readFileSync(file, "utf8");
|
|
60478
60963
|
} catch {
|
|
60479
60964
|
return null;
|
|
60480
60965
|
}
|
|
@@ -60780,7 +61265,7 @@ function definitionCard(data2, def, at, withRefs = true) {
|
|
|
60780
61265
|
return card;
|
|
60781
61266
|
}
|
|
60782
61267
|
function provenance2(def) {
|
|
60783
|
-
return fileLink(def.file, `${
|
|
61268
|
+
return fileLink(def.file, `${path27.basename(def.file)}:${def.line + 1}`, {
|
|
60784
61269
|
fragment: String(def.line + 1)
|
|
60785
61270
|
});
|
|
60786
61271
|
}
|
|
@@ -60803,14 +61288,14 @@ function savedScopeCard(data2, document, name, rootScopes, entry) {
|
|
|
60803
61288
|
const doc = [];
|
|
60804
61289
|
if (ambient) doc.push(`${ambient.doc}${entry ? ` *(${entry.kind.replace(/_/g, " ")})*` : ""}`);
|
|
60805
61290
|
const site = firstSaveSite(document, name);
|
|
60806
|
-
if (site !== null) doc.push(`Saved in this file: ${
|
|
61291
|
+
if (site !== null) doc.push(`Saved in this file: ${path27.basename(URIToPath(document.uri))}:${site + 1}`);
|
|
60807
61292
|
else if (ambient) doc.push(`Engine-provided (not saved in this file).`);
|
|
60808
61293
|
else if (!inferred) {
|
|
60809
61294
|
const sites = data2.index.lookup(name).filter((d) => d.kind === "saved_scope").slice(0, 3);
|
|
60810
61295
|
if (sites.length > 0) {
|
|
60811
61296
|
doc.push(
|
|
60812
61297
|
sites.map(
|
|
60813
|
-
(d) => `saved in ${fileLink(d.file, `${
|
|
61298
|
+
(d) => `saved in ${fileLink(d.file, `${path27.basename(d.file)}:${d.line + 1}`, { fragment: `L${d.line + 1}` })}`
|
|
60814
61299
|
).join(" \n")
|
|
60815
61300
|
);
|
|
60816
61301
|
} else {
|
|
@@ -60905,7 +61390,7 @@ function relationTriggerCard(data2, word) {
|
|
|
60905
61390
|
kind: m[1] === "has" ? "trigger" : "effect",
|
|
60906
61391
|
name: word,
|
|
60907
61392
|
headTail: `\xB7 generated from \`${m[2]}\``,
|
|
60908
|
-
doc: `${verb} the scripted relation \`${m[2]}\` (${
|
|
61393
|
+
doc: `${verb} the scripted relation \`${m[2]}\` (${path27.basename(def.file)}:${def.line + 1}) with the target character.`
|
|
60909
61394
|
};
|
|
60910
61395
|
}
|
|
60911
61396
|
function templatedModifierCard(data2, word) {
|
|
@@ -60975,7 +61460,7 @@ function definesCard(data2, namespace, name) {
|
|
|
60975
61460
|
function defineSourceLink(e) {
|
|
60976
61461
|
const norm2 = e.file.replace(/\\/g, "/");
|
|
60977
61462
|
const i = norm2.toLowerCase().lastIndexOf("/common/defines/");
|
|
60978
|
-
const rel = i >= 0 ? `${norm2.slice(i + 1)}:${e.line + 1}` : `${
|
|
61463
|
+
const rel = i >= 0 ? `${norm2.slice(i + 1)}:${e.line + 1}` : `${path27.basename(e.file)}:${e.line + 1}`;
|
|
60979
61464
|
return `${e.layer} \xB7 ${fileLink(e.file, rel, { fragment: String(e.line + 1) })}`;
|
|
60980
61465
|
}
|
|
60981
61466
|
function scopeWordCard(word) {
|
|
@@ -61036,14 +61521,14 @@ function scopeInference(data2, document, position, rootScopes, entry) {
|
|
|
61036
61521
|
);
|
|
61037
61522
|
}
|
|
61038
61523
|
function URIToPath(uri) {
|
|
61039
|
-
return uri.replace(/^file:\/\/\/?/, "").replace(/\//g,
|
|
61524
|
+
return uri.replace(/^file:\/\/\/?/, "").replace(/\//g, path27.sep);
|
|
61040
61525
|
}
|
|
61041
61526
|
|
|
61042
61527
|
// src/features/calendarDates.ts
|
|
61043
61528
|
var import_node7 = __toESM(require_main3());
|
|
61044
61529
|
|
|
61045
61530
|
// ../protocol/src/calendar.ts
|
|
61046
|
-
var
|
|
61531
|
+
var ENGINE_MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
61047
61532
|
var GREGORIAN_MONTHS = [
|
|
61048
61533
|
"January",
|
|
61049
61534
|
"February",
|
|
@@ -61057,8 +61542,8 @@ var GREGORIAN_MONTHS = [
|
|
|
61057
61542
|
"October",
|
|
61058
61543
|
"November",
|
|
61059
61544
|
"December"
|
|
61060
|
-
]
|
|
61061
|
-
function
|
|
61545
|
+
];
|
|
61546
|
+
function monthNames(cal) {
|
|
61062
61547
|
return cal.months ?? GREGORIAN_MONTHS;
|
|
61063
61548
|
}
|
|
61064
61549
|
function sanitizeCalendar(raw) {
|
|
@@ -61072,36 +61557,34 @@ function sanitizeCalendar(raw) {
|
|
|
61072
61557
|
if (typeof o.before === "string" && o.before.trim() !== "") cal.before = o.before.trim();
|
|
61073
61558
|
if (cal.before && cal.before.toLowerCase() === cal.after.toLowerCase()) return void 0;
|
|
61074
61559
|
if (Array.isArray(o.months) && o.months.length > 0) {
|
|
61560
|
+
if (o.months.length !== GREGORIAN_MONTHS.length) return void 0;
|
|
61075
61561
|
const months = [];
|
|
61076
61562
|
const seen = /* @__PURE__ */ new Set();
|
|
61077
61563
|
for (const m of o.months) {
|
|
61078
|
-
|
|
61079
|
-
const { name, days } = m;
|
|
61564
|
+
const name = typeof m === "string" ? m : m?.name ?? null;
|
|
61080
61565
|
if (typeof name !== "string" || name.trim() === "") return void 0;
|
|
61081
|
-
if (typeof days !== "number" || !Number.isInteger(days) || days < 1 || days > 999) return void 0;
|
|
61082
61566
|
const key = name.trim().toLowerCase();
|
|
61083
61567
|
if (seen.has(key)) return void 0;
|
|
61084
61568
|
seen.add(key);
|
|
61085
|
-
months.push(
|
|
61569
|
+
months.push(name.trim());
|
|
61086
61570
|
}
|
|
61087
61571
|
cal.months = months;
|
|
61088
61572
|
}
|
|
61089
61573
|
return cal;
|
|
61090
61574
|
}
|
|
61091
|
-
function isValidScriptDate(
|
|
61092
|
-
|
|
61093
|
-
return y >= 1 && m >= 1 && m <= months.length && d >= 1 && d <= months[m - 1].days;
|
|
61575
|
+
function isValidScriptDate(y, m, d) {
|
|
61576
|
+
return y >= 1 && m >= 1 && m <= ENGINE_MONTH_DAYS.length && d >= 1 && d <= ENGINE_MONTH_DAYS[m - 1];
|
|
61094
61577
|
}
|
|
61095
61578
|
function displayYear(cal, y) {
|
|
61096
61579
|
if (y >= cal.epoch) return `${y - cal.epoch + 1} ${cal.after}`;
|
|
61097
61580
|
return cal.before ? `${cal.epoch - y} ${cal.before}` : null;
|
|
61098
61581
|
}
|
|
61099
61582
|
function displayDate(cal, y, m, d) {
|
|
61100
|
-
if (!isValidScriptDate(
|
|
61583
|
+
if (!isValidScriptDate(y, m, d)) return null;
|
|
61101
61584
|
const year = displayYear(cal, y);
|
|
61102
61585
|
if (!year) return null;
|
|
61103
61586
|
if (m === 1 && d === 1) return year;
|
|
61104
|
-
return `${d} ${
|
|
61587
|
+
return `${d} ${monthNames(cal)[m - 1]} ${year}`;
|
|
61105
61588
|
}
|
|
61106
61589
|
|
|
61107
61590
|
// src/features/calendarDates.ts
|
|
@@ -61120,7 +61603,7 @@ function dateTokensOnLine(cal, lineText) {
|
|
|
61120
61603
|
const quotesBefore = (code.slice(0, match.index).match(/"/g) ?? []).length;
|
|
61121
61604
|
if (quotesBefore % 2 === 1) continue;
|
|
61122
61605
|
const [y, m, d] = [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
61123
|
-
if (!isValidScriptDate(
|
|
61606
|
+
if (!isValidScriptDate(y, m, d)) continue;
|
|
61124
61607
|
tokens.push({ start: match.index, end: match.index + match[0].length, y, m, d });
|
|
61125
61608
|
}
|
|
61126
61609
|
return tokens;
|
|
@@ -61142,7 +61625,7 @@ function calendarHints(cal, document, range) {
|
|
|
61142
61625
|
}
|
|
61143
61626
|
return hints;
|
|
61144
61627
|
}
|
|
61145
|
-
function provideDateHover(cal, document, position) {
|
|
61628
|
+
function provideDateHover(cal, document, position, source = "px.calendar") {
|
|
61146
61629
|
if (!cal || !isScriptLanguage(document.languageId)) return null;
|
|
61147
61630
|
const lineText = getLineText(document, position.line);
|
|
61148
61631
|
const token = dateTokensOnLine(cal, lineText).find(
|
|
@@ -61155,7 +61638,7 @@ function provideDateHover(cal, document, position) {
|
|
|
61155
61638
|
const eras = cal.before ? `${cal.before} / ${cal.after}` : cal.after;
|
|
61156
61639
|
const value = `\`${script}\` \u2192 **${display}**
|
|
61157
61640
|
|
|
61158
|
-
|
|
61641
|
+
*${source}: epoch ${cal.epoch} (${eras})${cal.months ? ", the mod's month names" : ""}*`;
|
|
61159
61642
|
return {
|
|
61160
61643
|
contents: { kind: import_node7.MarkupKind.Markdown, value },
|
|
61161
61644
|
range: {
|
|
@@ -61165,10 +61648,47 @@ function provideDateHover(cal, document, position) {
|
|
|
61165
61648
|
};
|
|
61166
61649
|
}
|
|
61167
61650
|
|
|
61651
|
+
// ../protocol/src/calendarFile.ts
|
|
61652
|
+
var fs25 = __toESM(require("fs"));
|
|
61653
|
+
var path28 = __toESM(require("path"));
|
|
61654
|
+
var CALENDAR_FILE = "calendar.json";
|
|
61655
|
+
function calendarFilePath(modRoot, names) {
|
|
61656
|
+
return path28.join(resolveConfigDir(modRoot, names), CALENDAR_FILE);
|
|
61657
|
+
}
|
|
61658
|
+
function readCalendarFile(modRoot, names) {
|
|
61659
|
+
const file = calendarFilePath(modRoot, names);
|
|
61660
|
+
let text;
|
|
61661
|
+
try {
|
|
61662
|
+
text = fs25.readFileSync(file, "utf8");
|
|
61663
|
+
} catch {
|
|
61664
|
+
return null;
|
|
61665
|
+
}
|
|
61666
|
+
let raw;
|
|
61667
|
+
try {
|
|
61668
|
+
raw = JSON.parse(text.replace(/^\uFEFF/, ""));
|
|
61669
|
+
} catch (err) {
|
|
61670
|
+
return { file, error: `not valid JSON (${err.message})` };
|
|
61671
|
+
}
|
|
61672
|
+
const calendar = sanitizeCalendar(raw);
|
|
61673
|
+
if (!calendar) {
|
|
61674
|
+
return {
|
|
61675
|
+
file,
|
|
61676
|
+
error: 'not a usable calendar: needs a whole-number "epoch" (1 or more), a non-empty "after" era label, a "before" label different from "after" when present, and, when "months" is given, exactly twelve distinct names'
|
|
61677
|
+
};
|
|
61678
|
+
}
|
|
61679
|
+
return { file, calendar };
|
|
61680
|
+
}
|
|
61681
|
+
function isCalendarFile(fsPath, names) {
|
|
61682
|
+
const parts = fsPath.split(/[\\/]/);
|
|
61683
|
+
if (parts.length < 2 || parts[parts.length - 1].toLowerCase() !== CALENDAR_FILE) return false;
|
|
61684
|
+
const dir = parts[parts.length - 2].toLowerCase();
|
|
61685
|
+
return dir === names.configDirName.toLowerCase() || dir === names.legacyConfigDirName?.toLowerCase();
|
|
61686
|
+
}
|
|
61687
|
+
|
|
61168
61688
|
// src/features/textureHover.ts
|
|
61169
61689
|
var import_node8 = __toESM(require_main3());
|
|
61170
|
-
var
|
|
61171
|
-
var
|
|
61690
|
+
var fs26 = __toESM(require("fs"));
|
|
61691
|
+
var path29 = __toESM(require("path"));
|
|
61172
61692
|
|
|
61173
61693
|
// src/dds/png.ts
|
|
61174
61694
|
var import_node_zlib = require("node:zlib");
|
|
@@ -61291,7 +61811,7 @@ var cache4 = /* @__PURE__ */ new Map();
|
|
|
61291
61811
|
function cachedPreview(fsPath) {
|
|
61292
61812
|
let stat;
|
|
61293
61813
|
try {
|
|
61294
|
-
stat =
|
|
61814
|
+
stat = fs26.statSync(fsPath);
|
|
61295
61815
|
} catch {
|
|
61296
61816
|
return null;
|
|
61297
61817
|
}
|
|
@@ -61299,7 +61819,7 @@ function cachedPreview(fsPath) {
|
|
|
61299
61819
|
if (cache4.has(key)) return cache4.get(key) ?? null;
|
|
61300
61820
|
let entry = null;
|
|
61301
61821
|
try {
|
|
61302
|
-
const buf =
|
|
61822
|
+
const buf = fs26.readFileSync(fsPath);
|
|
61303
61823
|
const info = ddsFormatInfo(buf);
|
|
61304
61824
|
if (info) {
|
|
61305
61825
|
let uri;
|
|
@@ -61344,16 +61864,16 @@ function provideTextureHover(settings2, document, position, entryKind) {
|
|
|
61344
61864
|
let resolved = null;
|
|
61345
61865
|
for (const { root, label } of candidates) {
|
|
61346
61866
|
if (!root) continue;
|
|
61347
|
-
const full =
|
|
61348
|
-
if (
|
|
61867
|
+
const full = path29.join(root, ...rel.split("/"));
|
|
61868
|
+
if (fs26.existsSync(full)) {
|
|
61349
61869
|
resolved = { fsPath: full, label };
|
|
61350
61870
|
break;
|
|
61351
61871
|
}
|
|
61352
61872
|
}
|
|
61353
61873
|
if (!resolved) {
|
|
61354
|
-
const docDir =
|
|
61355
|
-
const full =
|
|
61356
|
-
if (
|
|
61874
|
+
const docDir = path29.dirname(URI2.parse(document.uri).fsPath);
|
|
61875
|
+
const full = path29.join(docDir, ...rel.split("/"));
|
|
61876
|
+
if (fs26.existsSync(full)) resolved = { fsPath: full, label: "relative" };
|
|
61357
61877
|
}
|
|
61358
61878
|
if (!resolved && !rel.includes("/")) {
|
|
61359
61879
|
const keyMatch = /([A-Za-z_][A-Za-z0-9_]*)\s*=\s*"?$/.exec(lineText.slice(0, hit.start));
|
|
@@ -61361,8 +61881,8 @@ function provideTextureHover(settings2, document, position, entryKind) {
|
|
|
61361
61881
|
if (dirs) {
|
|
61362
61882
|
outer: for (const { root, label } of assetRoots(settings2)) {
|
|
61363
61883
|
for (const dir of dirs) {
|
|
61364
|
-
const full =
|
|
61365
|
-
if (
|
|
61884
|
+
const full = path29.join(root, ...dir.split("/"), rel);
|
|
61885
|
+
if (fs26.existsSync(full)) {
|
|
61366
61886
|
resolved = { fsPath: full, label };
|
|
61367
61887
|
break outer;
|
|
61368
61888
|
}
|
|
@@ -61380,7 +61900,7 @@ function provideTextureHover(settings2, document, position, entryKind) {
|
|
|
61380
61900
|
const card = {
|
|
61381
61901
|
kind: "texture",
|
|
61382
61902
|
badgeLabel: "texture",
|
|
61383
|
-
name:
|
|
61903
|
+
name: path29.basename(rel),
|
|
61384
61904
|
headTail: `\xB7 ${resolved.label}`,
|
|
61385
61905
|
provenance: open
|
|
61386
61906
|
};
|
|
@@ -61490,16 +62010,16 @@ function provideSemanticTokens(data2, document, refFields, entry, structures) {
|
|
|
61490
62010
|
const { result, lineIndex } = getParse(document);
|
|
61491
62011
|
const builder = new import_node9.SemanticTokensBuilder();
|
|
61492
62012
|
const byBlock = entry?.kind && structures ? structures.keysByKindBlock.get(entry.kind) : void 0;
|
|
61493
|
-
const pushScalar = (
|
|
61494
|
-
if (
|
|
61495
|
-
let word =
|
|
62013
|
+
const pushScalar = (scalar3, expectedKinds) => {
|
|
62014
|
+
if (scalar3.quoted) return;
|
|
62015
|
+
let word = scalar3.text;
|
|
61496
62016
|
if (!IDENTIFIER_START.test(word)) return;
|
|
61497
62017
|
const colon = word.indexOf(":");
|
|
61498
62018
|
if (colon >= 0) word = word.slice(0, colon);
|
|
61499
62019
|
if (word === "") return;
|
|
61500
62020
|
const classified = classify3(data2, word, colon >= 0 ? void 0 : expectedKinds);
|
|
61501
62021
|
if (!classified) return;
|
|
61502
|
-
const pos = lineIndex.positionAt(
|
|
62022
|
+
const pos = lineIndex.positionAt(scalar3.range.start);
|
|
61503
62023
|
builder.push(pos.line, pos.character, word.length, classified.type, classified.modifiers);
|
|
61504
62024
|
};
|
|
61505
62025
|
const fieldKinds = (key, form) => {
|
|
@@ -61519,9 +62039,9 @@ function provideSemanticTokens(data2, document, refFields, entry, structures) {
|
|
|
61519
62039
|
if (!spec?.values?.startsWith("enum:")) return false;
|
|
61520
62040
|
return spec.values.slice(5).split("|").includes(value.text);
|
|
61521
62041
|
};
|
|
61522
|
-
const pushAs = (
|
|
61523
|
-
const pos = lineIndex.positionAt(
|
|
61524
|
-
builder.push(pos.line, pos.character,
|
|
62042
|
+
const pushAs = (scalar3, type, modifiers) => {
|
|
62043
|
+
const pos = lineIndex.positionAt(scalar3.range.start);
|
|
62044
|
+
builder.push(pos.line, pos.character, scalar3.text.length, TYPE_INDEX[type], modifiers);
|
|
61525
62045
|
};
|
|
61526
62046
|
walkStatements(result.root, (stmt, ancestors) => {
|
|
61527
62047
|
if (stmt.kind === "assignment") {
|
|
@@ -61575,7 +62095,7 @@ function classify3(data2, word, expectedKinds) {
|
|
|
61575
62095
|
|
|
61576
62096
|
// src/features/inlayHints.ts
|
|
61577
62097
|
var import_node10 = __toESM(require_main3());
|
|
61578
|
-
var
|
|
62098
|
+
var path30 = __toESM(require("path"));
|
|
61579
62099
|
|
|
61580
62100
|
// ../protocol/src/locRefs.ts
|
|
61581
62101
|
var PROP_VALUE = /([A-Za-z_][A-Za-z0-9_.-]*)\s*=\s*("?)([A-Za-z_][A-Za-z0-9_.-]*)\2/g;
|
|
@@ -61623,11 +62143,11 @@ var HINT_MAX_LEN = 60;
|
|
|
61623
62143
|
function truncate(text, max) {
|
|
61624
62144
|
return text.length > max ? text.slice(0, max - 1) + "\u2026" : text;
|
|
61625
62145
|
}
|
|
61626
|
-
function provideInlayHints(data2, settings2, document, range, rootScopes, entry) {
|
|
62146
|
+
function provideInlayHints(data2, settings2, document, range, rootScopes, entry, calendar = settings2.calendar) {
|
|
61627
62147
|
if (document.languageId === "paradox-loc") return translationOverlayHints(data2, settings2, document, range);
|
|
61628
62148
|
const hints = locPreviewHints(data2, document, range);
|
|
61629
62149
|
if (settings2.scopeInlayHints) hints.push(...scopeHints(data2, document, range, rootScopes, entry));
|
|
61630
|
-
if (
|
|
62150
|
+
if (calendar) hints.push(...calendarHints(calendar, document, range));
|
|
61631
62151
|
return hints;
|
|
61632
62152
|
}
|
|
61633
62153
|
function scopeHints(data2, document, range, rootScopes, entry) {
|
|
@@ -61676,7 +62196,7 @@ function locPreviewHints(data2, document, range) {
|
|
|
61676
62196
|
kind: import_node10.MarkupKind.Markdown,
|
|
61677
62197
|
value: `${def.value ?? ""}
|
|
61678
62198
|
|
|
61679
|
-
*${
|
|
62199
|
+
*${path30.basename(def.file)}:${def.line + 1} (${def.source})*`
|
|
61680
62200
|
}
|
|
61681
62201
|
});
|
|
61682
62202
|
} else if (ref.strictness === "strict") {
|
|
@@ -61711,7 +62231,7 @@ function translationOverlayHints(data2, settings2, document, range) {
|
|
|
61711
62231
|
kind: import_node10.MarkupKind.Markdown,
|
|
61712
62232
|
value: `**${settings2.locLanguage}**: ${def.value}
|
|
61713
62233
|
|
|
61714
|
-
*${
|
|
62234
|
+
*${path30.basename(def.file)}:${def.line + 1} (${def.source})*`
|
|
61715
62235
|
}
|
|
61716
62236
|
});
|
|
61717
62237
|
}
|
|
@@ -61751,8 +62271,8 @@ function list(scopes) {
|
|
|
61751
62271
|
|
|
61752
62272
|
// src/features/codeActions.ts
|
|
61753
62273
|
var import_node11 = __toESM(require_main3());
|
|
61754
|
-
var
|
|
61755
|
-
var
|
|
62274
|
+
var fs27 = __toESM(require("fs"));
|
|
62275
|
+
var path31 = __toESM(require("path"));
|
|
61756
62276
|
function locKeyRefAt(lineText, character) {
|
|
61757
62277
|
const refs = findLocKeyRefs(lineText);
|
|
61758
62278
|
return refs.find((r) => character >= r.start - 1 && character <= r.end + 1) ?? refs[0] ?? null;
|
|
@@ -61762,12 +62282,12 @@ function locCreateEdit(key, docFsPath, ctx) {
|
|
|
61762
62282
|
if (!modRoot) return null;
|
|
61763
62283
|
const lang = ctx.locLanguage;
|
|
61764
62284
|
const locRoot = ctx.locRoots[0] ?? "localization";
|
|
61765
|
-
const target =
|
|
62285
|
+
const target = path31.join(modRoot, locRoot, lang, `zzz_px_lsp_edits_l_${lang}.yml`);
|
|
61766
62286
|
const uri = URI2.file(target).toString();
|
|
61767
62287
|
const entryLine = ` ${key}: ""`;
|
|
61768
62288
|
let content = null;
|
|
61769
62289
|
try {
|
|
61770
|
-
content =
|
|
62290
|
+
content = fs27.readFileSync(target, "utf8");
|
|
61771
62291
|
} catch {
|
|
61772
62292
|
content = null;
|
|
61773
62293
|
}
|
|
@@ -62527,9 +63047,9 @@ function computeLocDiagnostics(loc, lines, ctx) {
|
|
|
62527
63047
|
}
|
|
62528
63048
|
|
|
62529
63049
|
// src/features/references.ts
|
|
62530
|
-
var
|
|
63050
|
+
var path32 = __toESM(require("path"));
|
|
62531
63051
|
function siteKey(file, line) {
|
|
62532
|
-
const n =
|
|
63052
|
+
const n = path32.normalize(file);
|
|
62533
63053
|
return `${process.platform === "win32" ? n.toLowerCase() : n}|${line}`;
|
|
62534
63054
|
}
|
|
62535
63055
|
async function provideReferences(data2, document, position, includeDeclaration, lazyRefs2) {
|
|
@@ -62568,7 +63088,7 @@ function stripPrefix(word) {
|
|
|
62568
63088
|
|
|
62569
63089
|
// src/features/rename.ts
|
|
62570
63090
|
var import_node16 = __toESM(require_main3());
|
|
62571
|
-
var
|
|
63091
|
+
var fs28 = __toESM(require("fs"));
|
|
62572
63092
|
|
|
62573
63093
|
// ../protocol/src/regex.ts
|
|
62574
63094
|
function escapeRegExp(literal) {
|
|
@@ -62650,7 +63170,7 @@ function readLine(def, readOpenDocument) {
|
|
|
62650
63170
|
const open = readOpenDocument(uri);
|
|
62651
63171
|
if (open) return getLineText(open, def.line);
|
|
62652
63172
|
try {
|
|
62653
|
-
const lines =
|
|
63173
|
+
const lines = fs28.readFileSync(def.file, "utf8").replace(/^/, "").split(/\r?\n/);
|
|
62654
63174
|
return lines[def.line] ?? null;
|
|
62655
63175
|
} catch {
|
|
62656
63176
|
return null;
|
|
@@ -62699,6 +63219,52 @@ function provideWorkspaceSymbols(data2, query) {
|
|
|
62699
63219
|
}));
|
|
62700
63220
|
}
|
|
62701
63221
|
|
|
63222
|
+
// src/features/snippetList.ts
|
|
63223
|
+
var MAX_TOKENS = 60;
|
|
63224
|
+
function buildSnippetList(parse, offset, kind, skeletons, tokens, counts) {
|
|
63225
|
+
const out = kind ? skeletonsFor(parse, kind, skeletons).map((offer) => ({
|
|
63226
|
+
id: offer.id,
|
|
63227
|
+
label: offer.label,
|
|
63228
|
+
detail: offer.detail,
|
|
63229
|
+
form: offer.form,
|
|
63230
|
+
snippet: offer.text.snippet,
|
|
63231
|
+
plain: offer.text.plain
|
|
63232
|
+
})) : [];
|
|
63233
|
+
const { context } = detectContextFromParse(parse, offset);
|
|
63234
|
+
const seen = /* @__PURE__ */ new Set();
|
|
63235
|
+
const candidates = [];
|
|
63236
|
+
for (const token of tokens) {
|
|
63237
|
+
if (context === "trigger" && (token.kind === "effect" || token.kind === "modifier")) continue;
|
|
63238
|
+
if (context === "effect" && (token.kind === "trigger" || token.kind === "modifier")) continue;
|
|
63239
|
+
if (seen.has(token.name)) continue;
|
|
63240
|
+
if (!blockTemplateFor(token)) continue;
|
|
63241
|
+
seen.add(token.name);
|
|
63242
|
+
candidates.push({ token, count: counts[token.name] ?? 0 });
|
|
63243
|
+
}
|
|
63244
|
+
candidates.sort((a, b) => b.count - a.count || (a.token.name < b.token.name ? -1 : 1));
|
|
63245
|
+
for (const { token } of candidates.slice(0, MAX_TOKENS)) {
|
|
63246
|
+
const template = blockTemplateFor(token);
|
|
63247
|
+
out.push({
|
|
63248
|
+
id: token.name,
|
|
63249
|
+
label: token.name,
|
|
63250
|
+
detail: `${token.kind} block, from the game's own usage example`,
|
|
63251
|
+
form: "token",
|
|
63252
|
+
snippet: template.snippet,
|
|
63253
|
+
plain: template.plain
|
|
63254
|
+
});
|
|
63255
|
+
if (template.full)
|
|
63256
|
+
out.push({
|
|
63257
|
+
id: `${token.name}.full`,
|
|
63258
|
+
label: `${token.name} (all fields)`,
|
|
63259
|
+
detail: `${token.kind} block with its optional fields, from the game's own usage example`,
|
|
63260
|
+
form: "token",
|
|
63261
|
+
snippet: template.full.snippet,
|
|
63262
|
+
plain: template.full.plain
|
|
63263
|
+
});
|
|
63264
|
+
}
|
|
63265
|
+
return out;
|
|
63266
|
+
}
|
|
63267
|
+
|
|
62702
63268
|
// ../protocol/src/suppression.ts
|
|
62703
63269
|
function globMatch(pattern, filePath) {
|
|
62704
63270
|
const p = pattern.replace(/\\/g, "/").toLowerCase();
|
|
@@ -62815,8 +63381,8 @@ function computeModOverview(data2, inFocus = () => true) {
|
|
|
62815
63381
|
}
|
|
62816
63382
|
|
|
62817
63383
|
// src/overview/locCoverage.ts
|
|
62818
|
-
var
|
|
62819
|
-
var
|
|
63384
|
+
var path33 = __toESM(require("path"));
|
|
63385
|
+
var fs29 = __toESM(require("fs"));
|
|
62820
63386
|
var ISSUE_CAP = 500;
|
|
62821
63387
|
function locRoots(schemaEntries) {
|
|
62822
63388
|
const roots = schemaEntries.filter((e) => e.kind === "loc_key").map((e) => e.path);
|
|
@@ -62825,13 +63391,13 @@ function locRoots(schemaEntries) {
|
|
|
62825
63391
|
function modLocByLanguage(modPath, schemaEntries) {
|
|
62826
63392
|
const byLang = /* @__PURE__ */ new Map();
|
|
62827
63393
|
for (const root of locRoots(schemaEntries)) {
|
|
62828
|
-
const locDir =
|
|
63394
|
+
const locDir = path33.join(modPath, root);
|
|
62829
63395
|
for (const file of listFiles(locDir, ".yml")) {
|
|
62830
63396
|
const lang = detectLocFileLanguage(file);
|
|
62831
63397
|
if (!lang) continue;
|
|
62832
63398
|
let content;
|
|
62833
63399
|
try {
|
|
62834
|
-
content =
|
|
63400
|
+
content = fs29.readFileSync(file, "utf8");
|
|
62835
63401
|
} catch {
|
|
62836
63402
|
continue;
|
|
62837
63403
|
}
|
|
@@ -62962,7 +63528,7 @@ function computeOverrides(data2, gamePath, inFocus = () => true) {
|
|
|
62962
63528
|
}
|
|
62963
63529
|
|
|
62964
63530
|
// src/overview/eventGraph.ts
|
|
62965
|
-
var
|
|
63531
|
+
var fs30 = __toESM(require("fs"));
|
|
62966
63532
|
var DEFAULT_MAX_NODES = 400;
|
|
62967
63533
|
var GRAPH_KINDS = /* @__PURE__ */ new Set(["event", "on_action", "decision"]);
|
|
62968
63534
|
var MAX_SUGGESTIONS = 2e3;
|
|
@@ -62998,7 +63564,7 @@ function labelEdges(data2, edges, sites) {
|
|
|
62998
63564
|
const key = file.toLowerCase();
|
|
62999
63565
|
if (!parses.has(key)) {
|
|
63000
63566
|
try {
|
|
63001
|
-
const text = decode(
|
|
63567
|
+
const text = decode(fs30.readFileSync(file)).text;
|
|
63002
63568
|
parses.set(key, { result: parseScript(text), li: new LineIndex(text) });
|
|
63003
63569
|
} catch {
|
|
63004
63570
|
parses.set(key, null);
|
|
@@ -63215,6 +63781,19 @@ function computeEventGraph(data2, params, inFocus = () => true) {
|
|
|
63215
63781
|
sites.set(out, e);
|
|
63216
63782
|
}
|
|
63217
63783
|
labelEdges(data2, graphEdges, sites);
|
|
63784
|
+
let pruned = 0;
|
|
63785
|
+
if (params.connectedOnly ?? true) {
|
|
63786
|
+
const linked = /* @__PURE__ */ new Set();
|
|
63787
|
+
for (const e of graphEdges) {
|
|
63788
|
+
linked.add(e.from);
|
|
63789
|
+
linked.add(e.to);
|
|
63790
|
+
}
|
|
63791
|
+
for (const id of [...selected]) {
|
|
63792
|
+
if (linked.has(id) || id === params.root) continue;
|
|
63793
|
+
selected.delete(id);
|
|
63794
|
+
pruned++;
|
|
63795
|
+
}
|
|
63796
|
+
}
|
|
63218
63797
|
const firesCount = /* @__PURE__ */ new Map();
|
|
63219
63798
|
for (const e of graphEdges) firesCount.set(e.from, (firesCount.get(e.from) ?? 0) + 1);
|
|
63220
63799
|
const nodes = [];
|
|
@@ -63254,7 +63833,7 @@ function computeEventGraph(data2, params, inFocus = () => true) {
|
|
|
63254
63833
|
nodes.sort((a, b) => a.id.localeCompare(b.id));
|
|
63255
63834
|
const graph = { nodes, edges: graphEdges, truncated, suggestions: suggestionsOf(vocabulary) };
|
|
63256
63835
|
if (nodes.length === 0) {
|
|
63257
|
-
const reason = emptyReason(data2, params, inFocus);
|
|
63836
|
+
const reason = pruned > 0 ? `${pruned} definition(s) are here but none is connected to another. Turn "Connected only" off to show them.` : emptyReason(data2, params, inFocus);
|
|
63258
63837
|
if (reason) graph.emptyReason = reason;
|
|
63259
63838
|
}
|
|
63260
63839
|
return graph;
|
|
@@ -63294,7 +63873,7 @@ function fileFacts() {
|
|
|
63294
63873
|
facts = /* @__PURE__ */ new Map();
|
|
63295
63874
|
byFile.set(key, facts);
|
|
63296
63875
|
try {
|
|
63297
|
-
const text = decode(
|
|
63876
|
+
const text = decode(fs30.readFileSync(file)).text;
|
|
63298
63877
|
const root = parseScript(text).root;
|
|
63299
63878
|
const li = new LineIndex(text);
|
|
63300
63879
|
for (const stmt of root.statements) {
|
|
@@ -63379,6 +63958,324 @@ function suggestionsOf(vocabulary) {
|
|
|
63379
63958
|
return { ids: ids.slice(0, MAX_SUGGESTIONS), namespaces: [...namespaces].sort() };
|
|
63380
63959
|
}
|
|
63381
63960
|
|
|
63961
|
+
// src/overview/dynastyTree.ts
|
|
63962
|
+
var fs31 = __toESM(require("fs"));
|
|
63963
|
+
var DYNASTY_KIND = "dynasty";
|
|
63964
|
+
var HOUSE_KIND = "dynasty_house";
|
|
63965
|
+
var CHARACTER_KIND = "character";
|
|
63966
|
+
var SOURCE_RANK2 = { mod: 2, parent: 1, vanilla: 0 };
|
|
63967
|
+
var DATE_RE = /^-?\d+\.\d+\.\d+$/;
|
|
63968
|
+
var SKILL_KEYS = new Set(DYNASTY_SKILLS);
|
|
63969
|
+
var NONE = [];
|
|
63970
|
+
function interner() {
|
|
63971
|
+
const pool = /* @__PURE__ */ new Map();
|
|
63972
|
+
return (value) => {
|
|
63973
|
+
const known = pool.get(value);
|
|
63974
|
+
if (known !== void 0) return known;
|
|
63975
|
+
pool.set(value, value);
|
|
63976
|
+
return value;
|
|
63977
|
+
};
|
|
63978
|
+
}
|
|
63979
|
+
var cached = null;
|
|
63980
|
+
var IDLE_RELEASE_MS = 10 * 60 * 1e3;
|
|
63981
|
+
var idleTimer = null;
|
|
63982
|
+
function clearDynastyModel() {
|
|
63983
|
+
cached = null;
|
|
63984
|
+
if (idleTimer) {
|
|
63985
|
+
clearTimeout(idleTimer);
|
|
63986
|
+
idleTimer = null;
|
|
63987
|
+
}
|
|
63988
|
+
}
|
|
63989
|
+
function keepAlive() {
|
|
63990
|
+
if (idleTimer) clearTimeout(idleTimer);
|
|
63991
|
+
idleTimer = setTimeout(clearDynastyModel, IDLE_RELEASE_MS);
|
|
63992
|
+
idleTimer.unref?.();
|
|
63993
|
+
}
|
|
63994
|
+
function blockOf5(stmt) {
|
|
63995
|
+
if (stmt.kind !== "assignment") return null;
|
|
63996
|
+
const v = stmt.value;
|
|
63997
|
+
if (v?.kind === "block") return v;
|
|
63998
|
+
if (v?.kind === "tagged-block") return v.block;
|
|
63999
|
+
return null;
|
|
64000
|
+
}
|
|
64001
|
+
function scalarOf(stmt) {
|
|
64002
|
+
if (stmt.kind !== "assignment") return null;
|
|
64003
|
+
return stmt.value?.kind === "scalar" ? stmt.value.text : null;
|
|
64004
|
+
}
|
|
64005
|
+
function readCharacterBlock(id, block2, where, intern2 = (v) => v) {
|
|
64006
|
+
const traits = [];
|
|
64007
|
+
const spouses = [];
|
|
64008
|
+
const out = { id, name: id, female: false, traits, spouses, ...where };
|
|
64009
|
+
for (const stmt of block2.statements) {
|
|
64010
|
+
if (stmt.kind !== "assignment") continue;
|
|
64011
|
+
const key = stmt.key.text;
|
|
64012
|
+
if (DATE_RE.test(key)) {
|
|
64013
|
+
const dated = blockOf5(stmt);
|
|
64014
|
+
if (!dated) continue;
|
|
64015
|
+
for (const inner of dated.statements) {
|
|
64016
|
+
if (inner.kind !== "assignment") continue;
|
|
64017
|
+
const ikey = inner.key.text;
|
|
64018
|
+
if (ikey === "birth") out.birth ??= key;
|
|
64019
|
+
else if (ikey === "death") out.death ??= key;
|
|
64020
|
+
else if (ikey === "add_spouse") {
|
|
64021
|
+
const spouse = scalarOf(inner);
|
|
64022
|
+
if (spouse) spouses.push(intern2(spouse));
|
|
64023
|
+
}
|
|
64024
|
+
}
|
|
64025
|
+
continue;
|
|
64026
|
+
}
|
|
64027
|
+
const value = scalarOf(stmt);
|
|
64028
|
+
if (value === null) continue;
|
|
64029
|
+
if (SKILL_KEYS.has(key)) {
|
|
64030
|
+
const number = Number(value);
|
|
64031
|
+
if (Number.isFinite(number)) (out.skills ??= {})[key] = number;
|
|
64032
|
+
continue;
|
|
64033
|
+
}
|
|
64034
|
+
switch (key) {
|
|
64035
|
+
case "name":
|
|
64036
|
+
out.name = value;
|
|
64037
|
+
break;
|
|
64038
|
+
case "female":
|
|
64039
|
+
out.female = value === "yes";
|
|
64040
|
+
break;
|
|
64041
|
+
case "dynasty":
|
|
64042
|
+
out.dynasty = intern2(value);
|
|
64043
|
+
break;
|
|
64044
|
+
case "dynasty_house":
|
|
64045
|
+
out.house = intern2(value);
|
|
64046
|
+
break;
|
|
64047
|
+
case "father":
|
|
64048
|
+
out.father = value;
|
|
64049
|
+
break;
|
|
64050
|
+
case "mother":
|
|
64051
|
+
out.mother = value;
|
|
64052
|
+
break;
|
|
64053
|
+
case "culture":
|
|
64054
|
+
out.culture = intern2(value);
|
|
64055
|
+
break;
|
|
64056
|
+
case "religion":
|
|
64057
|
+
out.religion = intern2(value);
|
|
64058
|
+
break;
|
|
64059
|
+
case "dna":
|
|
64060
|
+
out.dna = value;
|
|
64061
|
+
break;
|
|
64062
|
+
case "trait":
|
|
64063
|
+
traits.push(intern2(value));
|
|
64064
|
+
break;
|
|
64065
|
+
case "add_spouse":
|
|
64066
|
+
spouses.push(intern2(value));
|
|
64067
|
+
break;
|
|
64068
|
+
}
|
|
64069
|
+
}
|
|
64070
|
+
if (traits.length === 0) out.traits = NONE;
|
|
64071
|
+
if (spouses.length === 0) out.spouses = NONE;
|
|
64072
|
+
return out;
|
|
64073
|
+
}
|
|
64074
|
+
function readDefinitionBlock(id, block2, where) {
|
|
64075
|
+
const out = { id, nameKey: "", dynasty: "", ...where };
|
|
64076
|
+
for (const stmt of block2.statements) {
|
|
64077
|
+
const value = scalarOf(stmt);
|
|
64078
|
+
if (value === null || stmt.kind !== "assignment") continue;
|
|
64079
|
+
if (stmt.key.text === "name") out.nameKey = value;
|
|
64080
|
+
else if (stmt.key.text === "culture") out.culture = value;
|
|
64081
|
+
else if (stmt.key.text === "dynasty") out.dynasty = value;
|
|
64082
|
+
}
|
|
64083
|
+
return out;
|
|
64084
|
+
}
|
|
64085
|
+
function eachTopLevelBlock(file, onBlock) {
|
|
64086
|
+
let text;
|
|
64087
|
+
try {
|
|
64088
|
+
text = decode(fs31.readFileSync(file)).text;
|
|
64089
|
+
} catch {
|
|
64090
|
+
return;
|
|
64091
|
+
}
|
|
64092
|
+
const { root } = parseScript(text);
|
|
64093
|
+
const li = new LineIndex(text);
|
|
64094
|
+
for (const stmt of root.statements) {
|
|
64095
|
+
if (stmt.kind !== "assignment") continue;
|
|
64096
|
+
const block2 = blockOf5(stmt);
|
|
64097
|
+
if (!block2) continue;
|
|
64098
|
+
onBlock(stmt.key.text, block2, li.positionAt(stmt.key.range.start).line);
|
|
64099
|
+
}
|
|
64100
|
+
}
|
|
64101
|
+
function scanIndex(data2) {
|
|
64102
|
+
const files = /* @__PURE__ */ new Map([
|
|
64103
|
+
[DYNASTY_KIND, []],
|
|
64104
|
+
[HOUSE_KIND, []],
|
|
64105
|
+
[CHARACTER_KIND, []]
|
|
64106
|
+
]);
|
|
64107
|
+
const seen = /* @__PURE__ */ new Set();
|
|
64108
|
+
let maxCharacterId = 0;
|
|
64109
|
+
let maxDynastyId = 0;
|
|
64110
|
+
const bump2 = (def) => {
|
|
64111
|
+
const n = Number(def.name);
|
|
64112
|
+
if (!Number.isInteger(n)) return;
|
|
64113
|
+
if (def.kind === CHARACTER_KIND) maxCharacterId = Math.max(maxCharacterId, n);
|
|
64114
|
+
else maxDynastyId = Math.max(maxDynastyId, n);
|
|
64115
|
+
};
|
|
64116
|
+
for (const def of data2.index.allDefinitions()) {
|
|
64117
|
+
const bucket = files.get(def.kind);
|
|
64118
|
+
if (!bucket) continue;
|
|
64119
|
+
bump2(def);
|
|
64120
|
+
const key = `${def.kind}\0${def.file}`;
|
|
64121
|
+
if (seen.has(key)) continue;
|
|
64122
|
+
seen.add(key);
|
|
64123
|
+
bucket.push({ file: def.file, source: def.source });
|
|
64124
|
+
}
|
|
64125
|
+
return { files, maxCharacterId, maxDynastyId };
|
|
64126
|
+
}
|
|
64127
|
+
function keep(map, id, rec) {
|
|
64128
|
+
const prev = map.get(id);
|
|
64129
|
+
if (prev && SOURCE_RANK2[prev.source] > SOURCE_RANK2[rec.source]) return;
|
|
64130
|
+
map.set(id, rec);
|
|
64131
|
+
}
|
|
64132
|
+
function buildModel(data2) {
|
|
64133
|
+
const { files, maxCharacterId, maxDynastyId } = scanIndex(data2);
|
|
64134
|
+
const dynasties = /* @__PURE__ */ new Map();
|
|
64135
|
+
const houses = /* @__PURE__ */ new Map();
|
|
64136
|
+
const characters = /* @__PURE__ */ new Map();
|
|
64137
|
+
const ordered = (kind) => [...files.get(kind) ?? []].sort((a, b) => SOURCE_RANK2[a.source] - SOURCE_RANK2[b.source]);
|
|
64138
|
+
for (const ref of ordered(DYNASTY_KIND)) {
|
|
64139
|
+
eachTopLevelBlock(ref.file, (id, block2, line) => {
|
|
64140
|
+
keep(dynasties, id, readDefinitionBlock(id, block2, { source: ref.source, file: ref.file, line }));
|
|
64141
|
+
});
|
|
64142
|
+
}
|
|
64143
|
+
for (const ref of ordered(HOUSE_KIND)) {
|
|
64144
|
+
eachTopLevelBlock(ref.file, (id, block2, line) => {
|
|
64145
|
+
keep(houses, id, readDefinitionBlock(id, block2, { source: ref.source, file: ref.file, line }));
|
|
64146
|
+
});
|
|
64147
|
+
}
|
|
64148
|
+
const intern2 = interner();
|
|
64149
|
+
for (const ref of ordered(CHARACTER_KIND)) {
|
|
64150
|
+
eachTopLevelBlock(ref.file, (id, block2, line) => {
|
|
64151
|
+
keep(
|
|
64152
|
+
characters,
|
|
64153
|
+
id,
|
|
64154
|
+
readCharacterBlock(id, block2, { source: ref.source, file: ref.file, line }, intern2)
|
|
64155
|
+
);
|
|
64156
|
+
});
|
|
64157
|
+
}
|
|
64158
|
+
const members = /* @__PURE__ */ new Map();
|
|
64159
|
+
for (const char of characters.values()) {
|
|
64160
|
+
const dynasty = char.dynasty ?? (char.house ? houses.get(char.house)?.dynasty : void 0);
|
|
64161
|
+
if (!dynasty) continue;
|
|
64162
|
+
const list2 = members.get(dynasty);
|
|
64163
|
+
if (list2) list2.push(char.id);
|
|
64164
|
+
else members.set(dynasty, [char.id]);
|
|
64165
|
+
}
|
|
64166
|
+
return {
|
|
64167
|
+
revision: data2.index.revision,
|
|
64168
|
+
dynasties,
|
|
64169
|
+
houses,
|
|
64170
|
+
characters,
|
|
64171
|
+
members,
|
|
64172
|
+
nextCharacterId: String(maxCharacterId + 1),
|
|
64173
|
+
nextDynastyId: String(maxDynastyId + 1)
|
|
64174
|
+
};
|
|
64175
|
+
}
|
|
64176
|
+
function modelFor(data2) {
|
|
64177
|
+
keepAlive();
|
|
64178
|
+
if (cached && cached.revision === data2.index.revision) return cached;
|
|
64179
|
+
cached = buildModel(data2);
|
|
64180
|
+
return cached;
|
|
64181
|
+
}
|
|
64182
|
+
function locText(data2, key) {
|
|
64183
|
+
if (key === "") return "";
|
|
64184
|
+
return data2.index.lookup(key).find((d) => d.kind === "loc_key" && d.value !== void 0)?.value ?? key;
|
|
64185
|
+
}
|
|
64186
|
+
function summaryOf(data2, model, rec, houseCount) {
|
|
64187
|
+
return {
|
|
64188
|
+
id: rec.id,
|
|
64189
|
+
nameKey: rec.nameKey,
|
|
64190
|
+
name: locText(data2, rec.nameKey),
|
|
64191
|
+
culture: rec.culture,
|
|
64192
|
+
source: rec.source,
|
|
64193
|
+
file: rec.file,
|
|
64194
|
+
line: rec.line,
|
|
64195
|
+
characterCount: model.members.get(rec.id)?.length ?? 0,
|
|
64196
|
+
houseCount
|
|
64197
|
+
};
|
|
64198
|
+
}
|
|
64199
|
+
function computeDynastyTree(data2, params, inFocus = () => true) {
|
|
64200
|
+
const supported = activeProfile().schema.some((entry) => entry.kind === DYNASTY_KIND);
|
|
64201
|
+
if (!supported) return { supported: false, dynasties: [] };
|
|
64202
|
+
const model = modelFor(data2);
|
|
64203
|
+
const visible = (rec2) => rec2.source !== "mod" || inFocus(rec2.file);
|
|
64204
|
+
const houseCounts = /* @__PURE__ */ new Map();
|
|
64205
|
+
for (const house of model.houses.values()) {
|
|
64206
|
+
if (!visible(house)) continue;
|
|
64207
|
+
houseCounts.set(house.dynasty, (houseCounts.get(house.dynasty) ?? 0) + 1);
|
|
64208
|
+
}
|
|
64209
|
+
const wanted = params.dynasty;
|
|
64210
|
+
if (wanted === void 0) {
|
|
64211
|
+
const mod = [];
|
|
64212
|
+
const rest = [];
|
|
64213
|
+
for (const rec2 of model.dynasties.values()) {
|
|
64214
|
+
if (!visible(rec2)) continue;
|
|
64215
|
+
const summary = summaryOf(data2, model, rec2, houseCounts.get(rec2.id) ?? 0);
|
|
64216
|
+
(rec2.source === "mod" ? mod : rest).push(summary);
|
|
64217
|
+
}
|
|
64218
|
+
const byName = (a, b) => a.name.localeCompare(b.name);
|
|
64219
|
+
mod.sort(byName);
|
|
64220
|
+
rest.sort(byName);
|
|
64221
|
+
return {
|
|
64222
|
+
supported: true,
|
|
64223
|
+
dynasties: [...mod, ...rest],
|
|
64224
|
+
nextCharacterId: model.nextCharacterId,
|
|
64225
|
+
nextDynastyId: model.nextDynastyId
|
|
64226
|
+
};
|
|
64227
|
+
}
|
|
64228
|
+
const rec = model.dynasties.get(wanted);
|
|
64229
|
+
if (!rec) {
|
|
64230
|
+
return {
|
|
64231
|
+
supported: true,
|
|
64232
|
+
dynasties: [],
|
|
64233
|
+
nextCharacterId: model.nextCharacterId,
|
|
64234
|
+
nextDynastyId: model.nextDynastyId
|
|
64235
|
+
};
|
|
64236
|
+
}
|
|
64237
|
+
const houses = [];
|
|
64238
|
+
for (const house of model.houses.values()) {
|
|
64239
|
+
if (house.dynasty !== wanted || !visible(house)) continue;
|
|
64240
|
+
houses.push({
|
|
64241
|
+
id: house.id,
|
|
64242
|
+
nameKey: house.nameKey,
|
|
64243
|
+
name: locText(data2, house.nameKey),
|
|
64244
|
+
dynasty: house.dynasty,
|
|
64245
|
+
source: house.source,
|
|
64246
|
+
file: house.file,
|
|
64247
|
+
line: house.line
|
|
64248
|
+
});
|
|
64249
|
+
}
|
|
64250
|
+
houses.sort((a, b) => a.name.localeCompare(b.name));
|
|
64251
|
+
const characters = [];
|
|
64252
|
+
const taken = /* @__PURE__ */ new Set();
|
|
64253
|
+
for (const id of model.members.get(wanted) ?? []) {
|
|
64254
|
+
const char = model.characters.get(id);
|
|
64255
|
+
if (!char || !visible(char) || taken.has(id)) continue;
|
|
64256
|
+
taken.add(id);
|
|
64257
|
+
characters.push(char);
|
|
64258
|
+
}
|
|
64259
|
+
for (const char of [...characters]) {
|
|
64260
|
+
for (const other of [char.father, char.mother, ...char.spouses]) {
|
|
64261
|
+
if (!other || taken.has(other)) continue;
|
|
64262
|
+
const rel = model.characters.get(other);
|
|
64263
|
+
if (!rel) continue;
|
|
64264
|
+
taken.add(other);
|
|
64265
|
+
characters.push({ ...rel, external: true });
|
|
64266
|
+
}
|
|
64267
|
+
}
|
|
64268
|
+
return {
|
|
64269
|
+
supported: true,
|
|
64270
|
+
dynasties: [],
|
|
64271
|
+
dynasty: summaryOf(data2, model, rec, houses.length),
|
|
64272
|
+
houses,
|
|
64273
|
+
characters,
|
|
64274
|
+
nextCharacterId: model.nextCharacterId,
|
|
64275
|
+
nextDynastyId: model.nextDynastyId
|
|
64276
|
+
};
|
|
64277
|
+
}
|
|
64278
|
+
|
|
63382
64279
|
// src/overview/eventVocabulary.ts
|
|
63383
64280
|
var MAX_DOC = 220;
|
|
63384
64281
|
function short(doc) {
|
|
@@ -63396,6 +64293,24 @@ function keyItems(specs) {
|
|
|
63396
64293
|
hint: spec.values === "block" ? "block" : spec.values === "bool" ? "yes/no" : spec.values === "loc" ? "loc" : void 0
|
|
63397
64294
|
}));
|
|
63398
64295
|
}
|
|
64296
|
+
function definitionsOfKind(data2, kind, inFocus = () => true) {
|
|
64297
|
+
const seen = /* @__PURE__ */ new Set();
|
|
64298
|
+
const mod = [];
|
|
64299
|
+
const rest = [];
|
|
64300
|
+
for (const def of data2.index.allDefinitions()) {
|
|
64301
|
+
if (def.kind !== kind || seen.has(def.name)) continue;
|
|
64302
|
+
if (def.source === "mod" && !inFocus(def.file)) continue;
|
|
64303
|
+
seen.add(def.name);
|
|
64304
|
+
(def.source === "mod" ? mod : rest).push({
|
|
64305
|
+
value: def.name,
|
|
64306
|
+
doc: short(def.doc),
|
|
64307
|
+
hint: def.source === "mod" ? "this mod" : def.source
|
|
64308
|
+
});
|
|
64309
|
+
}
|
|
64310
|
+
mod.sort((a, b) => a.value.localeCompare(b.value));
|
|
64311
|
+
rest.sort((a, b) => a.value.localeCompare(b.value));
|
|
64312
|
+
return [...mod, ...rest].slice(0, EVENT_VOCABULARY_MAX_VALUES);
|
|
64313
|
+
}
|
|
63399
64314
|
function computeEventVocabulary(data2, schema2, inFocus = () => true) {
|
|
63400
64315
|
const blocks = schema2.structures.keysByKindBlock.get("event");
|
|
63401
64316
|
const eventKeys = keyItems(blocks?.get(""));
|
|
@@ -63403,26 +64318,11 @@ function computeEventVocabulary(data2, schema2, inFocus = () => true) {
|
|
|
63403
64318
|
const values = {};
|
|
63404
64319
|
const byKind = /* @__PURE__ */ new Map();
|
|
63405
64320
|
const definitionsOf = (kind) => {
|
|
63406
|
-
let
|
|
63407
|
-
if (
|
|
63408
|
-
|
|
63409
|
-
|
|
63410
|
-
|
|
63411
|
-
for (const def of data2.index.allDefinitions()) {
|
|
63412
|
-
if (def.kind !== kind || seen.has(def.name)) continue;
|
|
63413
|
-
if (def.source === "mod" && !inFocus(def.file)) continue;
|
|
63414
|
-
seen.add(def.name);
|
|
63415
|
-
(def.source === "mod" ? mod : rest).push({
|
|
63416
|
-
value: def.name,
|
|
63417
|
-
doc: short(def.doc),
|
|
63418
|
-
hint: def.source === "mod" ? "this mod" : def.source
|
|
63419
|
-
});
|
|
63420
|
-
}
|
|
63421
|
-
mod.sort((a, b) => a.value.localeCompare(b.value));
|
|
63422
|
-
rest.sort((a, b) => a.value.localeCompare(b.value));
|
|
63423
|
-
cached = [...mod, ...rest].slice(0, EVENT_VOCABULARY_MAX_VALUES);
|
|
63424
|
-
byKind.set(kind, cached);
|
|
63425
|
-
return cached;
|
|
64321
|
+
let cached2 = byKind.get(kind);
|
|
64322
|
+
if (cached2) return cached2;
|
|
64323
|
+
cached2 = definitionsOfKind(data2, kind, inFocus);
|
|
64324
|
+
byKind.set(kind, cached2);
|
|
64325
|
+
return cached2;
|
|
63426
64326
|
};
|
|
63427
64327
|
for (const specs of [blocks?.get(""), blocks?.get("option")]) {
|
|
63428
64328
|
for (const spec of specs?.values() ?? []) {
|
|
@@ -63495,27 +64395,12 @@ function computeValueOptions(data2, value, inFocus = () => true) {
|
|
|
63495
64395
|
if (/^-?[\d.]+$/.test(name) || name.includes(":") || name.includes(".")) return null;
|
|
63496
64396
|
const def = data2.index.lookup(name).find((d) => !VALUE_KIND_SKIP.has(d.kind));
|
|
63497
64397
|
if (!def) return null;
|
|
63498
|
-
const
|
|
63499
|
-
const mod = [];
|
|
63500
|
-
const rest = [];
|
|
63501
|
-
for (const d of data2.index.allDefinitions()) {
|
|
63502
|
-
if (d.kind !== def.kind || seen.has(d.name)) continue;
|
|
63503
|
-
if (d.source === "mod" && !inFocus(d.file)) continue;
|
|
63504
|
-
seen.add(d.name);
|
|
63505
|
-
(d.source === "mod" ? mod : rest).push({
|
|
63506
|
-
value: d.name,
|
|
63507
|
-
doc: short(d.doc),
|
|
63508
|
-
hint: d.source === "mod" ? "this mod" : d.source
|
|
63509
|
-
});
|
|
63510
|
-
}
|
|
63511
|
-
mod.sort((a, b) => a.value.localeCompare(b.value));
|
|
63512
|
-
rest.sort((a, b) => a.value.localeCompare(b.value));
|
|
63513
|
-
const items = [...mod, ...rest].slice(0, EVENT_VOCABULARY_MAX_VALUES);
|
|
64398
|
+
const items = definitionsOfKind(data2, def.kind, inFocus);
|
|
63514
64399
|
return items.length > 1 ? { kind: def.kind, items } : null;
|
|
63515
64400
|
}
|
|
63516
64401
|
|
|
63517
64402
|
// src/overview/eventBanner.ts
|
|
63518
|
-
var
|
|
64403
|
+
var fs32 = __toESM(require("fs"));
|
|
63519
64404
|
var TEXTURE_PATH = /\.(dds|tga|png)$/i;
|
|
63520
64405
|
function computeEventBanner(data2, theme) {
|
|
63521
64406
|
if (TEXTURE_PATH.test(theme)) return { theme, texture: theme };
|
|
@@ -63537,7 +64422,7 @@ function referenceOf(data2, name, kind) {
|
|
|
63537
64422
|
if (!def) return null;
|
|
63538
64423
|
let block2 = null;
|
|
63539
64424
|
try {
|
|
63540
|
-
const text = decode(
|
|
64425
|
+
const text = decode(fs32.readFileSync(def.file)).text;
|
|
63541
64426
|
const stmt = parseScript(text).root.statements.find(
|
|
63542
64427
|
(s2) => s2.kind === "assignment" && s2.key.text === name
|
|
63543
64428
|
);
|
|
@@ -63575,9 +64460,691 @@ function childBlock5(stmt) {
|
|
|
63575
64460
|
return null;
|
|
63576
64461
|
}
|
|
63577
64462
|
|
|
64463
|
+
// src/creators/definitionForm.ts
|
|
64464
|
+
var fs33 = __toESM(require("fs"));
|
|
64465
|
+
var EXISTING_CAP = 500;
|
|
64466
|
+
function formKeys(specs) {
|
|
64467
|
+
if (!specs) return [];
|
|
64468
|
+
return [...specs.values()].map((spec) => ({
|
|
64469
|
+
key: spec.key,
|
|
64470
|
+
...short(spec.doc) ? { doc: short(spec.doc) } : {},
|
|
64471
|
+
...spec.values ? { values: spec.values } : {},
|
|
64472
|
+
...spec.freq !== void 0 ? { freq: spec.freq } : {},
|
|
64473
|
+
...spec.refKinds?.length ? { refKinds: spec.refKinds } : {}
|
|
64474
|
+
}));
|
|
64475
|
+
}
|
|
64476
|
+
function parsedFile(file, cache6) {
|
|
64477
|
+
const seen = cache6.get(file);
|
|
64478
|
+
if (seen) return seen;
|
|
64479
|
+
const defs = /* @__PURE__ */ new Map();
|
|
64480
|
+
cache6.set(file, defs);
|
|
64481
|
+
let text;
|
|
64482
|
+
try {
|
|
64483
|
+
text = decode(fs33.readFileSync(file)).text;
|
|
64484
|
+
} catch {
|
|
64485
|
+
return defs;
|
|
64486
|
+
}
|
|
64487
|
+
for (const s2 of parseScript(text).root.statements) {
|
|
64488
|
+
if (s2.kind !== "assignment" || s2.value?.kind !== "block") continue;
|
|
64489
|
+
defs.set(s2.key.text, {
|
|
64490
|
+
block: s2.value,
|
|
64491
|
+
source: text.slice(s2.key.range.start, s2.value.range.end),
|
|
64492
|
+
start: s2.key.range.start
|
|
64493
|
+
});
|
|
64494
|
+
}
|
|
64495
|
+
return defs;
|
|
64496
|
+
}
|
|
64497
|
+
function definitionFiles(data2, kind) {
|
|
64498
|
+
const out = [];
|
|
64499
|
+
for (const def of data2.index.allDefinitions()) {
|
|
64500
|
+
if (def.kind === kind) out.push({ name: def.name, file: def.file });
|
|
64501
|
+
}
|
|
64502
|
+
return out;
|
|
64503
|
+
}
|
|
64504
|
+
function scalarOf2(block2, key) {
|
|
64505
|
+
for (const s2 of block2.statements) {
|
|
64506
|
+
if (s2.kind === "assignment" && s2.key.text === key && s2.value?.kind === "scalar") return s2.value.text;
|
|
64507
|
+
}
|
|
64508
|
+
return null;
|
|
64509
|
+
}
|
|
64510
|
+
function offerable(text) {
|
|
64511
|
+
return text !== "" && !/^-?\d+(\.\d+)?$/.test(text) && !text.includes(":") && !text.startsWith("@");
|
|
64512
|
+
}
|
|
64513
|
+
function namesIn(value, into) {
|
|
64514
|
+
if (value.kind === "scalar") {
|
|
64515
|
+
if (!value.quoted && offerable(value.text)) into(value.text);
|
|
64516
|
+
return;
|
|
64517
|
+
}
|
|
64518
|
+
if (value.kind !== "block") return;
|
|
64519
|
+
for (const s2 of value.statements) {
|
|
64520
|
+
const inner = s2.kind === "value" ? s2.value : s2.value;
|
|
64521
|
+
if (inner?.kind === "scalar" && !inner.quoted && offerable(inner.text)) into(inner.text);
|
|
64522
|
+
}
|
|
64523
|
+
}
|
|
64524
|
+
function groupOptions(data2, schema2, kind, items, cache6) {
|
|
64525
|
+
const groupKey = schema2.entries.find((e) => e.kind === kind)?.groupKey;
|
|
64526
|
+
if (!groupKey) return;
|
|
64527
|
+
const groups = /* @__PURE__ */ new Map();
|
|
64528
|
+
for (const { name, file } of definitionFiles(data2, kind)) {
|
|
64529
|
+
const def = parsedFile(file, cache6).get(name);
|
|
64530
|
+
const group = def ? scalarOf2(def.block, groupKey) : null;
|
|
64531
|
+
if (group !== null) groups.set(name, group);
|
|
64532
|
+
}
|
|
64533
|
+
for (const item of items) {
|
|
64534
|
+
const group = groups.get(item.value);
|
|
64535
|
+
if (group !== void 0) item.group = group;
|
|
64536
|
+
}
|
|
64537
|
+
}
|
|
64538
|
+
function sampledValues(data2, kind, keys, cache6) {
|
|
64539
|
+
const wanted = keys.filter((k) => !k.refKinds?.length);
|
|
64540
|
+
if (wanted.length === 0) return;
|
|
64541
|
+
const counts = /* @__PURE__ */ new Map();
|
|
64542
|
+
const literals = /* @__PURE__ */ new Map();
|
|
64543
|
+
const bodies = /* @__PURE__ */ new Map();
|
|
64544
|
+
for (const key of wanted) {
|
|
64545
|
+
counts.set(key.key, /* @__PURE__ */ new Map());
|
|
64546
|
+
literals.set(key.key, /* @__PURE__ */ new Map());
|
|
64547
|
+
bodies.set(key.key, /* @__PURE__ */ new Map());
|
|
64548
|
+
}
|
|
64549
|
+
let read = 0;
|
|
64550
|
+
for (const { name, file } of definitionFiles(data2, kind)) {
|
|
64551
|
+
if (read >= EVENT_VOCABULARY_MAX_VALUES) break;
|
|
64552
|
+
const def = parsedFile(file, cache6).get(name);
|
|
64553
|
+
if (!def) continue;
|
|
64554
|
+
read++;
|
|
64555
|
+
for (const s2 of def.block.statements) {
|
|
64556
|
+
if (s2.kind !== "assignment" || !s2.value) continue;
|
|
64557
|
+
const bucket = counts.get(s2.key.text);
|
|
64558
|
+
if (!bucket) continue;
|
|
64559
|
+
namesIn(s2.value, (v) => bucket.set(v, (bucket.get(v) ?? 0) + 1));
|
|
64560
|
+
if (s2.value.kind === "scalar" && s2.value.text !== "") {
|
|
64561
|
+
const seen = literals.get(s2.key.text);
|
|
64562
|
+
seen.set(s2.value.text, (seen.get(s2.value.text) ?? 0) + 1);
|
|
64563
|
+
} else if (s2.value.kind === "block") {
|
|
64564
|
+
const body = oneLineBody(
|
|
64565
|
+
def.source.slice(s2.value.range.start - def.start, s2.value.range.end - def.start)
|
|
64566
|
+
);
|
|
64567
|
+
if (body !== "") {
|
|
64568
|
+
const seen = bodies.get(s2.key.text);
|
|
64569
|
+
seen.set(body, (seen.get(body) ?? 0) + 1);
|
|
64570
|
+
}
|
|
64571
|
+
}
|
|
64572
|
+
}
|
|
64573
|
+
}
|
|
64574
|
+
const mostUsed = (bucket) => [...bucket.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
|
|
64575
|
+
for (const key of wanted) {
|
|
64576
|
+
const bucket = counts.get(key.key);
|
|
64577
|
+
const stated = key.values === "bool" || key.values?.startsWith("enum:") === true;
|
|
64578
|
+
if (!stated && bucket.size > 0 && bucket.size <= DEFINITION_FORM_MAX_SAMPLED) {
|
|
64579
|
+
key.sampled = mostUsed(bucket).map(([value]) => value);
|
|
64580
|
+
}
|
|
64581
|
+
const example = mostUsed(literals.get(key.key))[0] ?? mostUsed(bodies.get(key.key))[0];
|
|
64582
|
+
if (example) key.example = example[0];
|
|
64583
|
+
}
|
|
64584
|
+
}
|
|
64585
|
+
function oneLineBody(text) {
|
|
64586
|
+
const flat = text.replace(/#[^\n]*/g, " ").replace(/\s+/g, " ").trim();
|
|
64587
|
+
return flat.length > DEFINITION_FORM_MAX_EXAMPLE ? `${flat.slice(0, DEFINITION_FORM_MAX_EXAMPLE - 1).trimEnd()}\u2026` : flat;
|
|
64588
|
+
}
|
|
64589
|
+
function docListValues(traits) {
|
|
64590
|
+
for (const line of traits.split("\n")) {
|
|
64591
|
+
const names = line.slice(line.lastIndexOf(":") + 1).split(",").map(
|
|
64592
|
+
(part) => part.trim().replace(/^and\s+/i, "").replace(/\.$/, "")
|
|
64593
|
+
).filter((name) => /^[A-Za-z][A-Za-z0-9_]*$/.test(name));
|
|
64594
|
+
if (names.length > 0) return [...new Set(names)];
|
|
64595
|
+
}
|
|
64596
|
+
return [];
|
|
64597
|
+
}
|
|
64598
|
+
function innerKeysOf(data2, kind, except, cache6) {
|
|
64599
|
+
const skip = new Set(except);
|
|
64600
|
+
const names = [];
|
|
64601
|
+
for (const { name, file } of definitionFiles(data2, kind)) {
|
|
64602
|
+
const def = parsedFile(file, cache6).get(name);
|
|
64603
|
+
if (!def) continue;
|
|
64604
|
+
for (const s2 of def.block.statements) {
|
|
64605
|
+
if (s2.kind !== "assignment" || s2.value?.kind !== "block") continue;
|
|
64606
|
+
if (skip.has(s2.key.text) || names.includes(s2.key.text)) continue;
|
|
64607
|
+
names.push(s2.key.text);
|
|
64608
|
+
}
|
|
64609
|
+
}
|
|
64610
|
+
return names;
|
|
64611
|
+
}
|
|
64612
|
+
function conditionItems(data2, source, trigger, inFocus, cache6) {
|
|
64613
|
+
if (source.from === "kind") return definitionsOfKind(data2, source.kind, inFocus);
|
|
64614
|
+
const values = source.from === "docList" ? docListValues(data2.tokenMap.get(trigger)?.find((token) => token.traits)?.traits ?? "") : innerKeysOf(data2, source.kind, source.except ?? [], cache6);
|
|
64615
|
+
return values.slice(0, EVENT_VOCABULARY_MAX_VALUES).map((value) => ({ value }));
|
|
64616
|
+
}
|
|
64617
|
+
function labeller(data2, schema2) {
|
|
64618
|
+
const patterns = /* @__PURE__ */ new Map();
|
|
64619
|
+
const patternsFor = (kind) => {
|
|
64620
|
+
let list2 = patterns.get(kind);
|
|
64621
|
+
if (!list2) {
|
|
64622
|
+
const entry = schema2.entries.find((e) => e.kind === kind);
|
|
64623
|
+
const own = entry?.locPatterns ?? entry?.requiredLoc ?? [];
|
|
64624
|
+
list2 = own.length > 0 ? [own[0]] : ["$_name", "$"];
|
|
64625
|
+
patterns.set(kind, list2);
|
|
64626
|
+
}
|
|
64627
|
+
return list2;
|
|
64628
|
+
};
|
|
64629
|
+
const locValue2 = (key) => data2.index.lookup(key).find((d) => d.kind === "loc_key" && d.value !== void 0)?.value;
|
|
64630
|
+
return (kind, name) => {
|
|
64631
|
+
for (const pattern of patternsFor(kind)) {
|
|
64632
|
+
const value = locValue2(pattern.replace("$", name));
|
|
64633
|
+
if (value === void 0 || value === "") continue;
|
|
64634
|
+
const alias = /^\$([\w.-]+)\$$/.exec(value);
|
|
64635
|
+
const resolved = alias ? locValue2(alias[1]) : void 0;
|
|
64636
|
+
return resolved !== void 0 && resolved !== "" ? resolved : value;
|
|
64637
|
+
}
|
|
64638
|
+
return void 0;
|
|
64639
|
+
};
|
|
64640
|
+
}
|
|
64641
|
+
function computeDefinitionForm(data2, schema2, params, inFocus = () => true) {
|
|
64642
|
+
const kind = params?.kind?.trim() ?? "";
|
|
64643
|
+
const entry = schema2.entries.find((e) => e.kind === kind);
|
|
64644
|
+
if (kind === "" || !entry) return null;
|
|
64645
|
+
const blocks = schema2.structures.keysByKindBlock.get(kind);
|
|
64646
|
+
const keys = formKeys(blocks?.get(""));
|
|
64647
|
+
const subBlocks = {};
|
|
64648
|
+
for (const [name, specs] of blocks ?? []) {
|
|
64649
|
+
if (name !== "") subBlocks[name] = formKeys(specs);
|
|
64650
|
+
}
|
|
64651
|
+
const files = /* @__PURE__ */ new Map();
|
|
64652
|
+
const labelOf = labeller(data2, schema2);
|
|
64653
|
+
const options = {};
|
|
64654
|
+
for (const key of keys) {
|
|
64655
|
+
for (const refKind of key.refKinds ?? []) {
|
|
64656
|
+
if (options[refKind]) continue;
|
|
64657
|
+
options[refKind] = definitionsOfKind(data2, refKind, inFocus);
|
|
64658
|
+
groupOptions(data2, schema2, refKind, options[refKind], files);
|
|
64659
|
+
for (const item of options[refKind]) {
|
|
64660
|
+
const label = labelOf(refKind, item.value);
|
|
64661
|
+
if (label !== void 0) item.label = label;
|
|
64662
|
+
}
|
|
64663
|
+
}
|
|
64664
|
+
}
|
|
64665
|
+
sampledValues(data2, kind, keys, files);
|
|
64666
|
+
const conditions = {};
|
|
64667
|
+
for (const [trigger, source] of Object.entries(activeProfile().conditionValues ?? {})) {
|
|
64668
|
+
const items = conditionItems(data2, source, trigger, inFocus, files);
|
|
64669
|
+
if (items.length > 0) conditions[trigger] = items;
|
|
64670
|
+
}
|
|
64671
|
+
const byName = /* @__PURE__ */ new Map();
|
|
64672
|
+
for (const def of data2.index.allDefinitions()) {
|
|
64673
|
+
if (def.kind !== kind) continue;
|
|
64674
|
+
if (def.source === "mod" && !inFocus(def.file)) continue;
|
|
64675
|
+
const seen = byName.get(def.name);
|
|
64676
|
+
if (seen && !(def.source === "mod" && seen.source !== "mod")) continue;
|
|
64677
|
+
const label = labelOf(kind, def.name);
|
|
64678
|
+
byName.set(def.name, {
|
|
64679
|
+
name: def.name,
|
|
64680
|
+
file: def.file,
|
|
64681
|
+
line: def.line,
|
|
64682
|
+
source: def.source,
|
|
64683
|
+
...label !== void 0 ? { label } : {}
|
|
64684
|
+
});
|
|
64685
|
+
}
|
|
64686
|
+
const existing = [...byName.values()].sort((a, b) => Number(b.source === "mod") - Number(a.source === "mod") || a.name.localeCompare(b.name)).slice(0, EXISTING_CAP);
|
|
64687
|
+
const modifiers = data2.tokens.filter((t) => t.kind === "modifier").sort((a, b) => data2.refIndex.usageCount(b.name) - data2.refIndex.usageCount(a.name)).slice(0, EVENT_VOCABULARY_MAX_VALUES).map((t) => ({ name: t.name, ...short(t.doc) ? { doc: short(t.doc) } : {} }));
|
|
64688
|
+
const form = {
|
|
64689
|
+
kind,
|
|
64690
|
+
folder: entry.path,
|
|
64691
|
+
// The whole set the game generates, which is a superset of the
|
|
64692
|
+
// conservative requiredLoc a diagnostic is allowed to demand.
|
|
64693
|
+
locPatterns: entry.locPatterns ?? entry.requiredLoc ?? [],
|
|
64694
|
+
...entry.iconFolder ? { iconFolder: entry.iconFolder } : {},
|
|
64695
|
+
keys,
|
|
64696
|
+
...Object.keys(subBlocks).length > 0 ? { blocks: subBlocks } : {},
|
|
64697
|
+
options,
|
|
64698
|
+
...Object.keys(conditions).length > 0 ? { conditions } : {},
|
|
64699
|
+
modifiers,
|
|
64700
|
+
existing
|
|
64701
|
+
};
|
|
64702
|
+
const wanted = params.name?.trim();
|
|
64703
|
+
if (wanted) {
|
|
64704
|
+
const defs = data2.index.lookup(wanted).filter((d) => d.kind === kind);
|
|
64705
|
+
const def = defs.find((d) => d.source === "mod" && inFocus(d.file)) ?? defs[0];
|
|
64706
|
+
const parsed = def ? parsedFile(def.file, files).get(wanted) : void 0;
|
|
64707
|
+
if (def && parsed) {
|
|
64708
|
+
form.current = { file: def.file, line: def.line, source: def.source, text: parsed.source };
|
|
64709
|
+
}
|
|
64710
|
+
}
|
|
64711
|
+
return form;
|
|
64712
|
+
}
|
|
64713
|
+
|
|
64714
|
+
// src/creators/definitionEdit.ts
|
|
64715
|
+
function topLevelBlock(file, name) {
|
|
64716
|
+
for (const entry of file.root.entries) {
|
|
64717
|
+
if (entry.key === name && entry.valueKind === "block") return entry;
|
|
64718
|
+
}
|
|
64719
|
+
return null;
|
|
64720
|
+
}
|
|
64721
|
+
function toFileNewline(text, file) {
|
|
64722
|
+
return text.replace(/\r?\n/g, file.newline);
|
|
64723
|
+
}
|
|
64724
|
+
function upsertBlock(file, name, blockText2, appended) {
|
|
64725
|
+
const trimmed = blockText2.trim();
|
|
64726
|
+
if (name.trim() === "" || trimmed === "") {
|
|
64727
|
+
return "an upsert needs both a definition name and the block text to write.";
|
|
64728
|
+
}
|
|
64729
|
+
const body = toFileNewline(trimmed, file);
|
|
64730
|
+
const existing = topLevelBlock(file, name);
|
|
64731
|
+
if (existing) return { start: existing.span.start, end: existing.span.end, newText: body };
|
|
64732
|
+
const text = file.text + appended;
|
|
64733
|
+
const eol = file.newline;
|
|
64734
|
+
const at = file.text.length;
|
|
64735
|
+
if (text.trim() === "") return { start: at, end: at, newText: body + eol };
|
|
64736
|
+
const closeLastLine = text.endsWith("\n") ? "" : eol;
|
|
64737
|
+
return { start: at, end: at, newText: closeLastLine + eol + body + eol };
|
|
64738
|
+
}
|
|
64739
|
+
function setProperties2(file, name, properties2) {
|
|
64740
|
+
const target = topLevelBlock(file, name);
|
|
64741
|
+
if (!target) {
|
|
64742
|
+
return `this file has no top-level \`${name} = { \u2026 }\` to change: write the whole block instead.`;
|
|
64743
|
+
}
|
|
64744
|
+
const edits = [];
|
|
64745
|
+
const missing = [];
|
|
64746
|
+
for (const { key, value } of properties2 ?? []) {
|
|
64747
|
+
if (typeof key !== "string" || key.trim() === "") continue;
|
|
64748
|
+
const existing = target.body ? findEntry(target.body, key) : null;
|
|
64749
|
+
if (value === null) {
|
|
64750
|
+
const edit = existing ? removeProperty(file, existing) : null;
|
|
64751
|
+
if (edit) edits.push(edit);
|
|
64752
|
+
continue;
|
|
64753
|
+
}
|
|
64754
|
+
if (existing) {
|
|
64755
|
+
const edit = setValue(file, existing, value);
|
|
64756
|
+
if (edit) edits.push(edit);
|
|
64757
|
+
} else {
|
|
64758
|
+
missing.push([key, value]);
|
|
64759
|
+
}
|
|
64760
|
+
}
|
|
64761
|
+
const insert = missing.length > 0 ? insertProperties(file, target, missing) : null;
|
|
64762
|
+
if (insert) edits.push(insert);
|
|
64763
|
+
return edits;
|
|
64764
|
+
}
|
|
64765
|
+
function overlaps(a, b) {
|
|
64766
|
+
return a.some((x) => b.some((y) => x.start < y.end && y.start < x.end));
|
|
64767
|
+
}
|
|
64768
|
+
function computeDefinitionEdits(params) {
|
|
64769
|
+
const text = params?.text ?? "";
|
|
64770
|
+
const ops = Array.isArray(params?.ops) ? params.ops : [];
|
|
64771
|
+
if (ops.length === 0) return { edits: [], ops: [] };
|
|
64772
|
+
const file = parseGuiSource(text, SCRIPT_DIALECT);
|
|
64773
|
+
if (file.errors.length > 0) {
|
|
64774
|
+
const refused = `this file has ${file.errors.length} parse error(s), so no offset in it can be trusted: fix the syntax first.`;
|
|
64775
|
+
return { edits: [], ops: ops.map(() => ({ refused })) };
|
|
64776
|
+
}
|
|
64777
|
+
const edits = [];
|
|
64778
|
+
const verdicts = [];
|
|
64779
|
+
const endOfFile = text.length;
|
|
64780
|
+
let appended = "";
|
|
64781
|
+
let appendEdit = null;
|
|
64782
|
+
for (const op of ops) {
|
|
64783
|
+
const answer = runOp2(file, op, appended);
|
|
64784
|
+
if (typeof answer === "string") {
|
|
64785
|
+
verdicts.push({ refused: answer });
|
|
64786
|
+
continue;
|
|
64787
|
+
}
|
|
64788
|
+
if (answer.length === 0) {
|
|
64789
|
+
verdicts.push({});
|
|
64790
|
+
continue;
|
|
64791
|
+
}
|
|
64792
|
+
if (overlaps(edits, answer)) {
|
|
64793
|
+
verdicts.push({
|
|
64794
|
+
refused: "another change in the same save already rewrites those bytes, so this one was left out: make it on its own."
|
|
64795
|
+
});
|
|
64796
|
+
continue;
|
|
64797
|
+
}
|
|
64798
|
+
for (const edit of answer) {
|
|
64799
|
+
if (edit.start === endOfFile && edit.end === endOfFile) {
|
|
64800
|
+
appended += edit.newText;
|
|
64801
|
+
if (appendEdit) appendEdit.newText += edit.newText;
|
|
64802
|
+
else {
|
|
64803
|
+
appendEdit = { ...edit };
|
|
64804
|
+
edits.push(appendEdit);
|
|
64805
|
+
}
|
|
64806
|
+
continue;
|
|
64807
|
+
}
|
|
64808
|
+
edits.push(edit);
|
|
64809
|
+
}
|
|
64810
|
+
verdicts.push({});
|
|
64811
|
+
}
|
|
64812
|
+
return { edits, ops: verdicts };
|
|
64813
|
+
}
|
|
64814
|
+
function runOp2(file, op, appended) {
|
|
64815
|
+
if (!op || typeof op.op !== "string") return "the server has no such edit.";
|
|
64816
|
+
switch (op.op) {
|
|
64817
|
+
case "setProperties": {
|
|
64818
|
+
const answer = setProperties2(file, op.name ?? "", op.properties ?? []);
|
|
64819
|
+
return typeof answer === "string" ? answer : answer;
|
|
64820
|
+
}
|
|
64821
|
+
case "upsertBlock": {
|
|
64822
|
+
const answer = upsertBlock(file, op.name ?? "", op.text ?? "", appended);
|
|
64823
|
+
return typeof answer === "string" ? answer : [answer];
|
|
64824
|
+
}
|
|
64825
|
+
default:
|
|
64826
|
+
return "the server has no such edit.";
|
|
64827
|
+
}
|
|
64828
|
+
}
|
|
64829
|
+
|
|
64830
|
+
// src/creators/modifierFormats.ts
|
|
64831
|
+
var fs34 = __toESM(require("fs"));
|
|
64832
|
+
var path34 = __toESM(require("path"));
|
|
64833
|
+
var cache5 = /* @__PURE__ */ new Map();
|
|
64834
|
+
function readText(file) {
|
|
64835
|
+
try {
|
|
64836
|
+
return decode(fs34.readFileSync(file)).text;
|
|
64837
|
+
} catch {
|
|
64838
|
+
return null;
|
|
64839
|
+
}
|
|
64840
|
+
}
|
|
64841
|
+
function scalar2(block2, key) {
|
|
64842
|
+
for (const s2 of block2.statements) {
|
|
64843
|
+
if (s2.kind === "assignment" && s2.key.text === key && s2.value?.kind === "scalar") return s2.value.text;
|
|
64844
|
+
}
|
|
64845
|
+
return null;
|
|
64846
|
+
}
|
|
64847
|
+
function flag(block2, key) {
|
|
64848
|
+
const value = scalar2(block2, key);
|
|
64849
|
+
return value === null ? void 0 : value === "yes";
|
|
64850
|
+
}
|
|
64851
|
+
function uvOf(block2, key) {
|
|
64852
|
+
for (const s2 of block2.statements) {
|
|
64853
|
+
if (s2.kind !== "assignment" || s2.key.text !== key || s2.value?.kind !== "block") continue;
|
|
64854
|
+
const numbers2 = [];
|
|
64855
|
+
for (const inner of s2.value.statements) {
|
|
64856
|
+
if (inner.kind === "value" && inner.value.kind === "scalar") numbers2.push(Number(inner.value.text));
|
|
64857
|
+
}
|
|
64858
|
+
if (numbers2.length === 4 && numbers2.every((n) => Number.isFinite(n))) {
|
|
64859
|
+
return [numbers2[0], numbers2[1], numbers2[2], numbers2[3]];
|
|
64860
|
+
}
|
|
64861
|
+
}
|
|
64862
|
+
return void 0;
|
|
64863
|
+
}
|
|
64864
|
+
function readFormats(dir) {
|
|
64865
|
+
const out = /* @__PURE__ */ new Map();
|
|
64866
|
+
let files;
|
|
64867
|
+
try {
|
|
64868
|
+
files = fs34.readdirSync(dir).filter((f) => f.endsWith(".txt"));
|
|
64869
|
+
} catch {
|
|
64870
|
+
return out;
|
|
64871
|
+
}
|
|
64872
|
+
for (const file of files.sort()) {
|
|
64873
|
+
const text = readText(path34.join(dir, file));
|
|
64874
|
+
if (text === null) continue;
|
|
64875
|
+
for (const s2 of parseScript(text).root.statements) {
|
|
64876
|
+
if (s2.kind !== "assignment" || s2.value?.kind !== "block") continue;
|
|
64877
|
+
const written = scalar2(s2.value, "decimals");
|
|
64878
|
+
const decimals = written === null ? NaN : Number(written);
|
|
64879
|
+
const color = scalar2(s2.value, "color");
|
|
64880
|
+
const prefix = scalar2(s2.value, "prefix");
|
|
64881
|
+
const suffix = scalar2(s2.value, "suffix");
|
|
64882
|
+
const negativeSuffix = scalar2(s2.value, "negative_suffix");
|
|
64883
|
+
const percent = flag(s2.value, "percent");
|
|
64884
|
+
const alreadyPercent = flag(s2.value, "already_percent");
|
|
64885
|
+
const hidden2 = flag(s2.value, "hidden");
|
|
64886
|
+
const noSign = flag(s2.value, "no_difference_sign");
|
|
64887
|
+
out.set(s2.key.text, {
|
|
64888
|
+
...Number.isFinite(decimals) ? { decimals } : {},
|
|
64889
|
+
...color !== null ? { color } : {},
|
|
64890
|
+
...percent !== void 0 ? { percent } : {},
|
|
64891
|
+
...alreadyPercent !== void 0 ? { alreadyPercent } : {},
|
|
64892
|
+
...hidden2 !== void 0 ? { hidden: hidden2 } : {},
|
|
64893
|
+
...noSign !== void 0 ? { noSign } : {},
|
|
64894
|
+
...prefix !== null ? { prefix } : {},
|
|
64895
|
+
...suffix !== null ? { suffix } : {},
|
|
64896
|
+
...negativeSuffix !== null ? { negativeSuffix } : {}
|
|
64897
|
+
});
|
|
64898
|
+
}
|
|
64899
|
+
}
|
|
64900
|
+
return out;
|
|
64901
|
+
}
|
|
64902
|
+
function readTextIcons(file) {
|
|
64903
|
+
const out = /* @__PURE__ */ new Map();
|
|
64904
|
+
const text = readText(file);
|
|
64905
|
+
if (text === null) return out;
|
|
64906
|
+
for (const s2 of parseScript(text).root.statements) {
|
|
64907
|
+
if (s2.kind !== "assignment" || s2.key.text !== "texticon" || s2.value?.kind !== "block") continue;
|
|
64908
|
+
const name = scalar2(s2.value, "icon");
|
|
64909
|
+
if (name === null) continue;
|
|
64910
|
+
for (const inner of s2.value.statements) {
|
|
64911
|
+
if (inner.kind !== "assignment" || inner.key.text !== "iconsize" || inner.value?.kind !== "block") {
|
|
64912
|
+
continue;
|
|
64913
|
+
}
|
|
64914
|
+
const texture = scalar2(inner.value, "texture");
|
|
64915
|
+
if (texture === null) continue;
|
|
64916
|
+
const uv = uvOf(inner.value, "uv");
|
|
64917
|
+
out.set(name, { texture, ...uv ? { uv } : {} });
|
|
64918
|
+
}
|
|
64919
|
+
}
|
|
64920
|
+
return out;
|
|
64921
|
+
}
|
|
64922
|
+
function sourcesFor(gamePath, source) {
|
|
64923
|
+
const key = `${gamePath}\0${source.folder}\0${source.textIcons}`;
|
|
64924
|
+
const seen = cache5.get(key);
|
|
64925
|
+
if (seen) return seen;
|
|
64926
|
+
const built = {
|
|
64927
|
+
formats: readFormats(path34.join(gamePath, source.folder)),
|
|
64928
|
+
icons: readTextIcons(path34.join(gamePath, source.textIcons))
|
|
64929
|
+
};
|
|
64930
|
+
cache5.set(key, built);
|
|
64931
|
+
return built;
|
|
64932
|
+
}
|
|
64933
|
+
function stripCodes(text) {
|
|
64934
|
+
return text.replace(/#!/g, "").replace(/#[A-Za-z0-9_;]+ /g, "");
|
|
64935
|
+
}
|
|
64936
|
+
function titleCase(name) {
|
|
64937
|
+
return name.split("_").filter((word) => word !== "").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
64938
|
+
}
|
|
64939
|
+
function toParts(raw, icons, loc) {
|
|
64940
|
+
const parts = [];
|
|
64941
|
+
let text = "";
|
|
64942
|
+
const flush = () => {
|
|
64943
|
+
if (text !== "") parts.push({ text });
|
|
64944
|
+
text = "";
|
|
64945
|
+
};
|
|
64946
|
+
const pushIcon = (name) => {
|
|
64947
|
+
const icon = icons.get(name);
|
|
64948
|
+
if (!icon) return false;
|
|
64949
|
+
flush();
|
|
64950
|
+
parts.push({ icon: { texture: icon.texture, ...icon.uv ? { uv: icon.uv } : {} } });
|
|
64951
|
+
return true;
|
|
64952
|
+
};
|
|
64953
|
+
const source = stripCodes(raw);
|
|
64954
|
+
for (let i = 0; i < source.length; ) {
|
|
64955
|
+
const char = source[i];
|
|
64956
|
+
if (char === "@") {
|
|
64957
|
+
const end = source.indexOf("!", i + 1);
|
|
64958
|
+
const name = end > i ? source.slice(i + 1, end) : "";
|
|
64959
|
+
if (/^[A-Za-z0-9_]+$/.test(name) && pushIcon(name)) {
|
|
64960
|
+
i = end + 1;
|
|
64961
|
+
continue;
|
|
64962
|
+
}
|
|
64963
|
+
}
|
|
64964
|
+
if (char === "[") {
|
|
64965
|
+
const end = source.indexOf("]", i + 1);
|
|
64966
|
+
if (end > i) {
|
|
64967
|
+
const inner = source.slice(i + 1, end);
|
|
64968
|
+
const bar = inner.indexOf("|");
|
|
64969
|
+
const word = (bar >= 0 ? inner.slice(0, bar) : inner).trim();
|
|
64970
|
+
const concept = /^[A-Za-z0-9_]+$/.test(word) ? loc(`game_concept_${word}`) : void 0;
|
|
64971
|
+
if (concept !== void 0) {
|
|
64972
|
+
const direct = /^@([A-Za-z0-9_]+)!$/.exec(concept.trim());
|
|
64973
|
+
if (direct && pushIcon(direct[1])) {
|
|
64974
|
+
i = end + 1;
|
|
64975
|
+
continue;
|
|
64976
|
+
}
|
|
64977
|
+
if (!direct) {
|
|
64978
|
+
text += stripCodes(concept);
|
|
64979
|
+
i = end + 1;
|
|
64980
|
+
continue;
|
|
64981
|
+
}
|
|
64982
|
+
}
|
|
64983
|
+
text += bar >= 0 ? word : source.slice(i, end + 1);
|
|
64984
|
+
i = end + 1;
|
|
64985
|
+
continue;
|
|
64986
|
+
}
|
|
64987
|
+
}
|
|
64988
|
+
text += char;
|
|
64989
|
+
i++;
|
|
64990
|
+
}
|
|
64991
|
+
flush();
|
|
64992
|
+
return parts;
|
|
64993
|
+
}
|
|
64994
|
+
function toText(raw, icons, loc) {
|
|
64995
|
+
return toParts(raw, icons, loc).map((part) => "text" in part ? part.text : "").join("").trim();
|
|
64996
|
+
}
|
|
64997
|
+
function computeModifierFormats(data2, source, gamePath, lines) {
|
|
64998
|
+
if (!source || !gamePath) return null;
|
|
64999
|
+
const { formats, icons } = sourcesFor(gamePath, source);
|
|
65000
|
+
const loc = (key) => data2.index.lookup(key).find((d) => d.kind === "loc_key" && d.value !== void 0)?.value;
|
|
65001
|
+
const parts = (key) => {
|
|
65002
|
+
if (key === void 0) return void 0;
|
|
65003
|
+
const value = loc(key);
|
|
65004
|
+
if (value === void 0) return void 0;
|
|
65005
|
+
const list2 = toParts(value, icons, loc);
|
|
65006
|
+
return list2.length > 0 ? list2 : void 0;
|
|
65007
|
+
};
|
|
65008
|
+
const out = {};
|
|
65009
|
+
for (const token of data2.tokens) {
|
|
65010
|
+
if (token.kind !== "modifier" || out[token.name]) continue;
|
|
65011
|
+
const raw = formats.get(token.name);
|
|
65012
|
+
const own = loc(token.name) ?? loc(`MOD_${token.name.toUpperCase()}`);
|
|
65013
|
+
const prefix = parts(raw?.prefix);
|
|
65014
|
+
const suffix = parts(raw?.suffix);
|
|
65015
|
+
const negativeSuffix = parts(raw?.negativeSuffix);
|
|
65016
|
+
out[token.name] = {
|
|
65017
|
+
label: (own !== void 0 ? toText(own, icons, loc) : "") || titleCase(token.name),
|
|
65018
|
+
// _definitions.info: "decimals = int # Defaults to 2".
|
|
65019
|
+
decimals: raw?.decimals ?? 2,
|
|
65020
|
+
// _definitions.info says "Defaults to bad", but the game's own file
|
|
65021
|
+
// contradicts it: of 667 blocks in 00_definitions.txt, 113 write
|
|
65022
|
+
// `color = bad` and 2 write `color = good` (measured 1.19), and the
|
|
65023
|
+
// player sees `diplomacy = 1` green. A doc that matched the data would
|
|
65024
|
+
// never need 113 explicit `bad` lines, so the working default is good.
|
|
65025
|
+
color: raw?.color === "bad" || raw?.color === "neutral" ? raw.color : "good",
|
|
65026
|
+
...raw?.percent ? { percent: true } : {},
|
|
65027
|
+
...raw?.alreadyPercent ? { alreadyPercent: true } : {},
|
|
65028
|
+
...raw?.noSign ? { noSign: true } : {},
|
|
65029
|
+
...raw?.hidden ? { hidden: true } : {},
|
|
65030
|
+
...prefix ? { prefix } : {},
|
|
65031
|
+
...suffix ? { suffix } : {},
|
|
65032
|
+
...negativeSuffix ? { negativeSuffix } : {}
|
|
65033
|
+
};
|
|
65034
|
+
}
|
|
65035
|
+
if (!lines) return { formats: out };
|
|
65036
|
+
const rendered = {};
|
|
65037
|
+
for (const key of lines) {
|
|
65038
|
+
const list2 = parts(key);
|
|
65039
|
+
if (list2) rendered[key] = list2;
|
|
65040
|
+
}
|
|
65041
|
+
return { formats: out, lines: rendered };
|
|
65042
|
+
}
|
|
65043
|
+
|
|
65044
|
+
// src/features/locText.ts
|
|
65045
|
+
var MAX_DEPTH2 = 2;
|
|
65046
|
+
var NESTED_KEY = /\$([A-Za-z0-9_.\-']+)(?:\|[^$]*)?\$/g;
|
|
65047
|
+
var ICON_TAG = /^[a-z0-9_]+_i$/;
|
|
65048
|
+
var CONCEPT_LINK = /^([A-Za-z0-9_]+)\|[A-Za-z]+$/;
|
|
65049
|
+
var LOCALIZE_CALL = /^(?:Localize|Concept)\s*\(\s*'([^']*)'(?:\s*,\s*'([^']*)')?\s*\)$/;
|
|
65050
|
+
var SELECT_CALL = /^SelectLocalization\s*\(.*?,\s*'([^']*)'\s*,\s*'([^']*)'\s*\)$/s;
|
|
65051
|
+
var DEF_CHAIN = /^Get(\w+)\s*\(\s*'([^']+)'\s*\)\s*((?:\.\s*\w+\s*(?:\([^()]*\))?\s*)*)$/;
|
|
65052
|
+
var NAME_MEMBERS = /* @__PURE__ */ new Set(["GetName", "GetTypeName", "GetNameNoTooltip"]);
|
|
65053
|
+
var CONCEPT_KIND = "game_concept";
|
|
65054
|
+
function pascal(kind) {
|
|
65055
|
+
return kind.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
65056
|
+
}
|
|
65057
|
+
function patternsWithFallback(kind, deps) {
|
|
65058
|
+
const own = kind === null ? [] : deps.patternsOf(kind);
|
|
65059
|
+
return [.../* @__PURE__ */ new Set([...own, "$"])];
|
|
65060
|
+
}
|
|
65061
|
+
function locOfName(name, kind, deps) {
|
|
65062
|
+
for (const pattern of patternsWithFallback(kind, deps)) {
|
|
65063
|
+
const value = deps.loc(pattern.replace("$", name));
|
|
65064
|
+
if (value !== void 0 && value !== "") return value;
|
|
65065
|
+
}
|
|
65066
|
+
return void 0;
|
|
65067
|
+
}
|
|
65068
|
+
function candidateKinds(head, name, deps) {
|
|
65069
|
+
const kinds = deps.kindsOf(name);
|
|
65070
|
+
const named2 = kinds.filter((kind) => head.includes(pascal(kind)));
|
|
65071
|
+
const rest = kinds.filter((kind) => !named2.includes(kind));
|
|
65072
|
+
return [...named2, ...rest, null];
|
|
65073
|
+
}
|
|
65074
|
+
function inline(value, deps, depth) {
|
|
65075
|
+
if (depth + 1 >= MAX_DEPTH2) return { text: stripFormatting(value).trim(), resolved: true };
|
|
65076
|
+
return render2(value, deps, depth + 1);
|
|
65077
|
+
}
|
|
65078
|
+
function renderFn(fn, deps, depth) {
|
|
65079
|
+
const concept = CONCEPT_LINK.exec(fn.trim());
|
|
65080
|
+
if (concept) {
|
|
65081
|
+
const value = locOfName(concept[1], CONCEPT_KIND, deps);
|
|
65082
|
+
return value === void 0 ? { text: concept[1], resolved: false } : inline(value, deps, depth);
|
|
65083
|
+
}
|
|
65084
|
+
const source = fn.split("|")[0].trim();
|
|
65085
|
+
if (ICON_TAG.test(source)) return { text: "", resolved: true };
|
|
65086
|
+
const localize = LOCALIZE_CALL.exec(source);
|
|
65087
|
+
if (localize) {
|
|
65088
|
+
const key = localize[2] ?? localize[1];
|
|
65089
|
+
const value = deps.loc(key);
|
|
65090
|
+
return value === void 0 ? { text: key, resolved: false } : inline(value, deps, depth);
|
|
65091
|
+
}
|
|
65092
|
+
const select = SELECT_CALL.exec(source);
|
|
65093
|
+
if (select) {
|
|
65094
|
+
const value = deps.loc(select[1]);
|
|
65095
|
+
return value === void 0 ? { text: select[1], resolved: false } : inline(value, deps, depth);
|
|
65096
|
+
}
|
|
65097
|
+
const chain = DEF_CHAIN.exec(source);
|
|
65098
|
+
const members = chain ? [...chain[3].matchAll(/\.\s*(\w+)/g)].map((m) => m[1]) : [];
|
|
65099
|
+
if (chain && members.length > 0 && NAME_MEMBERS.has(members[members.length - 1])) {
|
|
65100
|
+
const name = chain[2];
|
|
65101
|
+
for (const kind of candidateKinds(chain[1], name, deps)) {
|
|
65102
|
+
const value = locOfName(name, kind, deps);
|
|
65103
|
+
if (value !== void 0) return inline(value, deps, depth);
|
|
65104
|
+
}
|
|
65105
|
+
return { text: name, resolved: false };
|
|
65106
|
+
}
|
|
65107
|
+
return { text: chipFor(source), resolved: false };
|
|
65108
|
+
}
|
|
65109
|
+
function substituteKeys(s2, deps, resolved) {
|
|
65110
|
+
return s2.replace(NESTED_KEY, (whole, key) => {
|
|
65111
|
+
const value = deps.loc(key);
|
|
65112
|
+
if (value === void 0) {
|
|
65113
|
+
resolved.ok = false;
|
|
65114
|
+
return whole;
|
|
65115
|
+
}
|
|
65116
|
+
return value;
|
|
65117
|
+
});
|
|
65118
|
+
}
|
|
65119
|
+
function render2(raw, deps, depth) {
|
|
65120
|
+
const state = { ok: true };
|
|
65121
|
+
const parts = tokenize2(substituteKeys(raw, deps, state)).map((part) => {
|
|
65122
|
+
if (part.fn === void 0) return { text: stripFormatting(part.literal ?? ""), resolved: true };
|
|
65123
|
+
const out = renderFn(part.fn, deps, depth);
|
|
65124
|
+
if (!out.resolved) state.ok = false;
|
|
65125
|
+
return out;
|
|
65126
|
+
});
|
|
65127
|
+
const text = parts.map((part) => part.text).join("").replace(/[ \t]{2,}/g, " ").trim();
|
|
65128
|
+
return { text, resolved: state.ok };
|
|
65129
|
+
}
|
|
65130
|
+
function renderLocValue(raw, deps) {
|
|
65131
|
+
const out = render2(raw, deps, 0);
|
|
65132
|
+
return { raw, text: out.text, resolved: out.resolved };
|
|
65133
|
+
}
|
|
65134
|
+
function computeLocText(keys, deps) {
|
|
65135
|
+
const values = {};
|
|
65136
|
+
for (const key of keys) {
|
|
65137
|
+
if (key in values) continue;
|
|
65138
|
+
const raw = deps.loc(key);
|
|
65139
|
+
if (raw === void 0) continue;
|
|
65140
|
+
values[key] = renderLocValue(raw, deps);
|
|
65141
|
+
}
|
|
65142
|
+
return { values };
|
|
65143
|
+
}
|
|
65144
|
+
|
|
63578
65145
|
// src/overview/dependencies.ts
|
|
63579
|
-
var
|
|
63580
|
-
var
|
|
65146
|
+
var fs35 = __toESM(require("fs"));
|
|
65147
|
+
var path35 = __toESM(require("path"));
|
|
63581
65148
|
var CALL_KINDS2 = /* @__PURE__ */ new Set(["scripted_effect", "scripted_trigger"]);
|
|
63582
65149
|
function computeDependencies(data2, schema2, name, kind, guiUses) {
|
|
63583
65150
|
const resolved = data2.index.lookup(name);
|
|
@@ -63598,7 +65165,7 @@ function collectDependents(data2, def) {
|
|
|
63598
65165
|
for (const site of sites) {
|
|
63599
65166
|
const container = containingDef(data2, site.file, site.line);
|
|
63600
65167
|
const groupKind = container ? container.kind : "file";
|
|
63601
|
-
const itemName = container ? container.name :
|
|
65168
|
+
const itemName = container ? container.name : path35.basename(site.file);
|
|
63602
65169
|
const dedupe = `${itemName} ${site.file}`;
|
|
63603
65170
|
let byItem = groups.get(groupKind);
|
|
63604
65171
|
if (!byItem) groups.set(groupKind, byItem = /* @__PURE__ */ new Map());
|
|
@@ -63612,7 +65179,7 @@ function scanCallSites(data2, def) {
|
|
|
63612
65179
|
for (const file of modFiles(data2)) {
|
|
63613
65180
|
let text;
|
|
63614
65181
|
try {
|
|
63615
|
-
text = decode(
|
|
65182
|
+
text = decode(fs35.readFileSync(file)).text;
|
|
63616
65183
|
} catch {
|
|
63617
65184
|
continue;
|
|
63618
65185
|
}
|
|
@@ -63649,7 +65216,7 @@ function containingDef(data2, file, line) {
|
|
|
63649
65216
|
function collectDependencies(data2, schema2, def) {
|
|
63650
65217
|
let text;
|
|
63651
65218
|
try {
|
|
63652
|
-
text = decode(
|
|
65219
|
+
text = decode(fs35.readFileSync(def.file)).text;
|
|
63653
65220
|
} catch {
|
|
63654
65221
|
return [];
|
|
63655
65222
|
}
|
|
@@ -63729,7 +65296,7 @@ if (process.argv.includes("--version") || process.argv.includes("-v")) {
|
|
|
63729
65296
|
process.exit(0);
|
|
63730
65297
|
}
|
|
63731
65298
|
var TRANSPORT_FLAGS = ["--node-ipc", "--stdio", "--socket", "--pipe"];
|
|
63732
|
-
if (!process.send && !process.argv.some((arg) => TRANSPORT_FLAGS.some((
|
|
65299
|
+
if (!process.send && !process.argv.some((arg) => TRANSPORT_FLAGS.some((flag2) => arg === flag2 || arg.startsWith(flag2 + "=")))) {
|
|
63733
65300
|
process.argv.push("--stdio");
|
|
63734
65301
|
}
|
|
63735
65302
|
var connection = (0, import_node17.createConnection)(import_node17.ProposedFeatures.all);
|
|
@@ -63949,8 +65516,8 @@ function clearPathCaches() {
|
|
|
63949
65516
|
}
|
|
63950
65517
|
function engineRoots() {
|
|
63951
65518
|
if (!settings.gamePath) return [];
|
|
63952
|
-
const jomini =
|
|
63953
|
-
return
|
|
65519
|
+
const jomini = path36.join(path36.dirname(settings.gamePath), "jomini");
|
|
65520
|
+
return fs36.existsSync(jomini) ? [jomini] : [];
|
|
63954
65521
|
}
|
|
63955
65522
|
function workspaceModRoots() {
|
|
63956
65523
|
const mods = [];
|
|
@@ -63965,6 +65532,21 @@ function workspaceRootOf(fsPath) {
|
|
|
63965
65532
|
if (settings.modPath && lower.startsWith(settings.modPath.toLowerCase())) return settings.modPath;
|
|
63966
65533
|
return workspaceModRoots().find((r) => lower.startsWith(r.toLowerCase())) ?? null;
|
|
63967
65534
|
}
|
|
65535
|
+
var calendarByRoot = /* @__PURE__ */ new Map();
|
|
65536
|
+
function calendarFor(fsPath) {
|
|
65537
|
+
const root = workspaceRootOf(fsPath);
|
|
65538
|
+
if (root) {
|
|
65539
|
+
const key = root.toLowerCase();
|
|
65540
|
+
let cached2 = calendarByRoot.get(key);
|
|
65541
|
+
if (cached2 === void 0) {
|
|
65542
|
+
const read = readCalendarFile(root, activeProfile());
|
|
65543
|
+
cached2 = read?.calendar ? { calendar: read.calendar, source: path36.relative(root, read.file).replace(/\\/g, "/") } : null;
|
|
65544
|
+
calendarByRoot.set(key, cached2);
|
|
65545
|
+
}
|
|
65546
|
+
if (cached2) return cached2;
|
|
65547
|
+
}
|
|
65548
|
+
return { calendar: settings.calendar, source: "px.calendar" };
|
|
65549
|
+
}
|
|
63968
65550
|
function schemaEntryForFile(fsPath) {
|
|
63969
65551
|
const lower = fsPath.toLowerCase();
|
|
63970
65552
|
for (const root of contentRoots()) {
|
|
@@ -64071,7 +65653,7 @@ function loadDocs(force) {
|
|
|
64071
65653
|
let modifierTemplates = [];
|
|
64072
65654
|
if (settings.logsPath) {
|
|
64073
65655
|
const t0 = Date.now();
|
|
64074
|
-
const docsCacheFile =
|
|
65656
|
+
const docsCacheFile = path36.join(storageDir, `docsCache${activeProfile().cacheSuffix}.json`);
|
|
64075
65657
|
const result = loadTokenData(settings.logsPath, docsCacheFile, force);
|
|
64076
65658
|
scriptTokens = result.tokens;
|
|
64077
65659
|
modifierTemplates = result.templates;
|
|
@@ -64087,7 +65669,7 @@ function loadDocs(force) {
|
|
|
64087
65669
|
}
|
|
64088
65670
|
if (scriptTokens.length === 0 && bundledDumpsDir) {
|
|
64089
65671
|
const t0 = Date.now();
|
|
64090
|
-
const cacheFile =
|
|
65672
|
+
const cacheFile = path36.join(storageDir, `docsCacheBundled${activeProfile().cacheSuffix}.json`);
|
|
64091
65673
|
const result = loadTokenData(bundledDumpsDir, cacheFile, force);
|
|
64092
65674
|
scriptTokens = result.tokens;
|
|
64093
65675
|
modifierTemplates = result.templates;
|
|
@@ -64115,13 +65697,13 @@ function loadDocs(force) {
|
|
|
64115
65697
|
log(
|
|
64116
65698
|
`wiki docs: ${wikiTokens.length} tokens, ${merged.enriched} usage examples merged in, ${merged.added} added${merged.dropped > 0 ? `, ${merged.dropped} dropped as absent from your script_docs` : ""}, total ${merged.tokens.length} (${Date.now() - t1}ms)`
|
|
64117
65699
|
);
|
|
64118
|
-
const onActionsDir = settings.logsPath &&
|
|
65700
|
+
const onActionsDir = settings.logsPath && fs36.existsSync(path36.join(settings.logsPath, "on_actions.log")) ? settings.logsPath : bundledDumpsDir || settings.logsPath;
|
|
64119
65701
|
data.onActionScopes = onActionsDir ? parseOnActionsLog(onActionsDir) : /* @__PURE__ */ new Map();
|
|
64120
65702
|
if (data.onActionScopes.size > 0) log(`on_actions.log: ${data.onActionScopes.size} on_action root scopes`);
|
|
64121
65703
|
const dataTypeDirs = [bundledDataTypesDir || null];
|
|
64122
65704
|
if (settings.logsPath) {
|
|
64123
|
-
const sibling =
|
|
64124
|
-
if (sibling.toLowerCase() !==
|
|
65705
|
+
const sibling = path36.resolve(settings.logsPath, "..", "logs");
|
|
65706
|
+
if (sibling.toLowerCase() !== path36.resolve(settings.logsPath).toLowerCase()) dataTypeDirs.push(sibling);
|
|
64125
65707
|
dataTypeDirs.push(settings.logsPath);
|
|
64126
65708
|
}
|
|
64127
65709
|
data.dataTypes = loadDataTypes(dataTypeDirs);
|
|
@@ -64141,7 +65723,7 @@ function loadDocs(force) {
|
|
|
64141
65723
|
log(`data types: ${data.dataTypes.count} entries incl. data-type dumps`);
|
|
64142
65724
|
}
|
|
64143
65725
|
const t2 = Date.now();
|
|
64144
|
-
const usageCache = storageDir ?
|
|
65726
|
+
const usageCache = storageDir ? path36.join(storageDir, `dataFnUsage${activeProfile().cacheSuffix}.json`) : null;
|
|
64145
65727
|
const generation = ++usageGeneration;
|
|
64146
65728
|
void loadDataFnUsageAsync(settings.gamePath, settings.locLanguage, usageCache, force).then((result) => {
|
|
64147
65729
|
if (generation !== usageGeneration) return;
|
|
@@ -64189,7 +65771,7 @@ function harvestEngineData() {
|
|
|
64189
65771
|
var yieldNow2 = () => new Promise((resolve2) => setImmediate(resolve2));
|
|
64190
65772
|
function readFileStripBom(file) {
|
|
64191
65773
|
try {
|
|
64192
|
-
return
|
|
65774
|
+
return fs36.readFileSync(file, "utf8").replace(/^/, "");
|
|
64193
65775
|
} catch {
|
|
64194
65776
|
return null;
|
|
64195
65777
|
}
|
|
@@ -64204,7 +65786,7 @@ async function readBatchStripBom(files) {
|
|
|
64204
65786
|
const i = next++;
|
|
64205
65787
|
if (i >= files.length) return;
|
|
64206
65788
|
try {
|
|
64207
|
-
const content = await
|
|
65789
|
+
const content = await fs36.promises.readFile(files[i], "utf8");
|
|
64208
65790
|
out[i] = content.replace(/^/, "");
|
|
64209
65791
|
} catch {
|
|
64210
65792
|
out[i] = null;
|
|
@@ -64221,7 +65803,7 @@ async function scanRootChunked(root, source, generation, onProgress) {
|
|
|
64221
65803
|
const work = [];
|
|
64222
65804
|
let totalFiles = 0;
|
|
64223
65805
|
for (const entry of schema.entries) {
|
|
64224
|
-
const dir =
|
|
65806
|
+
const dir = path36.join(root, ...entry.path.split("/"));
|
|
64225
65807
|
let files = [];
|
|
64226
65808
|
for (const file of iterFiles(dir, entry.ext ?? ".txt")) {
|
|
64227
65809
|
if (file === null) {
|
|
@@ -64232,12 +65814,12 @@ async function scanRootChunked(root, source, generation, onProgress) {
|
|
|
64232
65814
|
}
|
|
64233
65815
|
}
|
|
64234
65816
|
if (entry.kind === "loc_key") {
|
|
64235
|
-
files = files.filter((f) => isWantedLocFile(
|
|
65817
|
+
files = files.filter((f) => isWantedLocFile(path36.relative(root, f), settings.locLanguage));
|
|
64236
65818
|
}
|
|
64237
65819
|
work.push({ entry, files });
|
|
64238
65820
|
totalFiles += files.length;
|
|
64239
65821
|
}
|
|
64240
|
-
perf(`scan ${
|
|
65822
|
+
perf(`scan ${path36.basename(root)} listed ${totalFiles} files ${Date.now() - tList}ms`);
|
|
64241
65823
|
const tRead = Date.now();
|
|
64242
65824
|
let done = 0;
|
|
64243
65825
|
const BATCH3 = 150;
|
|
@@ -64257,7 +65839,7 @@ async function scanRootChunked(root, source, generation, onProgress) {
|
|
|
64257
65839
|
}
|
|
64258
65840
|
}
|
|
64259
65841
|
perf(
|
|
64260
|
-
`scan ${
|
|
65842
|
+
`scan ${path36.basename(root)} (${source}) read+extract ${defs.length} defs from ${totalFiles} files ${Date.now() - tRead}ms`
|
|
64261
65843
|
);
|
|
64262
65844
|
return defs;
|
|
64263
65845
|
}
|
|
@@ -64280,12 +65862,12 @@ async function scanModRootBoth(root, generation) {
|
|
|
64280
65862
|
data.index.addAll(result.defs);
|
|
64281
65863
|
if (result.implicitDefs.length > 0) data.index.addAll(result.implicitDefs);
|
|
64282
65864
|
rebuildModNamespaces();
|
|
64283
|
-
perf(`scan ${
|
|
65865
|
+
perf(`scan ${path36.basename(root)} listed ${result.files} files ${result.listMs}ms`);
|
|
64284
65866
|
perf(
|
|
64285
|
-
`scan ${
|
|
65867
|
+
`scan ${path36.basename(root)} (mod) read+extract ${result.defs.length} defs and ${result.references} refs from ${result.files} files ${Date.now() - t0 - result.listMs}ms`
|
|
64286
65868
|
);
|
|
64287
65869
|
log(
|
|
64288
|
-
`indexed ${
|
|
65870
|
+
`indexed ${path36.basename(root)} references: ${result.references} usage sites in ${result.scriptFiles} files (${Date.now() - t0}ms)`
|
|
64289
65871
|
);
|
|
64290
65872
|
return result.defs.length;
|
|
64291
65873
|
}
|
|
@@ -64296,16 +65878,16 @@ function rebuildModNamespaces() {
|
|
|
64296
65878
|
}
|
|
64297
65879
|
}
|
|
64298
65880
|
function readPlayset(modPath) {
|
|
64299
|
-
const file =
|
|
65881
|
+
const file = path36.join(resolveConfigDir(modPath, activeProfile()), "playset.json");
|
|
64300
65882
|
try {
|
|
64301
|
-
if (!
|
|
64302
|
-
const parsed = JSON.parse(
|
|
65883
|
+
if (!fs36.existsSync(file)) return [];
|
|
65884
|
+
const parsed = JSON.parse(fs36.readFileSync(file, "utf8"));
|
|
64303
65885
|
const list2 = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.parents) ? parsed.parents : [];
|
|
64304
65886
|
const roots = [];
|
|
64305
65887
|
for (const p of list2) {
|
|
64306
65888
|
if (typeof p !== "string") continue;
|
|
64307
|
-
const abs =
|
|
64308
|
-
if (
|
|
65889
|
+
const abs = path36.isAbsolute(p) ? p : path36.join(modPath, p);
|
|
65890
|
+
if (fs36.existsSync(abs)) roots.push(abs);
|
|
64309
65891
|
else log(`playset parent not found, skipped: ${p}`);
|
|
64310
65892
|
}
|
|
64311
65893
|
return roots;
|
|
@@ -64318,6 +65900,7 @@ async function buildIndex() {
|
|
|
64318
65900
|
const tBuild = Date.now();
|
|
64319
65901
|
const generation = ++scanGeneration;
|
|
64320
65902
|
clearPathCaches();
|
|
65903
|
+
calendarByRoot.clear();
|
|
64321
65904
|
schema = loadSchema([...settings.modPath ? [settings.modPath] : [], ...workspaceModRoots()], log);
|
|
64322
65905
|
data.completableKinds = /* @__PURE__ */ new Set([
|
|
64323
65906
|
...schema.entries.filter((e) => e.completable !== false).map((e) => e.kind),
|
|
@@ -64341,34 +65924,34 @@ async function buildIndex() {
|
|
|
64341
65924
|
try {
|
|
64342
65925
|
if (settings.modPath) {
|
|
64343
65926
|
const t0 = Date.now();
|
|
64344
|
-
const
|
|
64345
|
-
if (
|
|
65927
|
+
const count2 = await scanModRootBoth(settings.modPath, generation);
|
|
65928
|
+
if (count2 === null) return;
|
|
64346
65929
|
indexChanged("mod scan");
|
|
64347
|
-
log(`indexed mod: ${
|
|
65930
|
+
log(`indexed mod: ${count2} definitions (${Date.now() - t0}ms)`);
|
|
64348
65931
|
}
|
|
64349
65932
|
const wsMods = new Set(workspaceModRoots().map((r) => r.toLowerCase()));
|
|
64350
65933
|
for (const parent of parentRoots()) {
|
|
64351
65934
|
const t1 = Date.now();
|
|
64352
65935
|
const isWorkspaceMod = wsMods.has(parent.toLowerCase());
|
|
64353
|
-
let
|
|
65936
|
+
let count2;
|
|
64354
65937
|
if (isWorkspaceMod) {
|
|
64355
|
-
|
|
65938
|
+
count2 = await scanModRootBoth(parent, generation);
|
|
64356
65939
|
} else {
|
|
64357
65940
|
const parentDefs = await scanRootChunked(parent, "parent", generation);
|
|
64358
|
-
|
|
65941
|
+
count2 = parentDefs === null ? null : parentDefs.length;
|
|
64359
65942
|
if (parentDefs !== null) data.index.addAll(parentDefs);
|
|
64360
65943
|
}
|
|
64361
|
-
if (
|
|
64362
|
-
indexChanged(`parent scan ${
|
|
65944
|
+
if (count2 === null) return;
|
|
65945
|
+
indexChanged(`parent scan ${path36.basename(parent)}`);
|
|
64363
65946
|
log(
|
|
64364
|
-
`indexed ${isWorkspaceMod ? "workspace mod" : "parent mod"} ${
|
|
65947
|
+
`indexed ${isWorkspaceMod ? "workspace mod" : "parent mod"} ${path36.basename(parent)}: ${count2} definitions (${Date.now() - t1}ms)`
|
|
64365
65948
|
);
|
|
64366
65949
|
}
|
|
64367
65950
|
if (settings.gamePath) {
|
|
64368
65951
|
const gamePath = settings.gamePath;
|
|
64369
65952
|
const t0 = Date.now();
|
|
64370
65953
|
const version2 = detectGameVersion(gamePath);
|
|
64371
|
-
const cacheFile =
|
|
65954
|
+
const cacheFile = path36.join(
|
|
64372
65955
|
storageDir,
|
|
64373
65956
|
`vanillaIndex${activeProfile().cacheSuffix}-${settings.locLanguage}.json`
|
|
64374
65957
|
);
|
|
@@ -64455,13 +66038,13 @@ function rescanModFile(fsPath) {
|
|
|
64455
66038
|
const entry = classifyFile(root, fsPath, schema.entries);
|
|
64456
66039
|
const isScript = lower.endsWith(".txt");
|
|
64457
66040
|
if (!entry && !isScript) return;
|
|
64458
|
-
if (entry?.kind === "loc_key" && !isWantedLocFile(
|
|
66041
|
+
if (entry?.kind === "loc_key" && !isWantedLocFile(path36.relative(root, fsPath), settings.locLanguage))
|
|
64459
66042
|
return;
|
|
64460
66043
|
const tParse = Date.now();
|
|
64461
|
-
const content =
|
|
66044
|
+
const content = fs36.existsSync(fsPath) ? readFileStripBom(fsPath) : null;
|
|
64462
66045
|
const digest = contentDigest(content);
|
|
64463
66046
|
if (rescanDigests.get(lower) === digest) {
|
|
64464
|
-
perf(`rescan ${
|
|
66047
|
+
perf(`rescan ${path36.basename(fsPath)} unchanged bytes, skipped ${Date.now() - tParse}ms`);
|
|
64465
66048
|
return;
|
|
64466
66049
|
}
|
|
64467
66050
|
rescanDigests.set(lower, digest);
|
|
@@ -64488,22 +66071,22 @@ function rescanModFile(fsPath) {
|
|
|
64488
66071
|
}
|
|
64489
66072
|
perfSpan("rescan namespaces", () => rebuildModNamespaces());
|
|
64490
66073
|
}
|
|
64491
|
-
perf(`rescan ${
|
|
64492
|
-
indexChanged(`rescan ${
|
|
64493
|
-
log(`re-indexed ${
|
|
66074
|
+
perf(`rescan ${path36.basename(fsPath)} parse+extract ${Date.now() - tParse}ms`);
|
|
66075
|
+
indexChanged(`rescan ${path36.basename(fsPath)}`);
|
|
66076
|
+
log(`re-indexed ${path36.basename(fsPath)}`);
|
|
64494
66077
|
}
|
|
64495
66078
|
function deriveBundledDataDirs() {
|
|
64496
|
-
const gameDir =
|
|
66079
|
+
const gameDir = path36.join(clientDataDir || path36.resolve(__dirname, "..", "data"), activeProfile().id);
|
|
64497
66080
|
wikidocsDir = clientWikidocsDir;
|
|
64498
66081
|
if (!wikidocsDir) {
|
|
64499
|
-
const bundled =
|
|
64500
|
-
if (
|
|
66082
|
+
const bundled = path36.join(gameDir, "wikidocs");
|
|
66083
|
+
if (fs36.existsSync(bundled)) wikidocsDir = bundled;
|
|
64501
66084
|
}
|
|
64502
|
-
freqsDir =
|
|
64503
|
-
const dumps =
|
|
64504
|
-
bundledDumpsDir =
|
|
64505
|
-
const dataTypes =
|
|
64506
|
-
bundledDataTypesDir =
|
|
66085
|
+
freqsDir = fs36.existsSync(path36.join(gameDir, "freqs.json")) ? gameDir : "";
|
|
66086
|
+
const dumps = path36.join(gameDir, "script_docs");
|
|
66087
|
+
bundledDumpsDir = fs36.existsSync(dumps) ? dumps : "";
|
|
66088
|
+
const dataTypes = path36.join(gameDir, "data_types");
|
|
66089
|
+
bundledDataTypesDir = fs36.existsSync(dataTypes) ? dataTypes : "";
|
|
64507
66090
|
}
|
|
64508
66091
|
var clientDataDir = "";
|
|
64509
66092
|
var clientWikidocsDir = "";
|
|
@@ -64526,9 +66109,9 @@ connection.onInitialize((params) => {
|
|
|
64526
66109
|
setActiveProfile(resolveProfile(settings.gameId));
|
|
64527
66110
|
deriveBundledDataDirs();
|
|
64528
66111
|
if (!storageDir) {
|
|
64529
|
-
storageDir =
|
|
66112
|
+
storageDir = path36.join(os.tmpdir(), "px-lsp");
|
|
64530
66113
|
try {
|
|
64531
|
-
|
|
66114
|
+
fs36.mkdirSync(storageDir, { recursive: true });
|
|
64532
66115
|
} catch {
|
|
64533
66116
|
storageDir = "";
|
|
64534
66117
|
}
|
|
@@ -64576,7 +66159,11 @@ connection.onInitialized(() => {
|
|
|
64576
66159
|
}
|
|
64577
66160
|
if (!clientOwnFileWatcher && clientWatchedFilesDynamic) {
|
|
64578
66161
|
void connection.client.register(import_node17.DidChangeWatchedFilesNotification.type, {
|
|
64579
|
-
watchers: [
|
|
66162
|
+
watchers: [
|
|
66163
|
+
{ globPattern: "**/*.{txt,yml,gui,mod}" },
|
|
66164
|
+
{ globPattern: "**/metadata.json" },
|
|
66165
|
+
{ globPattern: "**/calendar.json" }
|
|
66166
|
+
]
|
|
64580
66167
|
});
|
|
64581
66168
|
}
|
|
64582
66169
|
applyFreqs();
|
|
@@ -64643,7 +66230,7 @@ function indexRead(label, fn) {
|
|
|
64643
66230
|
}
|
|
64644
66231
|
function mentionsTextFormatting(fsPath) {
|
|
64645
66232
|
try {
|
|
64646
|
-
return
|
|
66233
|
+
return fs36.readFileSync(fsPath, "utf8").includes("textformatting");
|
|
64647
66234
|
} catch {
|
|
64648
66235
|
return false;
|
|
64649
66236
|
}
|
|
@@ -64653,6 +66240,7 @@ function applyModFileChange(fsPath) {
|
|
|
64653
66240
|
const lower = fsPath.toLowerCase();
|
|
64654
66241
|
if (lower.endsWith(".mod") || lower.endsWith("metadata.json")) refreshModOrigin();
|
|
64655
66242
|
if (lower.endsWith(".gui")) invalidateGuiDefsCache();
|
|
66243
|
+
if (isCalendarFile(fsPath, activeProfile())) calendarByRoot.clear();
|
|
64656
66244
|
if (lower.replace(/\\/g, "/").includes("common/defines/") || lower.endsWith(".gui") && mentionsTextFormatting(fsPath))
|
|
64657
66245
|
harvestEngineData();
|
|
64658
66246
|
}
|
|
@@ -64680,6 +66268,10 @@ connection.onRequest(
|
|
|
64680
66268
|
eventGraphRequest,
|
|
64681
66269
|
(params) => computeEventGraph(data, params ?? {}, focusFilter(params?.modRoot))
|
|
64682
66270
|
);
|
|
66271
|
+
connection.onRequest(
|
|
66272
|
+
dynastyTreeRequest,
|
|
66273
|
+
(params) => computeDynastyTree(data, params ?? {}, focusFilter(params?.modRoot))
|
|
66274
|
+
);
|
|
64683
66275
|
connection.onRequest(
|
|
64684
66276
|
eventVocabularyRequest,
|
|
64685
66277
|
(params) => computeEventVocabulary(data, schema, focusFilter(params?.modRoot))
|
|
@@ -64692,6 +66284,18 @@ connection.onRequest(
|
|
|
64692
66284
|
eventBannerRequest,
|
|
64693
66285
|
(params) => computeEventBanner(data, params?.theme ?? "")
|
|
64694
66286
|
);
|
|
66287
|
+
connection.onRequest(
|
|
66288
|
+
definitionFormRequest,
|
|
66289
|
+
(params) => computeDefinitionForm(data, schema, params ?? { kind: "" }, focusFilter(params?.modRoot))
|
|
66290
|
+
);
|
|
66291
|
+
connection.onRequest(
|
|
66292
|
+
definitionEditRequest,
|
|
66293
|
+
(params) => computeDefinitionEdits(params)
|
|
66294
|
+
);
|
|
66295
|
+
connection.onRequest(
|
|
66296
|
+
modifierFormatsRequest,
|
|
66297
|
+
(params) => computeModifierFormats(data, activeProfile().modifierFormats, settings.gamePath, params?.lines)
|
|
66298
|
+
);
|
|
64695
66299
|
connection.onRequest(guiTreeRequest, (params) => buildGuiTree(params.text ?? ""));
|
|
64696
66300
|
function locValue(key) {
|
|
64697
66301
|
return data.index.lookup(key).find((d) => d.kind === "loc_key" && d.value !== void 0)?.value;
|
|
@@ -64759,7 +66363,7 @@ connection.onRequest(
|
|
|
64759
66363
|
const file = params?.path ?? "";
|
|
64760
66364
|
let key = file;
|
|
64761
66365
|
try {
|
|
64762
|
-
key = `${file}:${
|
|
66366
|
+
key = `${file}:${fs36.statSync(file).mtimeMs}`;
|
|
64763
66367
|
} catch {
|
|
64764
66368
|
}
|
|
64765
66369
|
if (saveValues?.key === key) return saveValues.result;
|
|
@@ -64818,9 +66422,43 @@ connection.onRequest(scopeAtRequest, (params) => {
|
|
|
64818
66422
|
entry
|
|
64819
66423
|
);
|
|
64820
66424
|
});
|
|
66425
|
+
connection.onRequest(snippetsRequest, (params) => {
|
|
66426
|
+
const doc = params?.uri ? documents.get(params.uri) : void 0;
|
|
66427
|
+
if (!doc || !isScriptLanguage(doc.languageId) || !params.position) return { snippets: [] };
|
|
66428
|
+
const entry = schemaEntryForFile(URI2.parse(doc.uri).fsPath);
|
|
66429
|
+
const { result } = getParse(doc);
|
|
66430
|
+
return {
|
|
66431
|
+
snippets: buildSnippetList(
|
|
66432
|
+
result,
|
|
66433
|
+
doc.offsetAt(params.position),
|
|
66434
|
+
entry?.kind ?? null,
|
|
66435
|
+
activeProfile().skeletons,
|
|
66436
|
+
data.tokens,
|
|
66437
|
+
freqs.tokens
|
|
66438
|
+
)
|
|
66439
|
+
};
|
|
66440
|
+
});
|
|
64821
66441
|
connection.onRequest(lookupLocRequest, (params) => {
|
|
64822
66442
|
return data.index.lookup(params.key).filter((d) => d.kind === "loc_key").map((d) => ({ file: d.file, line: d.line, source: d.source, value: d.value }));
|
|
64823
66443
|
});
|
|
66444
|
+
function locTextDeps() {
|
|
66445
|
+
return {
|
|
66446
|
+
loc: locValue,
|
|
66447
|
+
kindsOf: (name) => [
|
|
66448
|
+
...new Set(
|
|
66449
|
+
data.index.lookup(name).filter((d) => d.kind !== "loc_key").map((d) => d.kind)
|
|
66450
|
+
)
|
|
66451
|
+
],
|
|
66452
|
+
patternsOf: (kind) => {
|
|
66453
|
+
const entry = schema.entries.find((e) => e.kind === kind);
|
|
66454
|
+
return [entry?.requiredLoc?.[0], entry?.locPatterns?.[0]].filter((p) => !!p);
|
|
66455
|
+
}
|
|
66456
|
+
};
|
|
66457
|
+
}
|
|
66458
|
+
connection.onRequest(
|
|
66459
|
+
locTextRequest,
|
|
66460
|
+
(params) => computeLocText(params?.keys ?? [], locTextDeps())
|
|
66461
|
+
);
|
|
64824
66462
|
connection.onCompletion(
|
|
64825
66463
|
(params) => indexRead(`completion ${perfName(params.textDocument.uri)}`, () => {
|
|
64826
66464
|
const doc = documents.get(params.textDocument.uri);
|
|
@@ -64883,7 +66521,8 @@ connection.onHover(
|
|
|
64883
66521
|
if (!isScriptLanguage(doc.languageId)) return null;
|
|
64884
66522
|
const fsPath = URI2.parse(doc.uri).fsPath;
|
|
64885
66523
|
const entry = schemaEntryForFile(fsPath);
|
|
64886
|
-
const
|
|
66524
|
+
const { calendar, source } = calendarFor(fsPath);
|
|
66525
|
+
const dateHover = provideDateHover(calendar, doc, params.position, source);
|
|
64887
66526
|
if (dateHover) return dateHover;
|
|
64888
66527
|
const texture = provideTextureHover(settings, doc, params.position, entry?.kind);
|
|
64889
66528
|
if (texture) return texture;
|
|
@@ -64958,9 +66597,18 @@ connection.languages.inlayHint.on(
|
|
|
64958
66597
|
(params) => indexRead(`inlayHint ${perfName(params.textDocument.uri)}`, () => {
|
|
64959
66598
|
const doc = documents.get(params.textDocument.uri);
|
|
64960
66599
|
if (!doc) return [];
|
|
64961
|
-
const
|
|
66600
|
+
const fsPath = URI2.parse(doc.uri).fsPath;
|
|
66601
|
+
const entry = schemaEntryForFile(fsPath);
|
|
64962
66602
|
const rootScopes = entry?.rootScopes?.length ? new Set(entry.rootScopes.map((s2) => s2.toLowerCase())) : null;
|
|
64963
|
-
return provideInlayHints(
|
|
66603
|
+
return provideInlayHints(
|
|
66604
|
+
data,
|
|
66605
|
+
settings,
|
|
66606
|
+
doc,
|
|
66607
|
+
params.range,
|
|
66608
|
+
rootScopes,
|
|
66609
|
+
entry,
|
|
66610
|
+
calendarFor(fsPath).calendar
|
|
66611
|
+
);
|
|
64964
66612
|
})
|
|
64965
66613
|
);
|
|
64966
66614
|
connection.languages.semanticTokens.on(
|
|
@@ -65035,13 +66683,13 @@ var validatedAt = /* @__PURE__ */ new Map();
|
|
|
65035
66683
|
function readBomFromDisk(uri) {
|
|
65036
66684
|
try {
|
|
65037
66685
|
const fsPath = URI2.parse(uri).fsPath;
|
|
65038
|
-
const fd =
|
|
66686
|
+
const fd = fs36.openSync(fsPath, "r");
|
|
65039
66687
|
try {
|
|
65040
66688
|
const buf = Buffer.alloc(3);
|
|
65041
|
-
const n =
|
|
66689
|
+
const n = fs36.readSync(fd, buf, 0, 3, 0);
|
|
65042
66690
|
return n >= 3 && buf[0] === 239 && buf[1] === 187 && buf[2] === 191;
|
|
65043
66691
|
} finally {
|
|
65044
|
-
|
|
66692
|
+
fs36.closeSync(fd);
|
|
65045
66693
|
}
|
|
65046
66694
|
} catch {
|
|
65047
66695
|
return null;
|
|
@@ -65106,11 +66754,11 @@ function filterSuppressed(diagnostics, fsPath, text) {
|
|
|
65106
66754
|
ignorePatterns: settings.diagnosticsIgnorePatterns
|
|
65107
66755
|
};
|
|
65108
66756
|
const rel = relForPatterns(fsPath);
|
|
65109
|
-
const
|
|
66757
|
+
const inline2 = scanInlineSuppressions(text);
|
|
65110
66758
|
return diagnostics.filter((d) => {
|
|
65111
66759
|
const code = typeof d.code === "string" ? d.code : d.code !== void 0 ? String(d.code) : void 0;
|
|
65112
66760
|
if (isIgnoredByConfig(cfg, code, rel)) return false;
|
|
65113
|
-
if (isSuppressedInline(
|
|
66761
|
+
if (isSuppressedInline(inline2, d.range.start.line, code)) return false;
|
|
65114
66762
|
return true;
|
|
65115
66763
|
});
|
|
65116
66764
|
}
|