@px-lsp/server 0.1.0
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/LICENSE +674 -0
- package/README.md +334 -0
- package/THIRD-PARTY-NOTICES.md +83 -0
- package/data/ck3/dataTypes.json +2195 -0
- package/data/ck3/data_types/data_types_common.txt +2040 -0
- package/data/ck3/data_types/data_types_gui.txt +5264 -0
- package/data/ck3/data_types/data_types_internalclausewitzgui.txt +14843 -0
- package/data/ck3/data_types/data_types_script.txt +4251 -0
- package/data/ck3/data_types/data_types_uncategorized.txt +109984 -0
- package/data/ck3/freqs.json +1 -0
- package/data/ck3/guiSchema.json +6344 -0
- package/data/ck3/script_docs/effects.log +16059 -0
- package/data/ck3/script_docs/event_targets.log +2098 -0
- package/data/ck3/script_docs/modifiers.log +2228 -0
- package/data/ck3/script_docs/on_actions.log +5275 -0
- package/data/ck3/script_docs/triggers.log +11991 -0
- package/data/ck3/structures.json +9743 -0
- package/data/ck3/wikidocs/ATTRIBUTION.md +18 -0
- package/data/ck3/wikidocs/Data_types.md +2568 -0
- package/data/ck3/wikidocs/Effects_list.md +1176 -0
- package/data/ck3/wikidocs/Scopes_list.md +341 -0
- package/data/ck3/wikidocs/Triggers_list.md +1097 -0
- package/data/eu5/data_types/data_types_common.txt +2087 -0
- package/data/eu5/data_types/data_types_gui.txt +6732 -0
- package/data/eu5/data_types/data_types_internalclausewitzgui.txt +19276 -0
- package/data/eu5/data_types/data_types_script.txt +5688 -0
- package/data/eu5/data_types/data_types_uncategorized.txt +135569 -0
- package/data/vic3/data_types/data_types_common.txt +2021 -0
- package/data/vic3/data_types/data_types_gui.txt +5592 -0
- package/data/vic3/data_types/data_types_internalclausewitzgui.txt +17304 -0
- package/data/vic3/data_types/data_types_script.txt +2817 -0
- package/data/vic3/data_types/data_types_uncategorized.txt +84354 -0
- package/data/vic3/freqs.json +1 -0
- package/data/vic3/guiSchema.json +5578 -0
- package/data/vic3/script_docs/effects.log +38135 -0
- package/data/vic3/script_docs/event_targets.log +2028 -0
- package/data/vic3/script_docs/modifiers.log +18954 -0
- package/data/vic3/script_docs/on_actions.log +1561 -0
- package/data/vic3/script_docs/triggers.log +15738 -0
- package/data/vic3/structures.json +10189 -0
- package/dist/server.js +63668 -0
- package/media/px-lsp.svg +12 -0
- package/package.json +50 -0
- package/src/clientMode.ts +60 -0
- package/src/coa/coa.ts +184 -0
- package/src/coa/coaParse.ts +267 -0
- package/src/context.ts +78 -0
- package/src/contextKeywords.ts +224 -0
- package/src/data/dataBindingMacros.ts +82 -0
- package/src/data/dataFnDocs.ts +152 -0
- package/src/data/dataFnUsage.ts +431 -0
- package/src/data/dataTypes.ts +279 -0
- package/src/data/defines.ts +123 -0
- package/src/data/docsParser.ts +453 -0
- package/src/data/keywordDocs.ts +98 -0
- package/src/data/modifierTemplates.ts +143 -0
- package/src/data/textFormatting.ts +165 -0
- package/src/data/wikiDocs.ts +187 -0
- package/src/dds/decoder.ts +1007 -0
- package/src/dds/encode.ts +235 -0
- package/src/dds/index.ts +58 -0
- package/src/dds/png.ts +96 -0
- package/src/dds/tga.ts +62 -0
- package/src/documents.ts +35 -0
- package/src/features/assetPaths.ts +169 -0
- package/src/features/codeActions.ts +148 -0
- package/src/features/colors.ts +244 -0
- package/src/features/completion.ts +961 -0
- package/src/features/datafunction.ts +729 -0
- package/src/features/definition.ts +84 -0
- package/src/features/diagnostics.ts +244 -0
- package/src/features/folding.ts +106 -0
- package/src/features/formatting.ts +60 -0
- package/src/features/guiLanguage.ts +366 -0
- package/src/features/guiNavigation.ts +140 -0
- package/src/features/guiTree.ts +97 -0
- package/src/features/hover.ts +817 -0
- package/src/features/hoverRender.ts +222 -0
- package/src/features/inlayHints.ts +147 -0
- package/src/features/locFormatting.ts +127 -0
- package/src/features/references.ts +70 -0
- package/src/features/rename.ts +135 -0
- package/src/features/scopeAt.ts +65 -0
- package/src/features/semanticTokens.ts +188 -0
- package/src/features/signatureHelp.ts +72 -0
- package/src/features/symbols.ts +241 -0
- package/src/features/textureHover.ts +143 -0
- package/src/features/workspaceSymbols.ts +69 -0
- package/src/games/active.ts +19 -0
- package/src/games/ck3/ambientScopes.ts +273 -0
- package/src/games/ck3/index.ts +38 -0
- package/src/games/ck3/meta.ts +28 -0
- package/src/games/ck3/modifierPlaceholders.ts +61 -0
- package/src/games/ck3/saveSchema.ts +134 -0
- package/src/games/ck3/scaffolds.ts +197 -0
- package/src/games/ck3/schema.ts +422 -0
- package/src/games/ck3/structures.ts +887 -0
- package/src/games/eu5/index.ts +75 -0
- package/src/games/eu5/meta.ts +44 -0
- package/src/games/eu5/scaffolds.ts +49 -0
- package/src/games/eu5/schema.generated.ts +1043 -0
- package/src/games/jomini/variables.ts +134 -0
- package/src/games/profile.ts +205 -0
- package/src/games/registry.ts +27 -0
- package/src/games/vic3/index.ts +52 -0
- package/src/games/vic3/meta.ts +55 -0
- package/src/games/vic3/saveSchema.ts +77 -0
- package/src/games/vic3/scaffolds.ts +135 -0
- package/src/games/vic3/schema.ts +650 -0
- package/src/games/vic3/structures.ts +33 -0
- package/src/gui/anchorSpec.ts +66 -0
- package/src/gui/declMarkers.ts +30 -0
- package/src/gui/fillGeometry.ts +101 -0
- package/src/gui/guiDefs.ts +386 -0
- package/src/gui/guiDependencies.ts +352 -0
- package/src/gui/guiLinks.ts +64 -0
- package/src/gui/layoutEngine.ts +1998 -0
- package/src/gui/layoutService.ts +221 -0
- package/src/gui/measuredMetrics.ts +21 -0
- package/src/gui/previewService.ts +89 -0
- package/src/gui/saveSchema.ts +220 -0
- package/src/gui/saveValues.ts +399 -0
- package/src/gui/saveZip.ts +60 -0
- package/src/gui/sourceEdit.ts +535 -0
- package/src/gui/sourceEditService.ts +439 -0
- package/src/gui/sourceModel.ts +603 -0
- package/src/gui/textResolve.ts +145 -0
- package/src/gui/textureInfo.ts +106 -0
- package/src/gui/vocabulary.ts +149 -0
- package/src/gui/widgetEdit.ts +52 -0
- package/src/gui/widgetInfo.ts +245 -0
- package/src/index/docComments.ts +103 -0
- package/src/index/extract.ts +252 -0
- package/src/index/indexer.ts +369 -0
- package/src/index/intern.ts +101 -0
- package/src/index/lazyRefs.ts +145 -0
- package/src/index/modOrigin.ts +69 -0
- package/src/index/references.ts +534 -0
- package/src/overview/dependencies.ts +240 -0
- package/src/overview/eventBanner.ts +95 -0
- package/src/overview/eventDetail.ts +482 -0
- package/src/overview/eventGraph.ts +617 -0
- package/src/overview/eventVocabulary.ts +214 -0
- package/src/overview/locCoverage.ts +138 -0
- package/src/overview/modOverview.ts +29 -0
- package/src/overview/overrides.ts +89 -0
- package/src/parseCache.ts +81 -0
- package/src/parser/cst.ts +257 -0
- package/src/parser/encoding.ts +106 -0
- package/src/parser/index.ts +7 -0
- package/src/parser/lexer.ts +245 -0
- package/src/parser/locParser.ts +276 -0
- package/src/parser/parser.ts +360 -0
- package/src/schema/freqs.ts +70 -0
- package/src/schema/loader.ts +113 -0
- package/src/schema/types.ts +142 -0
- package/src/scopes/inference.ts +478 -0
- package/src/scopes/model.ts +148 -0
- package/src/scopes/varTypes.ts +290 -0
- package/src/server.ts +1894 -0
- package/src/serverData.ts +98 -0
- package/src/structure.ts +56 -0
- package/src/wordAt.ts +49 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient (engine-provided) saved scopes per definition kind (update plan v1.1
|
|
3
|
+
* §B3). These names are referenced via `scope:x` but are never `save_scope_as`'d
|
|
4
|
+
* in script — the engine binds them — so a save-site index can't explain them.
|
|
5
|
+
*
|
|
6
|
+
* SOURCE: hand-curated from the game's `_*.info` files (2026-07 scope audit:
|
|
7
|
+
* every folder's documented `scope:<name>` lines were swept and typed). Scope
|
|
8
|
+
* type names are the canonical ones from event_scopes.log. Some ambient scopes
|
|
9
|
+
* only exist in specific blocks of the kind; per AD-5 they are offered for the
|
|
10
|
+
* whole file (rank/annotate, never hide) with the block noted in the doc.
|
|
11
|
+
*/
|
|
12
|
+
import type { AmbientScope } from "../../schema/types";
|
|
13
|
+
|
|
14
|
+
const CHAR = "character";
|
|
15
|
+
|
|
16
|
+
function s(name: string, type: string, doc: string): AmbientScope {
|
|
17
|
+
return { name, type, doc };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Ambient scopes keyed by schema kind. */
|
|
21
|
+
export const AMBIENT_SCOPES: Record<string, AmbientScope[]> = {
|
|
22
|
+
// common/character_interactions/_character_interactions.info
|
|
23
|
+
character_interaction: [
|
|
24
|
+
s("actor", CHAR, "The character sending the interaction (the initiator)."),
|
|
25
|
+
s("recipient", CHAR, "The character receiving the interaction."),
|
|
26
|
+
s(
|
|
27
|
+
"secondary_actor",
|
|
28
|
+
CHAR,
|
|
29
|
+
"Present when the interaction declares a secondary actor (e.g. marriage) or a redirect saves one."
|
|
30
|
+
),
|
|
31
|
+
s(
|
|
32
|
+
"secondary_recipient",
|
|
33
|
+
CHAR,
|
|
34
|
+
"As secondary_actor, for the recipient side (e.g. the character being married off)."
|
|
35
|
+
),
|
|
36
|
+
s(
|
|
37
|
+
"intermediary",
|
|
38
|
+
CHAR,
|
|
39
|
+
"The intermediary who forwards the interaction, when one is used. Set/replaced via redirect."
|
|
40
|
+
),
|
|
41
|
+
],
|
|
42
|
+
|
|
43
|
+
// common/activities/activity_types/_activity_type.info
|
|
44
|
+
activity_type: [
|
|
45
|
+
s("activity", "activity", "The activity (is_valid, on_* effect blocks, phases…)."),
|
|
46
|
+
s("host", CHAR, "Host of the activity."),
|
|
47
|
+
s(
|
|
48
|
+
"special_option",
|
|
49
|
+
"flag",
|
|
50
|
+
"Flag of the selected special option; unset when the activity has no special option category."
|
|
51
|
+
),
|
|
52
|
+
s("province", "province", "Phase blocks: the location the phase is at / being evaluated in."),
|
|
53
|
+
],
|
|
54
|
+
// common/activities/guest_invite_rules/_invite_rules.info (root = host character)
|
|
55
|
+
guest_invite_rule: [
|
|
56
|
+
s(
|
|
57
|
+
"special_option",
|
|
58
|
+
"flag",
|
|
59
|
+
"Flag of the selected special option; unset when the activity has no special option category."
|
|
60
|
+
),
|
|
61
|
+
],
|
|
62
|
+
// common/activities/intents/_intents.info
|
|
63
|
+
activity_intent: [
|
|
64
|
+
s("target", CHAR, "The target of the intent."),
|
|
65
|
+
s("activity", "activity", "The activity the intent applies to."),
|
|
66
|
+
s("special_option", "flag", "Flag of the selected special option."),
|
|
67
|
+
],
|
|
68
|
+
// common/activities/pulse_actions/_pulse_actions.info
|
|
69
|
+
activity_pulse_action: [
|
|
70
|
+
s("activity", "activity", "The activity."),
|
|
71
|
+
s("host", CHAR, "Host of the activity."),
|
|
72
|
+
s("province", "province", "Current activity location."),
|
|
73
|
+
s("first", CHAR, "First saved character, shown in the pulse-action entry."),
|
|
74
|
+
s("second", CHAR, "Second saved character, shown in the pulse-action entry."),
|
|
75
|
+
],
|
|
76
|
+
// common/activities/activity_locales/_activity_locales.info
|
|
77
|
+
activity_locale: [s("activity", "activity", "The activity."), s("host", CHAR, "Host of the activity.")],
|
|
78
|
+
|
|
79
|
+
// common/schemes/scheme_types/_schemes.info
|
|
80
|
+
scheme_type: [
|
|
81
|
+
s("scheme", "scheme", "The scheme itself."),
|
|
82
|
+
s(
|
|
83
|
+
"owner",
|
|
84
|
+
CHAR,
|
|
85
|
+
"The scheme owner (same as scheme_owner, valid in an unbroken chain from the scheme scope)."
|
|
86
|
+
),
|
|
87
|
+
s(
|
|
88
|
+
"target",
|
|
89
|
+
CHAR,
|
|
90
|
+
"Whatever the scheme targets — a character for character-targeted schemes (title/culture/faith schemes target those types)."
|
|
91
|
+
),
|
|
92
|
+
s(
|
|
93
|
+
"target_title",
|
|
94
|
+
"landed_title",
|
|
95
|
+
"The targeted title, when the scheme targets a title (otherwise unset)."
|
|
96
|
+
),
|
|
97
|
+
s("agent", CHAR, "An agent in the scheme (on_agent_exposed and similar per-agent effects)."),
|
|
98
|
+
],
|
|
99
|
+
// common/schemes/agent_types/_agent_types.info
|
|
100
|
+
scheme_agent_type: [
|
|
101
|
+
s("owner", CHAR, "The owner of the scheme."),
|
|
102
|
+
s("scheme", "scheme", "The scheme."),
|
|
103
|
+
s("target", CHAR, "The target of the scheme."),
|
|
104
|
+
],
|
|
105
|
+
// common/schemes/pulse_actions/_pulse_actions.info
|
|
106
|
+
scheme_pulse_action: [
|
|
107
|
+
s("activity", "scheme", "The scheme (the docs reuse the activity slot name)."),
|
|
108
|
+
s("owner", CHAR, "Owner of the scheme."),
|
|
109
|
+
s("first", CHAR, "First saved character, shown in the pulse-action entry."),
|
|
110
|
+
s("second", CHAR, "Second saved character, shown in the pulse-action entry."),
|
|
111
|
+
],
|
|
112
|
+
|
|
113
|
+
// common/secret_types/_secret_types.info (root = the secret)
|
|
114
|
+
secret: [
|
|
115
|
+
s("secret_owner", CHAR, "The character the secret is about."),
|
|
116
|
+
s("secret_target", CHAR, "Optional character related to the secret (e.g. the lover in a lover secret)."),
|
|
117
|
+
s(
|
|
118
|
+
"target",
|
|
119
|
+
CHAR,
|
|
120
|
+
"is_shunned/is_criminal: the character checking whether they view the secret as shunned/criminal."
|
|
121
|
+
),
|
|
122
|
+
s("discoverer", CHAR, "on_discover: the character who discovered the secret."),
|
|
123
|
+
s("secret_exposer", CHAR, "on_expose: the character who exposed the secret."),
|
|
124
|
+
],
|
|
125
|
+
|
|
126
|
+
// common/story_cycles/_story_cycles.info (root = the story)
|
|
127
|
+
story_cycle: [s("story", "story", "The story cycle (same as root in its effect blocks).")],
|
|
128
|
+
|
|
129
|
+
// common/situation/situations/_situations.info
|
|
130
|
+
situation: [
|
|
131
|
+
s("situation", "situation", "The situation."),
|
|
132
|
+
s("situation_sub_region", "situation_sub_region", "The situation sub-region of the current block/phase."),
|
|
133
|
+
s(
|
|
134
|
+
"situation_participant_group",
|
|
135
|
+
"situation_participant_group",
|
|
136
|
+
"The participant group (participant blocks)."
|
|
137
|
+
),
|
|
138
|
+
],
|
|
139
|
+
|
|
140
|
+
// common/casus_belli_types/_casus_belli.info
|
|
141
|
+
casus_belli: [
|
|
142
|
+
s("attacker", CHAR, "The attacker in the war."),
|
|
143
|
+
s("defender", CHAR, "The defender in the war."),
|
|
144
|
+
s("claimant", CHAR, "The claimant, for claim CBs."),
|
|
145
|
+
s("target", "landed_title", "The target title, when the CB has one."),
|
|
146
|
+
],
|
|
147
|
+
|
|
148
|
+
// common/council_tasks/_council_tasks.info
|
|
149
|
+
council_task: [
|
|
150
|
+
s("councillor", CHAR, "The councillor performing the task."),
|
|
151
|
+
s("councillor_liege", CHAR, "The councillor's liege."),
|
|
152
|
+
s("county", "landed_title", "County tasks: the county being worked."),
|
|
153
|
+
s("province", "province", "Province tasks: the province being worked."),
|
|
154
|
+
s("target_character", CHAR, "Character-targeted tasks: the target."),
|
|
155
|
+
],
|
|
156
|
+
|
|
157
|
+
// common/buildings/_buildings.info (root = province)
|
|
158
|
+
building: [s("holder", CHAR, "The holder of the province the building is in.")],
|
|
159
|
+
|
|
160
|
+
// common/legends/legend_types/_legends.info
|
|
161
|
+
legend_type: [
|
|
162
|
+
s("legend", "legend", "The legend."),
|
|
163
|
+
s("creator", CHAR, "The creator of the legend."),
|
|
164
|
+
s("protagonist", CHAR, "The protagonist of the legend."),
|
|
165
|
+
],
|
|
166
|
+
|
|
167
|
+
// common/epidemics/_epidemics.info
|
|
168
|
+
epidemic: [
|
|
169
|
+
s("epidemic", "epidemic", "The epidemic."),
|
|
170
|
+
s("epidemic_type", "epidemic_type", "The epidemic's type."),
|
|
171
|
+
],
|
|
172
|
+
|
|
173
|
+
// common/inspirations/_inspirations.info (root = inspiration)
|
|
174
|
+
inspiration: [
|
|
175
|
+
s("inspiration", "inspiration", "The inspiration."),
|
|
176
|
+
s("inspiration_owner", CHAR, "The character who has the inspiration."),
|
|
177
|
+
s("inspiration_sponsor", CHAR, "The sponsoring character, once sponsored."),
|
|
178
|
+
],
|
|
179
|
+
|
|
180
|
+
// common/travel/travel_options/_travel_options.info (root = travel owner / plan)
|
|
181
|
+
travel_option: [s("owner", CHAR, "The travel plan owner.")],
|
|
182
|
+
// common/travel/point_of_interest_types/_travel_point_of_interest_types.info
|
|
183
|
+
point_of_interest: [s("province", "province", "The point-of-interest province.")],
|
|
184
|
+
|
|
185
|
+
// common/court_positions/types/_court_positions.info (root = character)
|
|
186
|
+
court_position: [
|
|
187
|
+
s("liege", CHAR, "The court owner employing the position."),
|
|
188
|
+
s("employee", CHAR, "The character employed in the position."),
|
|
189
|
+
],
|
|
190
|
+
court_position_task: [
|
|
191
|
+
s("liege", CHAR, "The court owner employing the position."),
|
|
192
|
+
s("employee", CHAR, "The character employed in the position."),
|
|
193
|
+
],
|
|
194
|
+
|
|
195
|
+
// common/character_memory_types/_character_memories.info
|
|
196
|
+
character_memory_type: [
|
|
197
|
+
s("memory", "character_memory", "The memory."),
|
|
198
|
+
s("new_memory", "character_memory", "The newly created memory (creation blocks)."),
|
|
199
|
+
s("owner", CHAR, "The memory owner."),
|
|
200
|
+
],
|
|
201
|
+
|
|
202
|
+
// common/great_projects/types/_great_project_types.info
|
|
203
|
+
great_project: [
|
|
204
|
+
s("great_project", "great_project", "The funded project (ongoing projects)."),
|
|
205
|
+
s("owner", CHAR, "The project owner."),
|
|
206
|
+
s("founder", CHAR, "The project founder."),
|
|
207
|
+
s("province", "province", "The project's province."),
|
|
208
|
+
],
|
|
209
|
+
|
|
210
|
+
// common/domiciles (root = owner character / the domicile)
|
|
211
|
+
domicile_building: [s("owner", CHAR, "The domicile owner.")],
|
|
212
|
+
domicile_type: [s("owner", CHAR, "The domicile owner.")],
|
|
213
|
+
|
|
214
|
+
// common/task_contracts/_task_contracts.info
|
|
215
|
+
task_contract: [s("employer", CHAR, "The character offering the contract.")],
|
|
216
|
+
|
|
217
|
+
// common/subject_contracts + tax slots
|
|
218
|
+
subject_contract: [
|
|
219
|
+
s("liege", CHAR, "The liege side of the contract."),
|
|
220
|
+
s("subject", CHAR, "The subject side of the contract."),
|
|
221
|
+
s("vassal", CHAR, "The vassal (tax blocks)."),
|
|
222
|
+
s("tax_collector", CHAR, "The tax collector."),
|
|
223
|
+
s("tax_slot", "tax_slot", "The tax slot."),
|
|
224
|
+
],
|
|
225
|
+
tax_obligation: [
|
|
226
|
+
s("liege", CHAR, "The liege."),
|
|
227
|
+
s("vassal", CHAR, "The vassal."),
|
|
228
|
+
s("tax_collector", CHAR, "The tax collector."),
|
|
229
|
+
s("tax_slot", "tax_slot", "The tax slot."),
|
|
230
|
+
],
|
|
231
|
+
tax_slot_type: [
|
|
232
|
+
s("liege", CHAR, "The liege."),
|
|
233
|
+
s("vassal", CHAR, "The vassal."),
|
|
234
|
+
s("tax_collector", CHAR, "The tax collector."),
|
|
235
|
+
s("tax_slot", "tax_slot", "The tax slot."),
|
|
236
|
+
],
|
|
237
|
+
|
|
238
|
+
// common/succession_election/_succession_election.info (root = the title)
|
|
239
|
+
succession_election: [
|
|
240
|
+
s("candidate", CHAR, "The candidate being evaluated."),
|
|
241
|
+
s("holder", CHAR, "The current title holder."),
|
|
242
|
+
s("holder_candidate", CHAR, "The holder as a candidate."),
|
|
243
|
+
s("title", "landed_title", "The elective title."),
|
|
244
|
+
],
|
|
245
|
+
succession_appointment: [s("title", "landed_title", "The title being appointed.")],
|
|
246
|
+
|
|
247
|
+
// Misc single-scope kinds
|
|
248
|
+
vassal_stance: [s("liege", CHAR, "The vassal's liege.")],
|
|
249
|
+
legitimacy_level: [
|
|
250
|
+
s("target", CHAR, "The character whose legitimacy is checked."),
|
|
251
|
+
s("liege", CHAR, "The target's liege."),
|
|
252
|
+
],
|
|
253
|
+
scripted_relation: [s("target", CHAR, "The other character of the relation.")],
|
|
254
|
+
suggestion: [s("recipient", CHAR, "The character receiving the suggestion.")],
|
|
255
|
+
important_action: [s("recipient", CHAR, "The character the alert is for (the player).")],
|
|
256
|
+
house_aspiration: [s("house", "dynasty_house", "The house the aspiration belongs to.")],
|
|
257
|
+
combat_phase_event: [s("combat_side", "combat_side", "The combat side of the phase event.")],
|
|
258
|
+
culture_creation_name: [
|
|
259
|
+
s("culture", "culture", "The culture being created."),
|
|
260
|
+
s("other_culture", "culture", "The other parent culture (hybrid cultures)."),
|
|
261
|
+
],
|
|
262
|
+
innovation: [s("character", CHAR, "The innovating culture's ruler (specific trigger blocks).")],
|
|
263
|
+
|
|
264
|
+
// common/artifacts
|
|
265
|
+
artifact_template: [s("artifact", "artifact", "The artifact.")],
|
|
266
|
+
artifact_visual: [s("artifact", "artifact", "The artifact.")],
|
|
267
|
+
|
|
268
|
+
// common/accolade_names/_accolade_name.info (root = the accolade)
|
|
269
|
+
accolade_name: [
|
|
270
|
+
s("accolade_type", "accolade_type", "The accolade's primary type."),
|
|
271
|
+
s("owner", CHAR, "The accolade owner (the liege)."),
|
|
272
|
+
],
|
|
273
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Crusader Kings III game profile: identity plus every CK3 knowledge table
|
|
3
|
+
* and bundled-data import, assembled behind the GameProfile interface.
|
|
4
|
+
*/
|
|
5
|
+
import type { GameProfile } from "../profile";
|
|
6
|
+
import { ck3Meta } from "./meta";
|
|
7
|
+
import { BLOCK_REF_FIELDS, CK3_SCHEMA, PREFIX_REFS, REF_FIELDS } from "./schema";
|
|
8
|
+
import { STRUCTURE_SOURCES } from "./structures";
|
|
9
|
+
import { CK3_MODIFIER_PLACEHOLDERS } from "./modifierPlaceholders";
|
|
10
|
+
import { CK3_SAVE_SCHEMA } from "./saveSchema";
|
|
11
|
+
// Bundled baseline data (packages/server/data/ck3/), imported at build time so
|
|
12
|
+
// completion/hover work without gamePath set. See scripts/build-data-types-json.ts
|
|
13
|
+
// and scripts/build-gui-schema.ts for regeneration.
|
|
14
|
+
import BUNDLED_DATA_TYPES from "../../../data/ck3/dataTypes.json";
|
|
15
|
+
import GUI_SCHEMA from "../../../data/ck3/guiSchema.json";
|
|
16
|
+
|
|
17
|
+
export const ck3Profile: GameProfile = {
|
|
18
|
+
...ck3Meta,
|
|
19
|
+
schema: CK3_SCHEMA,
|
|
20
|
+
refFields: REF_FIELDS,
|
|
21
|
+
prefixRefs: PREFIX_REFS,
|
|
22
|
+
blockRefFields: BLOCK_REF_FIELDS,
|
|
23
|
+
structureSources: STRUCTURE_SOURCES,
|
|
24
|
+
// Events declare `scope = character|landed_title|…` and default to character
|
|
25
|
+
// when the key is absent (events/_events.info); custom loc `type = all` → any
|
|
26
|
+
// scope; scripted_guis declare `scope = X`.
|
|
27
|
+
defRootKeys: {
|
|
28
|
+
event: { key: "scope", default: "character" },
|
|
29
|
+
customizable_localization: { key: "type" },
|
|
30
|
+
scripted_gui: { key: "scope", default: "character" },
|
|
31
|
+
},
|
|
32
|
+
modifierPlaceholders: CK3_MODIFIER_PLACEHOLDERS,
|
|
33
|
+
bundledDataTypes: BUNDLED_DATA_TYPES,
|
|
34
|
+
guiSchema: GUI_SCHEMA,
|
|
35
|
+
saveSchema: CK3_SAVE_SCHEMA,
|
|
36
|
+
wikiNote: "Source: CK3 wiki (may lag behind the current game version)",
|
|
37
|
+
diagnosticSource: "ck3-script",
|
|
38
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crusader Kings III identity and conventions. Data only — safe for the VSCode
|
|
3
|
+
* client to import without pulling the knowledge tables into its bundle.
|
|
4
|
+
*/
|
|
5
|
+
import type { GameMeta } from "../profile";
|
|
6
|
+
import { GITAN_MEASURED_METRICS } from "../../gui/measuredMetrics";
|
|
7
|
+
import { CK3_SCAFFOLDS } from "./scaffolds";
|
|
8
|
+
|
|
9
|
+
export const ck3Meta: GameMeta = {
|
|
10
|
+
id: "ck3",
|
|
11
|
+
name: "Crusader Kings III",
|
|
12
|
+
shortName: "CK3",
|
|
13
|
+
engine: "jomini",
|
|
14
|
+
descriptor: "mod",
|
|
15
|
+
configDirName: ".ck3modding",
|
|
16
|
+
docsFolderName: "Crusader Kings III",
|
|
17
|
+
steamAppId: 1158310,
|
|
18
|
+
eventNamespaces: true,
|
|
19
|
+
// The engine's own default metrics: they were measured on this game's font,
|
|
20
|
+
// and the layout engine reuses them for games whose probe has not run.
|
|
21
|
+
uiFont: "fonts/Gitan/GitanLatin-Regular.otf",
|
|
22
|
+
guiTextMetrics: GITAN_MEASURED_METRICS,
|
|
23
|
+
scaffolds: CK3_SCAFFOLDS,
|
|
24
|
+
tiger: { binaryName: "ck3-tiger", repoSlug: "amtep/tiger", confName: "ck3-tiger.conf" },
|
|
25
|
+
// "" keeps the pre-profile cache filenames (docsCache.json, vanillaIndex-*.json)
|
|
26
|
+
// so existing users' caches survive the M2 restructure.
|
|
27
|
+
cacheSuffix: "",
|
|
28
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CK3's templated-modifier placeholder table ($CULTURE$_opinion, …), consumed
|
|
3
|
+
* by data/modifierTemplates.ts via the game profile.
|
|
4
|
+
*
|
|
5
|
+
* Every placeholder mapping below was verified against vanilla 1.19:
|
|
6
|
+
* `common/modifier_definition_formats/` enumerates the generated names, and
|
|
7
|
+
* script usage (traditions, buildings, perks…) confirms the join rule is
|
|
8
|
+
* `<definition name>` spliced verbatim into the template. Unverifiable
|
|
9
|
+
* placeholders are deliberately absent — a wrong expansion is worse than a
|
|
10
|
+
* missing one:
|
|
11
|
+
* - GEOGRAPHICAL_REGION (map_data) and TRAIT_TRACK (nested in traits) have no
|
|
12
|
+
* definition-index kind.
|
|
13
|
+
* - SUBJECT_SALARY expands to title tiers, but 40 of the 220 tier combinations
|
|
14
|
+
* do not exist in vanilla's formats.
|
|
15
|
+
*/
|
|
16
|
+
import type { PlaceholderSpec } from "../../data/modifierTemplates";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* MEN_AT_ARMS_TYPE expands to the engine's hardcoded base types (`type = …` in
|
|
20
|
+
* a men-at-arms definition), NOT to common/men_at_arms_types names: vanilla
|
|
21
|
+
* uses `heavy_infantry_damage_mult`, never `armored_footmen_damage_mult`.
|
|
22
|
+
*/
|
|
23
|
+
const MAA_BASE_TYPES = [
|
|
24
|
+
"archer_cavalry",
|
|
25
|
+
"archers",
|
|
26
|
+
"camel_cavalry",
|
|
27
|
+
"elephant_cavalry",
|
|
28
|
+
"gunpowder",
|
|
29
|
+
"heavy_cavalry",
|
|
30
|
+
"heavy_infantry",
|
|
31
|
+
"light_cavalry",
|
|
32
|
+
"nomadic_horde",
|
|
33
|
+
"pikemen",
|
|
34
|
+
"siege_weapon",
|
|
35
|
+
"skirmishers",
|
|
36
|
+
] as const;
|
|
37
|
+
|
|
38
|
+
export const CK3_MODIFIER_PLACEHOLDERS: Record<string, PlaceholderSpec> = {
|
|
39
|
+
CULTURE: { kind: "culture", label: "culture" }, // akan_opinion
|
|
40
|
+
// Faiths are nested under `faiths = { … }` and not indexed yet (see
|
|
41
|
+
// schema.ts); the mapping is inert until they are, which is correct.
|
|
42
|
+
FAITH: { kind: "faith", label: "faith" }, // mutazila_opinion
|
|
43
|
+
GOVERNMENT_TYPE: { kind: "government", label: "government" }, // feudal_government_opinion
|
|
44
|
+
HOLDING_TYPE: { kind: "holding_type", label: "holding type" }, // castle_holding_build_speed
|
|
45
|
+
LIFESTYLE: { kind: "lifestyle", label: "lifestyle" }, // diplomacy_lifestyle_xp_gain_add
|
|
46
|
+
MEN_AT_ARMS_TYPE: {
|
|
47
|
+
values: MAA_BASE_TYPES,
|
|
48
|
+
label: "men-at-arms base type",
|
|
49
|
+
// Verified exception: stationed_* variants exist for every base type
|
|
50
|
+
// EXCEPT nomadic_horde (absent from vanilla formats and script usage).
|
|
51
|
+
excludeValues: { stationed_: ["nomadic_horde"] },
|
|
52
|
+
},
|
|
53
|
+
RELIGIOUS: { kind: "religion", label: "religion" }, // christianity_religion_opinion
|
|
54
|
+
RELIGIOUS_FAMILY: { kind: "religion_family", label: "religion family" }, // rf_pagan_opinion
|
|
55
|
+
SCHEME_TYPE: { kind: "scheme_type", label: "scheme type" }, // abduct_scheme_phase_duration_add
|
|
56
|
+
SCRIPTED_RELATION: { kind: "scripted_relation", label: "scripted relation" }, // scheme_phase_duration_against_rival_add
|
|
57
|
+
SITUATION_TYPE: { kind: "situation", label: "situation" }, // the_great_steppe_supply_limit_add
|
|
58
|
+
TAX_SLOT_TYPE: { kind: "tax_slot_type", label: "tax slot type" }, // clan_tax_slot_add
|
|
59
|
+
TERRAIN_TYPE: { kind: "terrain_type", label: "terrain type" }, // plains_advantage
|
|
60
|
+
VASSAL_STANCE: { kind: "vassal_stance", label: "vassal stance" }, // courtly_opinion
|
|
61
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a Crusader Kings III save is read for GUI preview values.
|
|
3
|
+
*
|
|
4
|
+
* CK3 packs its script into a zip holding one `gamestate` entry (gui/saveZip.ts
|
|
5
|
+
* finds it; `-debug_mode` writes the same script as plain text instead), and
|
|
6
|
+
* names the played character LAST, in `played_character`, long after the
|
|
7
|
+
* `living` record a preview wants. That is what `record` below describes: find
|
|
8
|
+
* the id first, then cut out `living.<id>`.
|
|
9
|
+
*
|
|
10
|
+
* CK3's player is a character, so most rows read that record; the three names
|
|
11
|
+
* the load-game screen shows (character, primary title, house) the save already
|
|
12
|
+
* carries ready-localized in `meta_data`, which is why no title or dynasty
|
|
13
|
+
* block has to be cut out of a 70 MB gamestate to render them.
|
|
14
|
+
*/
|
|
15
|
+
import type { BlockNode } from "../../parser";
|
|
16
|
+
import {
|
|
17
|
+
age,
|
|
18
|
+
block,
|
|
19
|
+
named,
|
|
20
|
+
scalar,
|
|
21
|
+
statements,
|
|
22
|
+
thousands,
|
|
23
|
+
type SaveContext,
|
|
24
|
+
type SaveSchema,
|
|
25
|
+
type ValueMapping,
|
|
26
|
+
} from "../../gui/saveSchema";
|
|
27
|
+
|
|
28
|
+
/** The living character's own state (currencies, variables) sits under here. */
|
|
29
|
+
function aliveData(ctx: SaveContext): BlockNode | undefined {
|
|
30
|
+
return block(ctx.character, "alive_data");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function firstName(ctx: SaveContext): string | undefined {
|
|
34
|
+
return named(ctx, scalar(ctx.character, "first_name"));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const CK3_MAPPINGS: ValueMapping[] = [
|
|
38
|
+
{
|
|
39
|
+
// `first_name` is a loc key (`Alp_Arslan`), which is what CK3's own
|
|
40
|
+
// `GetName` renders for a character.
|
|
41
|
+
chains: ["GetPlayer.GetName", "GetPlayer.GetFirstName"],
|
|
42
|
+
read: (ctx) => firstName(ctx),
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
chains: ["GetPlayer.GetFullName"],
|
|
46
|
+
read: (ctx) => {
|
|
47
|
+
const first = firstName(ctx);
|
|
48
|
+
const house = scalar(ctx.meta, "meta_house_name");
|
|
49
|
+
return first && house ? `${first} ${house}` : first;
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
chains: ["GetPlayer.GetAge"],
|
|
54
|
+
read: (ctx) => age(scalar(ctx.character, "birth"), scalar(ctx.meta, "meta_date")),
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
chains: ["GetPlayer.GetGold"],
|
|
58
|
+
read: (ctx) => thousands(scalar(block(aliveData(ctx), "gold"), "value")),
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
chains: ["GetPlayer.GetPrestige"],
|
|
62
|
+
read: (ctx) => thousands(scalar(block(aliveData(ctx), "prestige"), "currency")),
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
chains: ["GetPlayer.GetPiety"],
|
|
66
|
+
read: (ctx) => thousands(scalar(block(aliveData(ctx), "piety"), "currency")),
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
// `meta_title_name` IS the primary title's name, article and all.
|
|
70
|
+
chains: ["GetPlayer.GetPrimaryTitle.GetName"],
|
|
71
|
+
read: (ctx) => scalar(ctx.meta, "meta_title_name"),
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
// The meta carries the HOUSE name; for most characters the dynasty reads
|
|
75
|
+
// the same, and a preview shows what is knowable.
|
|
76
|
+
chains: ["GetPlayer.GetDynasty.GetName", "GetPlayer.GetHouse.GetName"],
|
|
77
|
+
read: (ctx) => scalar(ctx.meta, "meta_house_name"),
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
chains: ["GetCurrentDate", "GetGameDate"],
|
|
81
|
+
read: (ctx) => ctx.date,
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The character variables the save holds, as the two chains a modder reads them
|
|
87
|
+
* back with. `alive_data.variables.data` is a list of
|
|
88
|
+
* `{ flag=<name> data={ type=… identity=… } }`; a script value is conventionally
|
|
89
|
+
* named exactly like the variable it mirrors, so both chains answer from it.
|
|
90
|
+
* A variable the save stores without a value (a bare flag) stays absent.
|
|
91
|
+
*/
|
|
92
|
+
function characterVariables(ctx: SaveContext): Record<string, string> {
|
|
93
|
+
const out: Record<string, string> = {};
|
|
94
|
+
const data = block(block(aliveData(ctx), "variables"), "data");
|
|
95
|
+
for (const s of statements(data)) {
|
|
96
|
+
if (s.kind !== "value" || s.value.kind !== "block") continue;
|
|
97
|
+
const name = scalar(s.value, "flag");
|
|
98
|
+
const text = variableValue(block(s.value, "data"));
|
|
99
|
+
if (!name || text === undefined) continue;
|
|
100
|
+
out[`GetPlayer.MakeScope.Var('${name}').GetValue`] = text;
|
|
101
|
+
out[`GetPlayer.MakeScope.ScriptValue('${name}')`] = text;
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** One variable's stored value; `type=value` is fixed point, x100000. */
|
|
107
|
+
function variableValue(data: BlockNode | undefined): string | undefined {
|
|
108
|
+
const identity = scalar(data, "identity");
|
|
109
|
+
if (identity === undefined) return undefined;
|
|
110
|
+
switch (scalar(data, "type")) {
|
|
111
|
+
case "value":
|
|
112
|
+
return fixedPoint(identity);
|
|
113
|
+
case "boolean":
|
|
114
|
+
return identity === "0" ? "no" : "yes";
|
|
115
|
+
default:
|
|
116
|
+
// A character/title/… variable: the id is all the save holds about it.
|
|
117
|
+
return identity;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** `2700000` -> `27`, `25000` -> `0.25`. */
|
|
122
|
+
function fixedPoint(raw: string): string | undefined {
|
|
123
|
+
const n = Number(raw);
|
|
124
|
+
if (!Number.isFinite(n)) return undefined;
|
|
125
|
+
return String(Number((n / 100000).toFixed(5)));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export const CK3_SAVE_SCHEMA: SaveSchema = {
|
|
129
|
+
dateKey: "meta_date",
|
|
130
|
+
nameKey: "meta_player_name",
|
|
131
|
+
mappings: CK3_MAPPINGS,
|
|
132
|
+
expand: characterVariables,
|
|
133
|
+
record: { marker: "\nplayed_character={", idKey: "character", block: "living" },
|
|
134
|
+
};
|