@neocompose/cli 0.72.4 → 0.73.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.
@@ -1561,6 +1561,260 @@ function isGeneratedCSharpReservedKeyword(value) {
1561
1561
  function generatedCSharpMemberNameForSchemaKey(schemaKey) {
1562
1562
  return isGeneratedCSharpReservedKeyword(schemaKey) ? `${schemaKey}Value` : schemaKey;
1563
1563
  }
1564
+ function generatedCSharpTypeName(value, fallback) {
1565
+ const parts = value.match(/[A-Za-z0-9]+/g) ?? [];
1566
+ const joined = parts.map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join("");
1567
+ const candidate = joined.length > 0 ? joined : fallback;
1568
+ const safe = /^[0-9]/.test(candidate) ? `_${candidate}` : candidate;
1569
+ return isGeneratedCSharpReservedKeyword(safe) ? `${safe}Type` : safe;
1570
+ }
1571
+ function generatedCSharpShortId(id) {
1572
+ return id.replace(/[^A-Za-z0-9_]/g, "").slice(0, 8) || "Id";
1573
+ }
1574
+ function dialogueGroupPropertyNames(groups, onCollision) {
1575
+ const ordered = [...groups].sort(compareGroupIds);
1576
+ const used = /* @__PURE__ */ new Set();
1577
+ const names = /* @__PURE__ */ new Map();
1578
+ for (const group of ordered) {
1579
+ const propertyName = generatedCSharpTypeName(group.name, "DialogueGroup");
1580
+ if (!used.has(propertyName)) {
1581
+ used.add(propertyName);
1582
+ names.set(group.id, propertyName);
1583
+ continue;
1584
+ }
1585
+ const uniqueName = `${propertyName}_${generatedCSharpShortId(group.id)}`;
1586
+ onCollision?.({
1587
+ groupId: group.id,
1588
+ groupName: group.name,
1589
+ propertyName,
1590
+ uniqueName
1591
+ });
1592
+ names.set(group.id, uniqueName);
1593
+ }
1594
+ return names;
1595
+ }
1596
+ function compareGroupIds(left, right) {
1597
+ if (left.id < right.id) return -1;
1598
+ if (left.id > right.id) return 1;
1599
+ return 0;
1600
+ }
1601
+
1602
+ // ../packages/neoscript-language/src/dialogue-types.ts
1603
+ var NEOSCRIPT_DIALOGUES_MEMBER_NAME = "Dialogues";
1604
+ var NEOSCRIPT_DIALOGUES_TYPE_ID = "builtin:Dialogues";
1605
+ var RENAMED_DIALOGUE_TYPES = /* @__PURE__ */ new Map([
1606
+ ["Dialogue", { base: "NeoDialogue", value: "NeoDialogueReference" }],
1607
+ [
1608
+ "DialogueRef",
1609
+ { base: "NeoDialogueReference", value: "NeoDialogueReference" }
1610
+ ],
1611
+ ["DialogueGroup", { base: "NeoDialogueGroup", value: "NeoDialogueGroup" }],
1612
+ ["PriorityGroup", { base: "NeoPriorityGroup", value: "NeoPriorityGroup" }]
1613
+ ]);
1614
+ function renamedDialogueTypeMessage(name, position) {
1615
+ const replacement = RENAMED_DIALOGUE_TYPES.get(name)?.[position];
1616
+ if (replacement === void 0) return void 0;
1617
+ return `\`${name}\` was renamed to \`${replacement}\`.`;
1618
+ }
1619
+ var BOOL_TYPE = { kind: "primitive", name: "bool" };
1620
+ var INT_TYPE = { kind: "primitive", name: "int" };
1621
+ var STRING_TYPE = { kind: "primitive", name: "string" };
1622
+ var NEOSCRIPT_DIALOGUE_ON_FINISH_TYPE = {
1623
+ kind: "delegate",
1624
+ returnType: { kind: "primitive", name: "void" },
1625
+ parameterTypes: [],
1626
+ nullable: true
1627
+ };
1628
+ var ON_FINISH_PARAMETER = {
1629
+ name: "onFinish",
1630
+ type: NEOSCRIPT_DIALOGUE_ON_FINISH_TYPE,
1631
+ defaultValue: { displayText: "null", value: null },
1632
+ documentation: "Runs once the dialogue ends, whether it finished, failed, or was disposed."
1633
+ };
1634
+ function method(ownerId, name, returnType, parameters, documentation) {
1635
+ return {
1636
+ id: `${ownerId}:${name}`,
1637
+ name,
1638
+ kind: "method",
1639
+ type: returnType,
1640
+ returnType,
1641
+ parameters,
1642
+ documentation
1643
+ };
1644
+ }
1645
+ function neoScriptDialogueReferenceMethods(ownerId) {
1646
+ return [
1647
+ method(
1648
+ ownerId,
1649
+ "TryTrigger",
1650
+ BOOL_TYPE,
1651
+ [ON_FINISH_PARAMETER],
1652
+ "Triggers the referenced dialogue. Returns true when it started or was queued."
1653
+ ),
1654
+ method(
1655
+ ownerId,
1656
+ "CanTrigger",
1657
+ BOOL_TYPE,
1658
+ [],
1659
+ "Checks whether the referenced dialogue's conditions are met, without triggering it."
1660
+ )
1661
+ ];
1662
+ }
1663
+ function rootMethods() {
1664
+ const dialogueId = {
1665
+ name: "dialogueId",
1666
+ type: STRING_TYPE
1667
+ };
1668
+ const pointer = { name: "pointer", type: STRING_TYPE };
1669
+ return [
1670
+ method(
1671
+ NEOSCRIPT_DIALOGUES_TYPE_ID,
1672
+ "TryTrigger",
1673
+ BOOL_TYPE,
1674
+ [dialogueId, ON_FINISH_PARAMETER],
1675
+ "Triggers a direct dialogue. Returns true when it started or was queued."
1676
+ ),
1677
+ method(
1678
+ NEOSCRIPT_DIALOGUES_TYPE_ID,
1679
+ "CanTrigger",
1680
+ BOOL_TYPE,
1681
+ [dialogueId],
1682
+ "Checks whether a direct dialogue's conditions are met, without triggering it."
1683
+ ),
1684
+ method(
1685
+ NEOSCRIPT_DIALOGUES_TYPE_ID,
1686
+ "VisitCount",
1687
+ INT_TYPE,
1688
+ [pointer],
1689
+ "Returns how many times a dialogue or text node was visited."
1690
+ ),
1691
+ method(
1692
+ NEOSCRIPT_DIALOGUES_TYPE_ID,
1693
+ "HasVisited",
1694
+ BOOL_TYPE,
1695
+ [pointer],
1696
+ "Returns whether a dialogue or text node was visited."
1697
+ )
1698
+ ];
1699
+ }
1700
+ function groupMethods(typeId, receiver) {
1701
+ if (receiver.kind === "standard") {
1702
+ return [
1703
+ method(
1704
+ typeId,
1705
+ "TryTrigger",
1706
+ BOOL_TYPE,
1707
+ [ON_FINISH_PARAMETER],
1708
+ "Triggers this group's highest-priority eligible dialogue. Returns true when it started or was queued."
1709
+ ),
1710
+ method(
1711
+ typeId,
1712
+ "CanTrigger",
1713
+ BOOL_TYPE,
1714
+ [],
1715
+ "Checks whether this group has an eligible dialogue, without triggering it."
1716
+ )
1717
+ ];
1718
+ }
1719
+ if (receiver.kind !== "lookup" || receiver.entryType === void 0) return [];
1720
+ const value = {
1721
+ name: "value",
1722
+ type: receiver.entryType
1723
+ };
1724
+ return [
1725
+ method(
1726
+ typeId,
1727
+ "TryTrigger",
1728
+ BOOL_TYPE,
1729
+ [value, ON_FINISH_PARAMETER],
1730
+ "Triggers the highest-priority eligible dialogue for the lookup value. Returns true when it started or was queued."
1731
+ ),
1732
+ method(
1733
+ typeId,
1734
+ "CanTrigger",
1735
+ BOOL_TYPE,
1736
+ [value],
1737
+ "Checks whether the lookup value has an eligible dialogue, without triggering it."
1738
+ )
1739
+ ];
1740
+ }
1741
+ var KIND_LABELS = {
1742
+ standard: "Dialogue group",
1743
+ lookup: "Lookup dialogue group",
1744
+ folder: "Dialogue folder"
1745
+ };
1746
+ function neoScriptDialogueTypes(groups) {
1747
+ const names = dialogueGroupPropertyNames(groups);
1748
+ const children = /* @__PURE__ */ new Map();
1749
+ for (const group of groups) {
1750
+ const siblings = children.get(group.parentId);
1751
+ if (siblings === void 0) children.set(group.parentId, [group]);
1752
+ else siblings.push(group);
1753
+ }
1754
+ const rootPath = `root.${NEOSCRIPT_DIALOGUES_MEMBER_NAME}`;
1755
+ const types = [];
1756
+ const typeFor = (parentId, path) => {
1757
+ const members = [];
1758
+ for (const group of children.get(parentId) ?? []) {
1759
+ const name = names.get(group.id);
1760
+ const groupPath = `${path}.${name}`;
1761
+ const typeId = `${NEOSCRIPT_DIALOGUES_TYPE_ID}:${group.id}`;
1762
+ const receiver = {
1763
+ kind: group.kind,
1764
+ path: groupPath,
1765
+ groupId: group.id,
1766
+ ...group.lookup ? { entryType: group.lookup.entryType } : {}
1767
+ };
1768
+ const lookup = group.lookup ? ` Looks up ${group.lookup.entryTypeName} in \`${group.lookup.collection}\`.` : "";
1769
+ const documentation = `${KIND_LABELS[group.kind]} \`${groupPath}\`.${lookup}`;
1770
+ types.push({
1771
+ id: typeId,
1772
+ name: groupPath,
1773
+ kind: "synthetic",
1774
+ documentation,
1775
+ dialogues: receiver,
1776
+ members: [
1777
+ ...typeFor(group.id, groupPath),
1778
+ ...groupMethods(typeId, receiver)
1779
+ ]
1780
+ });
1781
+ members.push({
1782
+ id: `${typeId}:member`,
1783
+ name,
1784
+ kind: "property",
1785
+ type: { kind: "named", typeId },
1786
+ documentation,
1787
+ detail: KIND_LABELS[group.kind],
1788
+ writable: false,
1789
+ writability: "readOnly",
1790
+ ...group.location ? { location: group.location } : {},
1791
+ ...group.selectionLocation ? { selectionLocation: group.selectionLocation } : {}
1792
+ });
1793
+ }
1794
+ return members;
1795
+ };
1796
+ const topLevel = typeFor(null, rootPath);
1797
+ types.push({
1798
+ id: NEOSCRIPT_DIALOGUES_TYPE_ID,
1799
+ name: rootPath,
1800
+ kind: "synthetic",
1801
+ documentation: "The project's dialogues and dialogue groups, the same paths as the generated C# Dialogues.",
1802
+ dialogues: { kind: "root", path: rootPath },
1803
+ members: [...topLevel, ...rootMethods()]
1804
+ });
1805
+ return {
1806
+ member: {
1807
+ id: `${NEOSCRIPT_DIALOGUES_TYPE_ID}:member`,
1808
+ name: NEOSCRIPT_DIALOGUES_MEMBER_NAME,
1809
+ kind: "property",
1810
+ type: { kind: "named", typeId: NEOSCRIPT_DIALOGUES_TYPE_ID },
1811
+ documentation: "The project's dialogues. Trigger them, check them, and read dialogue memory.",
1812
+ writable: false,
1813
+ writability: "readOnly"
1814
+ },
1815
+ types
1816
+ };
1817
+ }
1564
1818
 
1565
1819
  // ../packages/neoscript-language/src/language-spec.ts
1566
1820
  var NEOSCRIPT_KEYWORDS = [
@@ -1620,7 +1874,7 @@ var NEOSCRIPT_BUILTIN_ANNOTATION_TYPES = [
1620
1874
  "FunctionRef",
1621
1875
  "NeoDelegate",
1622
1876
  "NeoAction",
1623
- "Dialogue",
1877
+ "NeoDialogue",
1624
1878
  "Trigger",
1625
1879
  "Node",
1626
1880
  "Text",
@@ -1630,7 +1884,7 @@ var NEOSCRIPT_BUILTIN_ANNOTATION_TYPES = [
1630
1884
  "Outcome",
1631
1885
  "SpriteInfo",
1632
1886
  "AudioClipInfo",
1633
- "DialogueRef",
1887
+ "NeoDialogueReference",
1634
1888
  "Vector2",
1635
1889
  "Vector2Int",
1636
1890
  "Vector3",
@@ -1677,10 +1931,10 @@ var NEOSCRIPT_OPERATORS = [
1677
1931
  "<",
1678
1932
  ">"
1679
1933
  ];
1680
- var STRING_TYPE = { kind: "primitive", name: "string" };
1681
- var INT_TYPE = { kind: "primitive", name: "int" };
1934
+ var STRING_TYPE2 = { kind: "primitive", name: "string" };
1935
+ var INT_TYPE2 = { kind: "primitive", name: "int" };
1682
1936
  var FLOAT_TYPE = { kind: "primitive", name: "float" };
1683
- var BOOL_TYPE = { kind: "primitive", name: "bool" };
1937
+ var BOOL_TYPE2 = { kind: "primitive", name: "bool" };
1684
1938
  var IMAGE_REF_TYPE = {
1685
1939
  kind: "primitive",
1686
1940
  name: "ImageRef"
@@ -1705,7 +1959,7 @@ var NEOSCRIPT_STRUCTURED_LEAF_FIELDS = {
1705
1959
  {
1706
1960
  name: "SliceIndex",
1707
1961
  key: "sliceIndex",
1708
- type: INT_TYPE,
1962
+ type: INT_TYPE2,
1709
1963
  documentation: "Index into the file's slices."
1710
1964
  }
1711
1965
  ],
@@ -1727,13 +1981,13 @@ var NEOSCRIPT_STRUCTURED_LEAF_FIELDS = {
1727
1981
  {
1728
1982
  name: "x",
1729
1983
  key: "x",
1730
- type: INT_TYPE,
1984
+ type: INT_TYPE2,
1731
1985
  documentation: "Vector2Int x component."
1732
1986
  },
1733
1987
  {
1734
1988
  name: "y",
1735
1989
  key: "y",
1736
- type: INT_TYPE,
1990
+ type: INT_TYPE2,
1737
1991
  documentation: "Vector2Int y component."
1738
1992
  }
1739
1993
  ],
@@ -1761,19 +2015,19 @@ var NEOSCRIPT_STRUCTURED_LEAF_FIELDS = {
1761
2015
  {
1762
2016
  name: "x",
1763
2017
  key: "x",
1764
- type: INT_TYPE,
2018
+ type: INT_TYPE2,
1765
2019
  documentation: "Vector3Int x component."
1766
2020
  },
1767
2021
  {
1768
2022
  name: "y",
1769
2023
  key: "y",
1770
- type: INT_TYPE,
2024
+ type: INT_TYPE2,
1771
2025
  documentation: "Vector3Int y component."
1772
2026
  },
1773
2027
  {
1774
2028
  name: "z",
1775
2029
  key: "z",
1776
- type: INT_TYPE,
2030
+ type: INT_TYPE2,
1777
2031
  documentation: "Vector3Int z component."
1778
2032
  }
1779
2033
  ],
@@ -1856,14 +2110,14 @@ function builtinFunction(name, returnType, parameters, documentation) {
1856
2110
  var NEOSCRIPT_GLOBALS = [
1857
2111
  builtinFunction(
1858
2112
  "VisitCount",
1859
- INT_TYPE,
1860
- [parameter("pointer", STRING_TYPE)],
2113
+ INT_TYPE2,
2114
+ [parameter("pointer", STRING_TYPE2)],
1861
2115
  "Returns the number of visits recorded for a dialogue pointer."
1862
2116
  ),
1863
2117
  builtinFunction(
1864
2118
  "HasVisited",
1865
- BOOL_TYPE,
1866
- [parameter("pointer", STRING_TYPE)],
2119
+ BOOL_TYPE2,
2120
+ [parameter("pointer", STRING_TYPE2)],
1867
2121
  "Returns whether a dialogue pointer has been visited."
1868
2122
  )
1869
2123
  ];
@@ -1931,8 +2185,8 @@ var NEOSCRIPT_BUILTIN_TYPE_SYMBOLS = [
1931
2185
  // `FileId` and `SliceIndex` come from the field table above — they are
1932
2186
  // the writable, addressable fields, not derived properties (D11).
1933
2187
  ...structuredLeafFieldProperties("SpriteInfo"),
1934
- property("SpriteInfo", "FileName", STRING_TYPE, "Asset file name."),
1935
- property("SpriteInfo", "Name", STRING_TYPE, "Sprite name."),
2188
+ property("SpriteInfo", "FileName", STRING_TYPE2, "Asset file name."),
2189
+ property("SpriteInfo", "Name", STRING_TYPE2, "Sprite name."),
1936
2190
  property(
1937
2191
  "SpriteInfo",
1938
2192
  "Size",
@@ -1962,8 +2216,8 @@ var NEOSCRIPT_BUILTIN_TYPE_SYMBOLS = [
1962
2216
  name: "AudioClipInfo",
1963
2217
  kind: "builtin",
1964
2218
  members: [
1965
- property("AudioClipInfo", "FileId", STRING_TYPE, "Asset file id."),
1966
- property("AudioClipInfo", "Name", STRING_TYPE, "Audio clip name."),
2219
+ property("AudioClipInfo", "FileId", STRING_TYPE2, "Asset file id."),
2220
+ property("AudioClipInfo", "Name", STRING_TYPE2, "Audio clip name."),
1967
2221
  property(
1968
2222
  "AudioClipInfo",
1969
2223
  "DurationSeconds",
@@ -1973,10 +2227,13 @@ var NEOSCRIPT_BUILTIN_TYPE_SYMBOLS = [
1973
2227
  ]
1974
2228
  },
1975
2229
  {
1976
- id: "builtin:DialogueRef",
1977
- name: "DialogueRef",
2230
+ id: "builtin:NeoDialogueReference",
2231
+ name: "NeoDialogueReference",
1978
2232
  kind: "builtin",
1979
- members: [property("DialogueRef", "id", STRING_TYPE, "Dialogue id.")]
2233
+ members: [
2234
+ property("NeoDialogueReference", "id", STRING_TYPE2, "Dialogue id."),
2235
+ ...neoScriptDialogueReferenceMethods("builtin:NeoDialogueReference")
2236
+ ]
1980
2237
  },
1981
2238
  ...vectorTypes(),
1982
2239
  {
@@ -1998,7 +2255,7 @@ var NEOSCRIPT_BUILTIN_TYPE_SYMBOLS = [
1998
2255
  returnType: { kind: "primitive", name: "void" },
1999
2256
  static: true,
2000
2257
  parameters: [
2001
- ...name === "Assert" ? [parameter("condition", BOOL_TYPE)] : [],
2258
+ ...name === "Assert" ? [parameter("condition", BOOL_TYPE2)] : [],
2002
2259
  parameter("message", { kind: "primitive", name: "unknown" })
2003
2260
  ],
2004
2261
  documentation: name === "Assert" ? "Emits an assertion event when condition is false. Both arguments are evaluated. Does not throw." : "Emits a bounded message and the current NeoScript stack. Does not throw when the sink fails."
@@ -2029,25 +2286,25 @@ var NEOSCRIPT_BUILTIN_TYPE_SYMBOLS = [
2029
2286
  "Round",
2030
2287
  ["x"],
2031
2288
  `Rounds to the nearest integer; midpoints round to even (banker's rounding). ${MATH_INTEGRAL_RULE}`,
2032
- INT_TYPE
2289
+ INT_TYPE2
2033
2290
  ),
2034
2291
  mathFunction(
2035
2292
  "Floor",
2036
2293
  ["x"],
2037
2294
  `Rounds toward negative infinity. ${MATH_INTEGRAL_RULE}`,
2038
- INT_TYPE
2295
+ INT_TYPE2
2039
2296
  ),
2040
2297
  mathFunction(
2041
2298
  "Ceiling",
2042
2299
  ["x"],
2043
2300
  `Rounds toward positive infinity. ${MATH_INTEGRAL_RULE}`,
2044
- INT_TYPE
2301
+ INT_TYPE2
2045
2302
  ),
2046
2303
  mathFunction(
2047
2304
  "Truncate",
2048
2305
  ["x"],
2049
2306
  `Rounds toward zero. ${MATH_INTEGRAL_RULE}`,
2050
- INT_TYPE
2307
+ INT_TYPE2
2051
2308
  ),
2052
2309
  mathFunction(
2053
2310
  "Abs",
@@ -2058,7 +2315,7 @@ var NEOSCRIPT_BUILTIN_TYPE_SYMBOLS = [
2058
2315
  "Sign",
2059
2316
  ["x"],
2060
2317
  "Returns -1, 0, or 1 for a negative, zero, or positive value. Accepts int, float, or decimal and always returns int.",
2061
- INT_TYPE
2318
+ INT_TYPE2
2062
2319
  ),
2063
2320
  mathFunction(
2064
2321
  "Sqrt",
@@ -2099,7 +2356,7 @@ var NEOSCRIPT_BUILTIN_TYPE_SYMBOLS = [
2099
2356
  returnType: { kind: "list", elementType: LIST_ENTRY_TYPE },
2100
2357
  parameters: [
2101
2358
  parameter("value", LIST_ENTRY_TYPE),
2102
- parameter("count", INT_TYPE)
2359
+ parameter("count", INT_TYPE2)
2103
2360
  ],
2104
2361
  documentation: "Returns a list of count copies of value. The entry type is inferred from value and the assignment context \u2014 never spell it. value is evaluated exactly once, then count exactly once, so a reference-typed value is the same reference in every entry; count must be a non-negative int, and 0 produces an empty list.",
2105
2362
  static: true
@@ -2187,6 +2444,11 @@ function relativeDebugUri(uri) {
2187
2444
 
2188
2445
  // ../packages/neoscript-language/src/strict-ir.ts
2189
2446
  var NEOSCRIPT_COMPILER_REVISION = 17;
2447
+ var NeoScriptDialogueOp = /* @__PURE__ */ ((NeoScriptDialogueOp2) => {
2448
+ NeoScriptDialogueOp2["TryTrigger"] = "TryTrigger";
2449
+ NeoScriptDialogueOp2["CanTrigger"] = "CanTrigger";
2450
+ return NeoScriptDialogueOp2;
2451
+ })(NeoScriptDialogueOp || {});
2190
2452
 
2191
2453
  // ../src/models/neoscript/neoscript-compiler-revision.ts
2192
2454
  var ACTIVE_NEOSCRIPT_COMPILER_REVISION_ROLLOUT = (
@@ -3074,6 +3336,31 @@ function isNSFunctionHasVisited(value) {
3074
3336
  const v = value;
3075
3337
  return v?.type === "hasVisited" /* hasVisited */ && isNSDialogueMemoryFunctionInfo(v.info);
3076
3338
  }
3339
+ function isNSDialogueOp(value) {
3340
+ return value === "TryTrigger" || value === "CanTrigger";
3341
+ }
3342
+ function isOptionalNSPointer(value) {
3343
+ return value === void 0 || isNSPointer(value);
3344
+ }
3345
+ function isNSFunctionDialogueGroup(value) {
3346
+ const v = value;
3347
+ if (v?.type !== "dialogueGroup" /* dialogueGroup */) return false;
3348
+ const info = v.info;
3349
+ if (typeof info !== "object" || info === null) return false;
3350
+ if (!isNSDialogueOp(Reflect.get(info, "op"))) return false;
3351
+ if (typeof Reflect.get(info, "groupId") !== "string") return false;
3352
+ if (!isOptionalNSPointer(Reflect.get(info, "valuePointer"))) return false;
3353
+ return isOptionalNSPointer(Reflect.get(info, "onFinishPointer"));
3354
+ }
3355
+ function isNSFunctionDialogue(value) {
3356
+ const v = value;
3357
+ if (v?.type !== "dialogue" /* dialogue */) return false;
3358
+ const info = v.info;
3359
+ if (typeof info !== "object" || info === null) return false;
3360
+ if (!isNSDialogueOp(Reflect.get(info, "op"))) return false;
3361
+ if (!isNSPointer(Reflect.get(info, "dialogueIdPointer"))) return false;
3362
+ return isOptionalNSPointer(Reflect.get(info, "onFinishPointer"));
3363
+ }
3077
3364
  function isNSVectorConstructorType(value) {
3078
3365
  return value === 14 /* Vector2 */ || value === 15 /* Vector2Int */ || value === 16 /* Vector3 */ || value === 17 /* Vector3Int */;
3079
3366
  }
@@ -3133,7 +3420,7 @@ function isNSFunction(value) {
3133
3420
  return isNSFunctionClassConstructor(value) || isNSFunctionClassClone(value) || isNSFunctionListIndex(value) || isNSFunctionSelect(value) || isNSFunctionCollectionQuery(value) || isNSFunctionFirst(value) || isNSFunctionFirstOrDefault(value) || isNSFunctionWhere(value) || isNSFunctionContains(value) || isNSFunctionIndexOf(value) || // stringOp was missing from this chain since its introduction — a
3134
3421
  // compiled getter using ToLower()/StartsWith() would fail pointer
3135
3422
  // validation anywhere isNSFunction gates. Fixed alongside decimalOp.
3136
- isNSFunctionStringOp(value) || isNSFunctionDecimalOp(value) || isNSFunctionMathOp(value) || isNSFunctionListRepeat(value) || isNSFunctionCount(value) || isNSFunctionVisitCount(value) || isNSFunctionHasVisited(value) || isNSFunctionVectorConstructor(value) || isNSFunctionImageSlice(value) || isNSFunctionVariantInitialize(value) || isNSFunctionVariantApply(value) || isNSFunctionDeclaredConstructor(value);
3423
+ isNSFunctionStringOp(value) || isNSFunctionDecimalOp(value) || isNSFunctionMathOp(value) || isNSFunctionListRepeat(value) || isNSFunctionCount(value) || isNSFunctionVisitCount(value) || isNSFunctionHasVisited(value) || isNSFunctionDialogueGroup(value) || isNSFunctionDialogue(value) || isNSFunctionVectorConstructor(value) || isNSFunctionImageSlice(value) || isNSFunctionVariantInitialize(value) || isNSFunctionVariantApply(value) || isNSFunctionDeclaredConstructor(value);
3137
3424
  }
3138
3425
  function isNSInstructionVariable(value) {
3139
3426
  const v = value;
@@ -22268,6 +22555,26 @@ function evalFunction(fn, scope, ctx) {
22268
22555
  const pointer = evalPointer(fn.info.pointer, scope, ctx);
22269
22556
  return dialogueMemoryVisitCount(pointer, ctx) > 0;
22270
22557
  }
22558
+ case "dialogueGroup" /* dialogueGroup */: {
22559
+ if (fn.info.valuePointer !== void 0)
22560
+ evalPointer(fn.info.valuePointer, scope, ctx);
22561
+ if (fn.info.onFinishPointer !== void 0)
22562
+ evalPointer(fn.info.onFinishPointer, scope, ctx);
22563
+ return false;
22564
+ }
22565
+ case "dialogue" /* dialogue */: {
22566
+ const idPointer = fn.info.dialogueIdPointer;
22567
+ const dialogueId = evalPointer(idPointer, scope, ctx);
22568
+ if (dialogueId === null && idPointer.type === "keyOf" /* keyOf */ && idPointer.optional === true)
22569
+ return null;
22570
+ if (typeof dialogueId !== "string")
22571
+ throw new NSGetterRuntimeError(
22572
+ `${fn.info.op} needs a dialogue id string, but got ${dialogueId === null ? "null" : typeof dialogueId}.`
22573
+ );
22574
+ if (fn.info.onFinishPointer !== void 0)
22575
+ evalPointer(fn.info.onFinishPointer, scope, ctx);
22576
+ return false;
22577
+ }
22271
22578
  case "vectorConstructor" /* vectorConstructor */: {
22272
22579
  return evalVectorConstructor(
22273
22580
  fn.info.vectorType,
@@ -35095,23 +35402,23 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
35095
35402
  resolveDebugStatement(expr, scope) {
35096
35403
  if (expr.kind !== "call" || expr.callee.kind !== "member" || expr.callee.receiver.kind !== "ident" || expr.callee.receiver.name !== "Debug" || this.hasValueReceiver("Debug", scope) || this.project.typeByName.get("Debug")?.id !== "builtin:Debug" && this.project.typeByName.has("Debug"))
35097
35404
  return null;
35098
- const method = expr.callee.name;
35405
+ const method2 = expr.callee.name;
35099
35406
  const severities = {
35100
35407
  Log: "log",
35101
35408
  LogWarning: "warning",
35102
35409
  LogError: "error",
35103
35410
  Assert: "assert"
35104
35411
  };
35105
- if (!Object.hasOwn(severities, method))
35106
- throw new CompileError(`Unknown Debug method '${method}'.`, expr.pos);
35107
- const severity = severities[method];
35108
- const expected = method === "Assert" ? 2 : 1;
35412
+ if (!Object.hasOwn(severities, method2))
35413
+ throw new CompileError(`Unknown Debug method '${method2}'.`, expr.pos);
35414
+ const severity = severities[method2];
35415
+ const expected = method2 === "Assert" ? 2 : 1;
35109
35416
  if (expr.args.length !== expected)
35110
35417
  throw new CompileError(
35111
- `Debug.${method} expects ${expected} argument(s).`,
35418
+ `Debug.${method2} expects ${expected} argument(s).`,
35112
35419
  expr.pos
35113
35420
  );
35114
- const condition = method === "Assert" ? this.resolveExpression(requiredAt(expr.args, 0), scope) : void 0;
35421
+ const condition = method2 === "Assert" ? this.resolveExpression(requiredAt(expr.args, 0), scope) : void 0;
35115
35422
  if (condition && (!isPrimitive(condition.type, "bool") || isNullable(condition.type)))
35116
35423
  throw new CompileError(
35117
35424
  "Debug.Assert requires a non-null bool condition.",
@@ -36001,6 +36308,17 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
36001
36308
  }
36002
36309
  }
36003
36310
  resolveExpression(expression, scope, expected) {
36311
+ const result = this.resolveReceiverExpression(expression, scope, expected);
36312
+ if (result.dialogues !== void 0) {
36313
+ throw new CompileError(
36314
+ dialogueValueError(result.dialogues),
36315
+ expression.pos
36316
+ );
36317
+ }
36318
+ return result;
36319
+ }
36320
+ /** {@link resolveExpression} that also admits a `root.Dialogues` receiver. */
36321
+ resolveReceiverExpression(expression, scope, expected) {
36004
36322
  let result = this.resolveExpressionCore(expression, scope, expected);
36005
36323
  if (result.pointer.type === "function" /* Function */ || result.pointer.type === "callFunction" /* CallFunction */ || result.pointer.type === "callDelegate" /* CallDelegate */ || result.pointer.type === "callAction" /* CallAction */ || result.pointer.type === "callGetter" /* CallGetter */) {
36006
36324
  result = {
@@ -37578,7 +37896,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37578
37896
  return this.resolveStaticMemberValue(staticType, member, pos);
37579
37897
  }
37580
37898
  }
37581
- const resolvedReceiver = receiverValue ? receiverValue() : this.resolveExpression(receiverAst, scope);
37899
+ const resolvedReceiver = receiverValue ? receiverValue() : this.resolveReceiverExpression(receiverAst, scope);
37582
37900
  if (optional2 && !isNullable(resolvedReceiver.type)) {
37583
37901
  throw new CompileError(
37584
37902
  `\`?.\` requires an optional receiver; got ${this.describe(resolvedReceiver.type)}`,
@@ -37674,7 +37992,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37674
37992
  }
37675
37993
  const primitiveMember = resolvePrimitiveMember(receiver.type, name);
37676
37994
  if (primitiveMember) {
37677
- if (isPrimitive(receiver.type, "DialogueRef")) {
37995
+ if (isPrimitive(receiver.type, "NeoDialogueReference")) {
37678
37996
  return {
37679
37997
  pointer: {
37680
37998
  type: "keyOf" /* KeyOf */,
@@ -37707,12 +38025,15 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37707
38025
  pos
37708
38026
  );
37709
38027
  }
37710
- if (isPrimitive(receiver.type, "DialogueRef")) {
38028
+ if (isPrimitive(receiver.type, "NeoDialogueReference")) {
37711
38029
  throw new CompileError(
37712
38030
  `${this.describe(receiver.type)} has no member '${name}'`,
37713
38031
  pos
37714
38032
  );
37715
38033
  }
38034
+ if (receiver.dialogues !== void 0) {
38035
+ return this.resolveDialogueGroupRead(receiver, name, pos);
38036
+ }
37716
38037
  const memberReceiverType = neoScriptMemberLookupType(receiver.type);
37717
38038
  if (memberReceiverType.kind === "named") {
37718
38039
  const type = this.project.typeById.get(memberReceiverType.typeId);
@@ -37741,6 +38062,10 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37741
38062
  if (this.userClassCode && type.id === this.rootTypeId && member.writability !== "user") {
37742
38063
  throw new CompileError("User code can only read `root.User`.", pos);
37743
38064
  }
38065
+ const dialogues = this.dialogueReceiverOf(member.type);
38066
+ if (dialogues !== void 0) {
38067
+ return { ...literal(member.type, null), dialogues, symbol: member };
38068
+ }
37744
38069
  if (member.static === true) {
37745
38070
  throw new CompileError(
37746
38071
  `Static member '${type.name}.${name}' must be accessed through the type name, not an instance.`,
@@ -38095,6 +38420,227 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38095
38420
  );
38096
38421
  }
38097
38422
  }
38423
+ /** P105 §2.1. The receiver a value of this type is, if it is one. */
38424
+ dialogueReceiverOf(type) {
38425
+ if (type.kind !== "named") return void 0;
38426
+ return this.project.typeById.get(type.typeId)?.dialogues;
38427
+ }
38428
+ /** P105 §2.1. `<receiver>.<Group>`; the methods are only callable. */
38429
+ resolveDialogueGroupRead(receiver, name, pos) {
38430
+ const path = receiver.dialogues.path;
38431
+ const type = receiver.type.kind === "named" ? this.project.typeById.get(receiver.type.typeId) : void 0;
38432
+ const member = type?.members.find((candidate) => candidate.name === name);
38433
+ if (member === void 0) {
38434
+ throw new CompileError(`${path} has no dialogue group '${name}'.`, pos);
38435
+ }
38436
+ if (member.kind === "method") {
38437
+ throw new CompileError(
38438
+ `'${path}.${name}' must be called with \`()\`; it cannot be read as a value.`,
38439
+ pos
38440
+ );
38441
+ }
38442
+ const dialogues = this.dialogueReceiverOf(member.type);
38443
+ if (dialogues === void 0) {
38444
+ throw new Error(
38445
+ `Dialogue group member '${path}.${name}' has no group type.`
38446
+ );
38447
+ }
38448
+ return { ...literal(member.type, null), dialogues, symbol: member };
38449
+ }
38450
+ /** P105 §2.1. A call on `root.Dialogues` or one of its groups. */
38451
+ resolveDialogueReceiverCall(receiver, name, args, scope, pos) {
38452
+ if (receiver.kind === "root") {
38453
+ if (name === "VisitCount" || name === "HasVisited") {
38454
+ return this.resolveDialogueMemoryRead(name, args, scope, pos);
38455
+ }
38456
+ if (!isDialogueRequestName(name)) {
38457
+ throw new CompileError(
38458
+ `${receiver.path} has no method '${name}'.`,
38459
+ pos
38460
+ );
38461
+ }
38462
+ this.assertDialogueRequestAllowed(name, pos);
38463
+ requireDialogueArgCount(name, args, 1, name === "TryTrigger", pos);
38464
+ const dialogueId = this.resolveExpression(requiredAt(args, 0), scope, {
38465
+ kind: "primitive",
38466
+ name: "string"
38467
+ });
38468
+ this.requireAssignable(
38469
+ dialogueId.type,
38470
+ { kind: "primitive", name: "string" },
38471
+ requiredAt(args, 0).pos,
38472
+ "dialogueId"
38473
+ );
38474
+ return dialogueIntrinsic({
38475
+ type: "dialogue" /* Dialogue */,
38476
+ info: {
38477
+ op: NeoScriptDialogueOp[name],
38478
+ dialogueIdPointer: dialogueId.pointer,
38479
+ ...this.dialogueOnFinish(args[1], scope)
38480
+ }
38481
+ });
38482
+ }
38483
+ if (!isDialogueRequestName(name)) {
38484
+ throw new CompileError(`${receiver.path} has no member '${name}'.`, pos);
38485
+ }
38486
+ if (receiver.kind === "folder") {
38487
+ throw new CompileError(
38488
+ `${receiver.path} is a dialogue folder, so it has no '${name}'. Use one of its groups' members.`,
38489
+ pos
38490
+ );
38491
+ }
38492
+ this.assertDialogueRequestAllowed(name, pos);
38493
+ if (receiver.kind === "standard") {
38494
+ requireDialogueArgCount(name, args, 0, name === "TryTrigger", pos);
38495
+ return dialogueIntrinsic({
38496
+ type: "dialogueGroup" /* DialogueGroup */,
38497
+ info: {
38498
+ op: NeoScriptDialogueOp[name],
38499
+ groupId: receiver.groupId,
38500
+ ...this.dialogueOnFinish(args[0], scope)
38501
+ }
38502
+ });
38503
+ }
38504
+ const entryType = receiver.entryType;
38505
+ if (entryType === void 0) {
38506
+ throw new CompileError(
38507
+ `${receiver.path} can't be triggered: its lookup collection has no entry class.`,
38508
+ pos
38509
+ );
38510
+ }
38511
+ requireDialogueArgCount(name, args, 1, name === "TryTrigger", pos);
38512
+ const value = this.resolveExpression(requiredAt(args, 0), scope, entryType);
38513
+ this.requireAssignable(
38514
+ value.type,
38515
+ entryType,
38516
+ requiredAt(args, 0).pos,
38517
+ "lookup value"
38518
+ );
38519
+ return dialogueIntrinsic({
38520
+ type: "dialogueGroup" /* DialogueGroup */,
38521
+ info: {
38522
+ op: NeoScriptDialogueOp[name],
38523
+ groupId: receiver.groupId,
38524
+ valuePointer: value.pointer,
38525
+ ...this.dialogueOnFinish(args[1], scope)
38526
+ }
38527
+ });
38528
+ }
38529
+ /**
38530
+ * P105 §2.2. `NeoDialogueReference` methods request the dialogue by the
38531
+ * reference's `id`, the same index-0 read `.id` lowers to.
38532
+ */
38533
+ resolveDialogueReferenceCall(receiver, name, args, scope, pos, optional2) {
38534
+ if (this.userClassCode) {
38535
+ throw new CompileError(
38536
+ `User code can't use ${name}. Dialogues run against a save.`,
38537
+ pos
38538
+ );
38539
+ }
38540
+ const nullPropagating = optional2 || receiver.optionalChainType !== void 0;
38541
+ if (!optional2 && isNullable(receiver.type)) {
38542
+ throw new CompileError(
38543
+ `Member '${name}' is called on ${this.describe(receiver.type)}, which may be null. Handle null before calling through it \u2014 use \`!\` if it is always set, or \`?.\` or a null check that narrows it.`,
38544
+ pos
38545
+ );
38546
+ }
38547
+ this.assertDialogueRequestAllowed(name, pos);
38548
+ requireDialogueArgCount(name, args, 0, name === "TryTrigger", pos);
38549
+ const resolved = dialogueIntrinsic({
38550
+ type: "dialogue" /* Dialogue */,
38551
+ info: {
38552
+ op: NeoScriptDialogueOp[name],
38553
+ dialogueIdPointer: {
38554
+ type: "keyOf" /* KeyOf */,
38555
+ keyOf: { pointer: receiver.pointer, key: numberPointer(0) },
38556
+ ...nullPropagating ? { optional: true } : {}
38557
+ },
38558
+ ...this.dialogueOnFinish(args[0], scope)
38559
+ }
38560
+ });
38561
+ if (!nullPropagating) return resolved;
38562
+ return {
38563
+ ...resolved,
38564
+ type: { ...resolved.type, nullable: true },
38565
+ optionalChainType: resolved.type
38566
+ };
38567
+ }
38568
+ dialogueOnFinish(argument2, scope) {
38569
+ if (argument2 === void 0) return {};
38570
+ const onFinish = this.resolveExpression(
38571
+ argument2,
38572
+ scope,
38573
+ NEOSCRIPT_DIALOGUE_ON_FINISH_TYPE
38574
+ );
38575
+ this.requireAssignable(
38576
+ onFinish.type,
38577
+ NEOSCRIPT_DIALOGUE_ON_FINISH_TYPE,
38578
+ argument2.pos,
38579
+ "onFinish"
38580
+ );
38581
+ return { onFinishPointer: onFinish.pointer };
38582
+ }
38583
+ /**
38584
+ * P105 §2.4. Requests run only from bodies that run once per call; reads
38585
+ * run wherever dialogue memory has a value.
38586
+ */
38587
+ assertDialogueRequestAllowed(name, pos) {
38588
+ if (name === "CanTrigger") {
38589
+ this.assertDialogueMemoryReadable(name, pos);
38590
+ return;
38591
+ }
38592
+ const kind = this.context.kind;
38593
+ if (kind === "function" || kind === "action") return;
38594
+ if (kind === "getter" || kind === "property" || kind === "condition") {
38595
+ throw new CompileError(
38596
+ "A getter can't trigger a dialogue. It runs whenever its value is read.",
38597
+ pos
38598
+ );
38599
+ }
38600
+ if (kind === "setter") {
38601
+ throw new CompileError(
38602
+ "A setter can't trigger a dialogue. Trigger it from a function.",
38603
+ pos
38604
+ );
38605
+ }
38606
+ throw new CompileError(
38607
+ `${capitalize(dialogueBodyKindLabel(kind))} body can't trigger a dialogue. Dialogues only run during play.`,
38608
+ pos
38609
+ );
38610
+ }
38611
+ /**
38612
+ * P43 §7.2.2. Dialogue memory is runtime state; it has no value at push
38613
+ * time, in a freshly constructed instance, or while migrating a save.
38614
+ */
38615
+ assertDialogueMemoryReadable(name, pos) {
38616
+ const kind = this.context.kind;
38617
+ if (!isNeoScriptConstructionDocumentKind(kind) && kind !== "migration") {
38618
+ return;
38619
+ }
38620
+ throw new CompileError(
38621
+ `${name} reads runtime dialogue memory, which has no meaning in ${dialogueBodyKindLabel(kind)} body.`,
38622
+ pos
38623
+ );
38624
+ }
38625
+ resolveDialogueMemoryRead(name, args, scope, pos) {
38626
+ this.assertDialogueMemoryReadable(name, pos);
38627
+ requireArgCount(name, args, 1, pos);
38628
+ const pointer = this.resolveExpression(requiredAt(args, 0), scope, {
38629
+ kind: "primitive",
38630
+ name: "string"
38631
+ });
38632
+ if (!isPrimitive(pointer.type, "string")) {
38633
+ throw new CompileError(
38634
+ `${name} pointer must be a string; got ${this.describe(pointer.type)}`,
38635
+ pos
38636
+ );
38637
+ }
38638
+ return intrinsic(
38639
+ name === "VisitCount" ? "visitCount" /* VisitCount */ : "hasVisited" /* HasVisited */,
38640
+ { pointer: pointer.pointer },
38641
+ { kind: "primitive", name: name === "VisitCount" ? "int" : "bool" }
38642
+ );
38643
+ }
38098
38644
  /**
38099
38645
  * P69 §2.7. A member read on the `Math` namespace: the two constants lower
38100
38646
  * to `float` literals, and nothing else on `Math` is readable as a value.
@@ -38300,7 +38846,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38300
38846
  return () => {
38301
38847
  if (!result) {
38302
38848
  try {
38303
- result = { value: this.resolveExpression(callee.receiver, scope) };
38849
+ result = {
38850
+ value: this.resolveReceiverExpression(callee.receiver, scope)
38851
+ };
38304
38852
  } catch (error) {
38305
38853
  result = { error };
38306
38854
  }
@@ -38355,31 +38903,11 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38355
38903
  if (vector3)
38356
38904
  return this.resolveVectorConstructor(vector3, argumentsList2, scope, pos);
38357
38905
  if (callee.name === "VisitCount" || callee.name === "HasVisited") {
38358
- if (isNeoScriptConstructionDocumentKind(this.context.kind)) {
38359
- throw new CompileError(
38360
- `${callee.name} reads runtime dialogue memory, which has no meaning in a ${this.context.kind} body.`,
38361
- pos
38362
- );
38363
- }
38364
- requireArgCount(callee.name, argumentsList2, 1, pos);
38365
- const pointer = this.resolveExpression(
38366
- requiredAt(argumentsList2, 0),
38906
+ return this.resolveDialogueMemoryRead(
38907
+ callee.name,
38908
+ argumentsList2,
38367
38909
  scope,
38368
- { kind: "primitive", name: "string" }
38369
- );
38370
- if (!isPrimitive(pointer.type, "string")) {
38371
- throw new CompileError(
38372
- `${callee.name} pointer must be a string; got ${this.describe(pointer.type)}`,
38373
- pos
38374
- );
38375
- }
38376
- return intrinsic(
38377
- callee.name === "VisitCount" ? "visitCount" /* VisitCount */ : "hasVisited" /* HasVisited */,
38378
- { pointer: pointer.pointer },
38379
- {
38380
- kind: "primitive",
38381
- name: callee.name === "VisitCount" ? "int" : "bool"
38382
- }
38910
+ pos
38383
38911
  );
38384
38912
  }
38385
38913
  const global = this.context.project.globals.find(
@@ -38484,12 +39012,37 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38484
39012
  }
38485
39013
  const receiver = receiverValue();
38486
39014
  const optional2 = callee.optional === true;
39015
+ if (receiver.dialogues !== void 0) {
39016
+ if (optional2) {
39017
+ throw new CompileError(
39018
+ `\`?.\` is not valid on ${receiver.dialogues.path}; it is never null.`,
39019
+ pos
39020
+ );
39021
+ }
39022
+ return this.resolveDialogueReceiverCall(
39023
+ receiver.dialogues,
39024
+ callee.name,
39025
+ argumentsList2,
39026
+ scope,
39027
+ pos
39028
+ );
39029
+ }
38487
39030
  if (optional2 && !isNullable(receiver.type)) {
38488
39031
  throw new CompileError(
38489
39032
  `\`?.\` requires an optional receiver; got ${this.describe(receiver.type)}`,
38490
39033
  pos
38491
39034
  );
38492
39035
  }
39036
+ if (isPrimitive(receiver.type, "NeoDialogueReference") && isDialogueRequestName(callee.name)) {
39037
+ return this.resolveDialogueReferenceCall(
39038
+ receiver,
39039
+ callee.name,
39040
+ argumentsList2,
39041
+ scope,
39042
+ pos,
39043
+ optional2
39044
+ );
39045
+ }
38493
39046
  if (callee.name === "Slice" && isPrimitive(receiver.type, "ImageRef")) {
38494
39047
  return this.resolveImageSlice(receiver, argumentsList2, scope, pos);
38495
39048
  }
@@ -40771,6 +41324,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
40771
41324
  }
40772
41325
  }
40773
41326
  const receiver = receiverValue();
41327
+ if (receiver.dialogues !== void 0) return null;
40774
41328
  const memberReceiverType = neoScriptMemberLookupType(receiver.type);
40775
41329
  if (memberReceiverType.kind !== "named") return null;
40776
41330
  const type = this.project.typeById.get(memberReceiverType.typeId);
@@ -42243,6 +42797,43 @@ function enumLiteralKeyOptionId(pointer) {
42243
42797
  }
42244
42798
  return pointer.value.value[0];
42245
42799
  }
42800
+ function isDialogueRequestName(name) {
42801
+ return name === "TryTrigger" || name === "CanTrigger";
42802
+ }
42803
+ function dialogueBodyKindLabel(kind) {
42804
+ if (kind === "initializer" || kind === "initializerExpression")
42805
+ return "an initializer";
42806
+ return `a ${kind}`;
42807
+ }
42808
+ function capitalize(text) {
42809
+ return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
42810
+ }
42811
+ function requireDialogueArgCount(name, args, required, acceptsOnFinish, pos) {
42812
+ if (!acceptsOnFinish) {
42813
+ requireArgCount(name, args, required, pos);
42814
+ return;
42815
+ }
42816
+ if (args.length === required || args.length === required + 1) return;
42817
+ throw new CompileError(
42818
+ `${name} expects ${required} or ${required + 1} arguments, got ${args.length}.`,
42819
+ pos
42820
+ );
42821
+ }
42822
+ function dialogueValueError(receiver) {
42823
+ if (receiver.kind === "root") {
42824
+ return `\`${receiver.path}\` is not a value. Use one of its members.`;
42825
+ }
42826
+ if (receiver.kind === "folder") {
42827
+ return `\`${receiver.path}\` is a dialogue folder, not a value. Use one of its groups' members.`;
42828
+ }
42829
+ return `\`${receiver.path}\` is a dialogue group, not a value. Use one of its members.`;
42830
+ }
42831
+ function dialogueIntrinsic(fn) {
42832
+ return {
42833
+ pointer: { type: "function" /* Function */, function: fn },
42834
+ type: { kind: "primitive", name: "bool" }
42835
+ };
42836
+ }
42246
42837
  function intrinsic(kind, info, type) {
42247
42838
  return {
42248
42839
  pointer: {
@@ -42449,7 +43040,7 @@ function primitiveValueKind(name) {
42449
43040
  return 11 /* Sprite */;
42450
43041
  case "AudioClipInfo":
42451
43042
  return 12 /* Audio */;
42452
- case "DialogueRef":
43043
+ case "NeoDialogueReference":
42453
43044
  return 18 /* DialogueLookup */;
42454
43045
  case "Vector2":
42455
43046
  return 14 /* Vector2 */;
@@ -42482,7 +43073,7 @@ function valueKindPrimitive(kind) {
42482
43073
  case 12 /* Audio */:
42483
43074
  return "AudioClipInfo";
42484
43075
  case 18 /* DialogueLookup */:
42485
- return "DialogueRef";
43076
+ return "NeoDialogueReference";
42486
43077
  case 14 /* Vector2 */:
42487
43078
  return "Vector2";
42488
43079
  case 15 /* Vector2Int */:
@@ -42673,7 +43264,7 @@ function resolvePrimitiveMember(type, name) {
42673
43264
  if (name === "length")
42674
43265
  return { type: { kind: "primitive", name: "float" } };
42675
43266
  }
42676
- if (type.name === "DialogueRef" && name === "id")
43267
+ if (type.name === "NeoDialogueReference" && name === "id")
42677
43268
  return { type: { kind: "primitive", name: "string" } };
42678
43269
  return null;
42679
43270
  }
@@ -42772,7 +43363,7 @@ function namedPrimitive(name) {
42772
43363
  case "decimal":
42773
43364
  case "SpriteInfo":
42774
43365
  case "AudioClipInfo":
42775
- case "DialogueRef":
43366
+ case "NeoDialogueReference":
42776
43367
  case "Vector2":
42777
43368
  case "Vector2Int":
42778
43369
  case "Vector3":
@@ -43007,7 +43598,10 @@ function resolveNeoScriptType(type, context, project) {
43007
43598
  }
43008
43599
  const named = project.typeByName.get(type.name);
43009
43600
  if (!named)
43010
- throw new CompileError(`Unknown type '${type.name}'`, type.pos);
43601
+ throw new CompileError(
43602
+ renamedDialogueTypeMessage(type.name, "value") ?? `Unknown type '${type.name}'`,
43603
+ type.pos
43604
+ );
43011
43605
  resolved = {
43012
43606
  kind: "named",
43013
43607
  typeId: named.id,
@@ -43348,7 +43942,8 @@ function projectSchemaManifest(input, options = {}) {
43348
43942
  (item, index) => enumType(item, environment, `enums[${index}]`)
43349
43943
  )
43350
43944
  ];
43351
- const rootType = createRootType(rootMemberIds, environment);
43945
+ const dialogues = neoScriptDialogueTypes(options.dialogueGroups ?? []);
43946
+ const rootType = createRootType(rootMemberIds, environment, dialogues.member);
43352
43947
  declaredTypes.push(rootType);
43353
43948
  const roots = options.roots ?? [
43354
43949
  {
@@ -43367,7 +43962,7 @@ function projectSchemaManifest(input, options = {}) {
43367
43962
  return {
43368
43963
  project: {
43369
43964
  version: options.version ?? `manifest:${nextManifestProjectionVersion++}`,
43370
- types: languageTypes,
43965
+ types: [...languageTypes, ...dialogues.types],
43371
43966
  globals: options.globals ?? [],
43372
43967
  roots,
43373
43968
  listIndexes: members.flatMap(
@@ -43502,7 +44097,7 @@ function staticDefaultWritability(classId, environment) {
43502
44097
  resolvedAllowedStorage(classId, environment)
43503
44098
  );
43504
44099
  }
43505
- function createRootType(ids, environment) {
44100
+ function createRootType(ids, environment, dialogues) {
43506
44101
  const definitions = [
43507
44102
  ["Assets", ids.assets, false, "immutable"],
43508
44103
  ["Save", ids.save, true, "save"],
@@ -43525,6 +44120,7 @@ function createRootType(ids, environment) {
43525
44120
  ...sourceLocation(member.source, environment, `root.${name}.source`)
43526
44121
  });
43527
44122
  }
44123
+ members.push(dialogues);
43528
44124
  return {
43529
44125
  id: "__root__",
43530
44126
  name: "Root",
@@ -44301,8 +44897,7 @@ function memberType(member, environment, visiting, field) {
44301
44897
  return member.multiselect === true ? { kind: "set", elementType: entryType, nullable: nullable2 } : { ...entryType, nullable: nullable2 };
44302
44898
  }
44303
44899
  if (kind === "dialogueLookup") {
44304
- const dialogue = primitive("DialogueRef", false);
44305
- return member.multiselect === true ? { kind: "set", elementType: dialogue, nullable: nullable2 } : { ...dialogue, nullable: nullable2 };
44900
+ return member.multiselect === true ? { kind: "set", elementType: primitive("string", false), nullable: nullable2 } : { ...primitive("NeoDialogueReference", false), nullable: nullable2 };
44306
44901
  }
44307
44902
  if (kind === "computed") {
44308
44903
  return manifestType(member.returnType, environment, `${field}.returnType`);
@@ -44784,7 +45379,7 @@ function manifestPrimitive(kind) {
44784
45379
  case "vector3Int":
44785
45380
  return "Vector3Int";
44786
45381
  case "dialogueLookup":
44787
- return "DialogueRef";
45382
+ return "NeoDialogueReference";
44788
45383
  case "color":
44789
45384
  return "Color";
44790
45385
  default:
@@ -45180,6 +45775,164 @@ function pascalIdentifier(value) {
45180
45775
  return identifier;
45181
45776
  }
45182
45777
 
45778
+ // ../src/models/dialogue/dialogue-source-identifiers.ts
45779
+ function isDialogueSourceIdentifier(value) {
45780
+ return isValidProjectSourceIdentifier(value);
45781
+ }
45782
+
45783
+ // ../src/models/dialogue/logic-types.ts
45784
+ function isNSBoolGetter(value) {
45785
+ if (!isNSGetter(value)) return false;
45786
+ if (value.typeInfo.type !== 1 /* Bool */) return false;
45787
+ return value.typeInfo.required === true;
45788
+ }
45789
+ function isNSVoidBody2(value) {
45790
+ if (!isNSGetter(value)) return false;
45791
+ if (value.typeInfo.type !== 0 /* Null */) return false;
45792
+ return value.typeInfo.required === true;
45793
+ }
45794
+ function isUILogicCondition(value) {
45795
+ const v = value;
45796
+ if (typeof v !== "object") return false;
45797
+ if (v === null) return false;
45798
+ if (!isNonEmptyString(v.id)) return false;
45799
+ if (v.type !== 0 /* UI */) return false;
45800
+ if (!isNSBoolGetter(v.getter)) return false;
45801
+ return isUIRenderableCondition(v.getter);
45802
+ }
45803
+ function isCodeLogicCondition(value) {
45804
+ const v = value;
45805
+ if (typeof v !== "object") return false;
45806
+ if (v === null) return false;
45807
+ if (!isNonEmptyString(v.id)) return false;
45808
+ if (v.type !== 1 /* Code */) return false;
45809
+ if (!isNonEmptyString(v.sourceFunctionId)) return false;
45810
+ if (!isDialogueSourceIdentifier(v.sourceFunctionName)) return false;
45811
+ if (typeof v.code !== "string") return false;
45812
+ return isNSBoolGetter(v.getter);
45813
+ }
45814
+ function isLogicCondition(value) {
45815
+ return isUILogicCondition(value) || isCodeLogicCondition(value);
45816
+ }
45817
+ function isUILogicAction(value) {
45818
+ const v = value;
45819
+ if (typeof v !== "object") return false;
45820
+ if (v === null) return false;
45821
+ if (v.type !== 0 /* UI */) return false;
45822
+ if (!isNSVoidBody2(v.action)) return false;
45823
+ return isUIRenderableAction(v.action);
45824
+ }
45825
+ function isCodeLogicAction(value) {
45826
+ const v = value;
45827
+ if (typeof v !== "object") return false;
45828
+ if (v === null) return false;
45829
+ if (v.type !== 1 /* Code */) return false;
45830
+ if (!isNonEmptyString(v.sourceFunctionId)) return false;
45831
+ if (!isDialogueSourceIdentifier(v.sourceFunctionName)) return false;
45832
+ if (typeof v.code !== "string") return false;
45833
+ return isNSVoidBody2(v.action);
45834
+ }
45835
+ function isNonEmptyString(value) {
45836
+ return typeof value === "string" && value.length > 0;
45837
+ }
45838
+ function isLogicAction(value) {
45839
+ return isUILogicAction(value) || isCodeLogicAction(value);
45840
+ }
45841
+ function isUIRenderableCondition(getter) {
45842
+ if (getter.instructions.length !== 1) return false;
45843
+ return getter.instructions[0]?.type === "return" /* return */;
45844
+ }
45845
+ function isUIRenderableAction(action) {
45846
+ if (action.instructions.length === 0) return true;
45847
+ if (action.instructions.length !== 1) return false;
45848
+ const instruction = action.instructions[0];
45849
+ if (!instruction) return false;
45850
+ return instruction.type === "return" /* return */ || instruction.type === "assign" /* assign */ || instruction.type === "collectionCall" /* collectionCall */ || instruction.type === "functionCall" /* functionCall */;
45851
+ }
45852
+
45853
+ // ../src/models/dialogue/dialogue-group-types.ts
45854
+ function isOptionalNullableString2(value) {
45855
+ if (value === void 0) return true;
45856
+ if (value === null) return true;
45857
+ return typeof value === "string";
45858
+ }
45859
+ function isDialogueGroupType(value) {
45860
+ return value === 0 /* Standard */ || value === 1 /* Lookup */ || value === 2 /* Folder */;
45861
+ }
45862
+ function isDialogueGroupBase(value, expectedType) {
45863
+ const v = value;
45864
+ if (typeof v !== "object") return false;
45865
+ if (v === null) return false;
45866
+ if (typeof v.name !== "string") return false;
45867
+ if (!isDialogueGroupType(v.type)) return false;
45868
+ if (expectedType !== void 0 && v.type !== expectedType) return false;
45869
+ if (!isOptionalNullableString2(v.parentDialogueGroupId)) return false;
45870
+ if (!Array.isArray(v.conditions)) return false;
45871
+ if (!v.conditions.every(isLogicCondition)) return false;
45872
+ return isOptionalNullableString2(v.priorityGroupIdOverride);
45873
+ }
45874
+ function isStandardDialogueGroupBase(value) {
45875
+ return isDialogueGroupBase(value, 0 /* Standard */);
45876
+ }
45877
+ function isLookupDialogueGroupBase(value) {
45878
+ const v = value;
45879
+ if (!isDialogueGroupBase(value, 1 /* Lookup */)) return false;
45880
+ if (typeof v?.collectionMemberId !== "string") return false;
45881
+ return isOptionalNullableString2(v.collectionValueId);
45882
+ }
45883
+ function isFolderDialogueGroupBase(value) {
45884
+ return isDialogueGroupBase(value, 2 /* Folder */);
45885
+ }
45886
+ function isDialogueGroupProps(value, expectedType) {
45887
+ const v = value;
45888
+ if (!isDialogueGroupBase(value, expectedType)) return false;
45889
+ if (!isWithId(value)) return false;
45890
+ if (!isIWithTimestamps(value)) return false;
45891
+ return typeof v?.projectId === "string";
45892
+ }
45893
+ function isDialogueGroup(value, expectedType) {
45894
+ return isDialogueGroupProps(value, expectedType);
45895
+ }
45896
+ function isAnyDialogueGroup(value) {
45897
+ if (!isDialogueGroup(value)) return false;
45898
+ return isStandardDialogueGroupBase(value) || isLookupDialogueGroupBase(value) || isFolderDialogueGroupBase(value);
45899
+ }
45900
+
45901
+ // ../src/models/dialogue/dialogue-group-language.ts
45902
+ var KINDS = {
45903
+ [0 /* Standard */]: "standard",
45904
+ [1 /* Lookup */]: "lookup",
45905
+ [2 /* Folder */]: "folder"
45906
+ };
45907
+ function storedDialogueGroupSources(groups, memberById, classById) {
45908
+ const sources2 = [];
45909
+ for (const group of groups) {
45910
+ const lookup = group.type === 1 /* Lookup */ ? lookupEntry(group.collectionMemberId, memberById, classById) : void 0;
45911
+ sources2.push({
45912
+ id: group.id,
45913
+ name: group.name,
45914
+ parentId: group.parentDialogueGroupId ?? null,
45915
+ kind: KINDS[group.type],
45916
+ ...lookup ? { lookup } : {}
45917
+ });
45918
+ }
45919
+ return sources2;
45920
+ }
45921
+ function lookupEntry(collectionMemberId, memberById, classById) {
45922
+ const collection = memberById(collectionMemberId);
45923
+ if (!isMemberListBase(collection) && !isMemberDictionaryBase(collection))
45924
+ return void 0;
45925
+ const entry = memberById(collection.entryMemberId);
45926
+ if (!isMemberClassBase(entry)) return void 0;
45927
+ const entryClass = classById(entry.classId);
45928
+ if (!entryClass) return void 0;
45929
+ return {
45930
+ collection: collection.name,
45931
+ entryType: { kind: "named", typeId: entryClass.id },
45932
+ entryTypeName: entryClass.name
45933
+ };
45934
+ }
45935
+
45183
45936
  // ../src/runtime/neoscript/analyzer-types.ts
45184
45937
  var AnalyzerRootClassId = "__root__";
45185
45938
  var AnalyzerDialogueContextClassId = "__dialogue_context__";
@@ -45221,7 +45974,7 @@ function resolveAnalyzerMember(context, member) {
45221
45974
  }
45222
45975
 
45223
45976
  // ../src/runtime/neoscript/neoscript-language-context-adapter.ts
45224
- var NEOSCRIPT_COMPILER_ADAPTER_REVISION = 5;
45977
+ var NEOSCRIPT_COMPILER_ADAPTER_REVISION = 6;
45225
45978
  var UNKNOWN_TYPE = {
45226
45979
  kind: "primitive",
45227
45980
  name: "unknown"
@@ -45398,8 +46151,15 @@ function createNeoScriptProjectInScope(context) {
45398
46151
  })
45399
46152
  });
45400
46153
  }
45401
- const rootType = createRootType2(context);
45402
- languageTypes.push(rootType);
46154
+ const dialogues = neoScriptDialogueTypes(
46155
+ storedDialogueGroupSources(
46156
+ context.vm.dialogueGroups ?? [],
46157
+ (id) => analyzerMemberById(context, id),
46158
+ (id) => analyzerSchemaIndex(context).classesById.get(id)
46159
+ )
46160
+ );
46161
+ const rootType = createRootType2(context, dialogues.member);
46162
+ languageTypes.push(rootType, ...dialogues.types);
45403
46163
  if (context.dialogueContext) {
45404
46164
  languageTypes.push(createDialogueContextType(context));
45405
46165
  }
@@ -45934,7 +46694,7 @@ var ROOT_WRITABILITY = {
45934
46694
  [3 /* Session */]: "session",
45935
46695
  [5 /* User */]: "user"
45936
46696
  };
45937
- function createRootType2(context) {
46697
+ function createRootType2(context, dialogues) {
45938
46698
  const members = [];
45939
46699
  for (const [index, root] of PROJECT_ROOTS.entries()) {
45940
46700
  const name = root.key;
@@ -45959,6 +46719,7 @@ function createRootType2(context) {
45959
46719
  )
45960
46720
  });
45961
46721
  }
46722
+ members.push(dialogues);
45962
46723
  return {
45963
46724
  id: AnalyzerRootClassId,
45964
46725
  name: "Root",
@@ -46061,11 +46822,11 @@ function memberRuntimeType(record4, context, seen = /* @__PURE__ */ new Set(), g
46061
46822
  if (isMemberDialogueLookupBase(member) && isMultiSelectionMember(member)) {
46062
46823
  return {
46063
46824
  kind: "set",
46064
- elementType: primitive2("DialogueRef", true),
46825
+ elementType: primitive2("string", true),
46065
46826
  nullable: !required
46066
46827
  };
46067
46828
  }
46068
- return primitive2("DialogueRef", required);
46829
+ return primitive2("NeoDialogueReference", required);
46069
46830
  case 14 /* Vector2 */:
46070
46831
  return primitive2("Vector2", required);
46071
46832
  case 15 /* Vector2Int */:
@@ -46313,7 +47074,7 @@ function toLanguageType(type, context, genericEnvironment) {
46313
47074
  case 12 /* Audio */:
46314
47075
  return primitive2("AudioClipInfo", required);
46315
47076
  case 18 /* DialogueLookup */:
46316
- return primitive2("DialogueRef", required);
47077
+ return primitive2("NeoDialogueReference", required);
46317
47078
  case 14 /* Vector2 */:
46318
47079
  return primitive2("Vector2", required);
46319
47080
  case 15 /* Vector2Int */:
@@ -46513,7 +47274,9 @@ function projectLanguageVersion(context) {
46513
47274
  ...context.vm.projectFiles ?? [],
46514
47275
  // P43 §6. Editing a constructor's parameters changes what a `new Foo(…)`
46515
47276
  // call site resolves to, so an open editor's cached context must rebuild.
46516
- ...context.constructors ?? []
47277
+ ...context.constructors ?? [],
47278
+ // P105 §2.6. Group names, parents, and kinds shape `root.Dialogues`.
47279
+ ...context.vm.dialogueGroups ?? []
46517
47280
  ];
46518
47281
  return [
46519
47282
  `adapter:${NEOSCRIPT_COMPILER_ADAPTER_REVISION}`,
@@ -46731,6 +47494,7 @@ function createAnalyzerProject(ctx) {
46731
47494
  return {
46732
47495
  project: ctx.project,
46733
47496
  projectFiles: [...ctx.projectFiles ?? []],
47497
+ dialogueGroups: [...ctx.dialogueGroups ?? []],
46734
47498
  members,
46735
47499
  classes: [...ctx.classes],
46736
47500
  enums: [...ctx.enums],
@@ -46975,6 +47739,7 @@ function compileDelegateClosureValue(code, signature) {
46975
47739
  const compiled = compileNSGetter(`return ${code};`, {
46976
47740
  project: signature.project,
46977
47741
  projectFiles: [...signature.projectFiles ?? []],
47742
+ dialogueGroups: signature.dialogueGroups ?? [],
46978
47743
  members: [...signature.members],
46979
47744
  classes: [...signature.classes],
46980
47745
  enums: [...signature.enums],
@@ -47034,6 +47799,7 @@ function compilationProjectContext(args, members = args.members) {
47034
47799
  return {
47035
47800
  project: args.project,
47036
47801
  projectFiles: args.projectFiles ?? [],
47802
+ dialogueGroups: args.dialogueGroups ?? [],
47037
47803
  members: [...members],
47038
47804
  classes: [...args.classes],
47039
47805
  enums: [...args.enums],
@@ -47235,6 +48001,7 @@ function compilationProjectForDocument(document2, state) {
47235
48001
  state.compilationProject ??= createNeoScriptCompilationProject({
47236
48002
  project: document2.project,
47237
48003
  projectFiles: document2.projectFiles,
48004
+ dialogueGroups: document2.dialogueGroups,
47238
48005
  members: document2.members,
47239
48006
  classes: document2.classes,
47240
48007
  enums: document2.enums,
@@ -47329,6 +48096,7 @@ function compileValueInitializerDependency(document2, valueId, compilationProjec
47329
48096
  compileValueRowInitializerBody({
47330
48097
  project: document2.project,
47331
48098
  projectFiles: document2.projectFiles,
48099
+ dialogueGroups: document2.dialogueGroups,
47332
48100
  members: document2.members,
47333
48101
  classes: document2.classes,
47334
48102
  enums: document2.enums,
@@ -47347,6 +48115,7 @@ function compileMemberInitializerDependency(document2, memberId, compilationProj
47347
48115
  const compileArgs = {
47348
48116
  project: document2.project,
47349
48117
  projectFiles: document2.projectFiles,
48118
+ dialogueGroups: document2.dialogueGroups,
47350
48119
  members: document2.members,
47351
48120
  classes: document2.classes,
47352
48121
  enums: document2.enums,
@@ -47495,7 +48264,7 @@ async function restartProjectRead(read) {
47495
48264
  // ../src/models/project/project-types.ts
47496
48265
  function isProject(value) {
47497
48266
  const v = value;
47498
- return typeof v?.name === "string" && typeof v?.id === "string" && isProjectOwner(v.owner) && isActorIdentifier(v.author) && typeof v?.createdAt === "number" && typeof v?.updatedAt === "number" && typeof v?.rootAssetsMemberId === "string" && typeof v?.rootSaveFileMemberId === "string" && typeof v?.rootSessionMemberId === "string" && typeof v?.rootUserMemberId === "string" && isOptionalNullableString2(v.defaultPriorityGroupId) && isOptionalNullableString2(v.defaultTextureTemplateId) && isOptionalNullableString2(v.defaultAudioClipTemplateId) && isProjectExportSettingsOrEmpty(v.exportSettings);
48267
+ return typeof v?.name === "string" && typeof v?.id === "string" && isProjectOwner(v.owner) && isActorIdentifier(v.author) && typeof v?.createdAt === "number" && typeof v?.updatedAt === "number" && typeof v?.rootAssetsMemberId === "string" && typeof v?.rootSaveFileMemberId === "string" && typeof v?.rootSessionMemberId === "string" && typeof v?.rootUserMemberId === "string" && isOptionalNullableString3(v.defaultPriorityGroupId) && isOptionalNullableString3(v.defaultTextureTemplateId) && isOptionalNullableString3(v.defaultAudioClipTemplateId) && isProjectExportSettingsOrEmpty(v.exportSettings);
47499
48268
  }
47500
48269
  function isProjectOwner(value) {
47501
48270
  if (!isActorIdentifier(value)) return false;
@@ -47507,7 +48276,7 @@ function isProjectExportSettingsOrEmpty(value) {
47507
48276
  const settings = value;
47508
48277
  return isUnityExportSettingsOrEmpty(settings.unity);
47509
48278
  }
47510
- function isOptionalNullableString2(value) {
48279
+ function isOptionalNullableString3(value) {
47511
48280
  if (value === void 0) return true;
47512
48281
  if (value === null) return true;
47513
48282
  return typeof value === "string";
@@ -47541,7 +48310,7 @@ function isProjectMigration(value) {
47541
48310
  }
47542
48311
 
47543
48312
  // ../src/models/variants/variants.ts
47544
- function isNonEmptyString(value) {
48313
+ function isNonEmptyString2(value) {
47545
48314
  if (typeof value !== "string") return false;
47546
48315
  return value.length > 0;
47547
48316
  }
@@ -47549,151 +48318,28 @@ function isNeoClassVariant(value) {
47549
48318
  if (typeof value !== "object" || value === null) return false;
47550
48319
  if (Array.isArray(value)) return false;
47551
48320
  const v = value;
47552
- if (!isNonEmptyString(v.id)) return false;
47553
- if (!isNonEmptyString(v.classId)) return false;
47554
- if (!isNonEmptyString(v.name)) return false;
47555
- if (!isNonEmptyString(v.valueId)) return false;
47556
- if (v.folderId !== null && !isNonEmptyString(v.folderId)) return false;
48321
+ if (!isNonEmptyString2(v.id)) return false;
48322
+ if (!isNonEmptyString2(v.classId)) return false;
48323
+ if (!isNonEmptyString2(v.name)) return false;
48324
+ if (!isNonEmptyString2(v.valueId)) return false;
48325
+ if (v.folderId !== null && !isNonEmptyString2(v.folderId)) return false;
47557
48326
  return true;
47558
48327
  }
47559
48328
  function isNeoClassVariantFolder(value) {
47560
48329
  if (typeof value !== "object" || value === null) return false;
47561
48330
  if (Array.isArray(value)) return false;
47562
48331
  const v = value;
47563
- if (!isNonEmptyString(v.id)) return false;
47564
- if (!isNonEmptyString(v.classId)) return false;
48332
+ if (!isNonEmptyString2(v.id)) return false;
48333
+ if (!isNonEmptyString2(v.classId)) return false;
47565
48334
  if (typeof v.path !== "string") return false;
47566
48335
  if (v.binding === void 0) return v.path.length > 0;
47567
48336
  if (typeof v.binding !== "object" || Array.isArray(v.binding)) return false;
47568
48337
  const binding = v.binding;
47569
- if (!isNonEmptyString(binding.collectionMemberId)) return false;
47570
- if (!isNonEmptyString(binding.collectionValueId)) return false;
48338
+ if (!isNonEmptyString2(binding.collectionMemberId)) return false;
48339
+ if (!isNonEmptyString2(binding.collectionValueId)) return false;
47571
48340
  return true;
47572
48341
  }
47573
48342
 
47574
- // ../src/models/dialogue/dialogue-source-identifiers.ts
47575
- function isDialogueSourceIdentifier(value) {
47576
- return isValidProjectSourceIdentifier(value);
47577
- }
47578
-
47579
- // ../src/models/dialogue/logic-types.ts
47580
- function isNSBoolGetter(value) {
47581
- if (!isNSGetter(value)) return false;
47582
- if (value.typeInfo.type !== 1 /* Bool */) return false;
47583
- return value.typeInfo.required === true;
47584
- }
47585
- function isNSVoidBody2(value) {
47586
- if (!isNSGetter(value)) return false;
47587
- if (value.typeInfo.type !== 0 /* Null */) return false;
47588
- return value.typeInfo.required === true;
47589
- }
47590
- function isUILogicCondition(value) {
47591
- const v = value;
47592
- if (typeof v !== "object") return false;
47593
- if (v === null) return false;
47594
- if (!isNonEmptyString2(v.id)) return false;
47595
- if (v.type !== 0 /* UI */) return false;
47596
- if (!isNSBoolGetter(v.getter)) return false;
47597
- return isUIRenderableCondition(v.getter);
47598
- }
47599
- function isCodeLogicCondition(value) {
47600
- const v = value;
47601
- if (typeof v !== "object") return false;
47602
- if (v === null) return false;
47603
- if (!isNonEmptyString2(v.id)) return false;
47604
- if (v.type !== 1 /* Code */) return false;
47605
- if (!isNonEmptyString2(v.sourceFunctionId)) return false;
47606
- if (!isDialogueSourceIdentifier(v.sourceFunctionName)) return false;
47607
- if (typeof v.code !== "string") return false;
47608
- return isNSBoolGetter(v.getter);
47609
- }
47610
- function isLogicCondition(value) {
47611
- return isUILogicCondition(value) || isCodeLogicCondition(value);
47612
- }
47613
- function isUILogicAction(value) {
47614
- const v = value;
47615
- if (typeof v !== "object") return false;
47616
- if (v === null) return false;
47617
- if (v.type !== 0 /* UI */) return false;
47618
- if (!isNSVoidBody2(v.action)) return false;
47619
- return isUIRenderableAction(v.action);
47620
- }
47621
- function isCodeLogicAction(value) {
47622
- const v = value;
47623
- if (typeof v !== "object") return false;
47624
- if (v === null) return false;
47625
- if (v.type !== 1 /* Code */) return false;
47626
- if (!isNonEmptyString2(v.sourceFunctionId)) return false;
47627
- if (!isDialogueSourceIdentifier(v.sourceFunctionName)) return false;
47628
- if (typeof v.code !== "string") return false;
47629
- return isNSVoidBody2(v.action);
47630
- }
47631
- function isNonEmptyString2(value) {
47632
- return typeof value === "string" && value.length > 0;
47633
- }
47634
- function isLogicAction(value) {
47635
- return isUILogicAction(value) || isCodeLogicAction(value);
47636
- }
47637
- function isUIRenderableCondition(getter) {
47638
- if (getter.instructions.length !== 1) return false;
47639
- return getter.instructions[0]?.type === "return" /* return */;
47640
- }
47641
- function isUIRenderableAction(action) {
47642
- if (action.instructions.length === 0) return true;
47643
- if (action.instructions.length !== 1) return false;
47644
- const instruction = action.instructions[0];
47645
- if (!instruction) return false;
47646
- return instruction.type === "return" /* return */ || instruction.type === "assign" /* assign */ || instruction.type === "collectionCall" /* collectionCall */ || instruction.type === "functionCall" /* functionCall */;
47647
- }
47648
-
47649
- // ../src/models/dialogue/dialogue-group-types.ts
47650
- function isOptionalNullableString3(value) {
47651
- if (value === void 0) return true;
47652
- if (value === null) return true;
47653
- return typeof value === "string";
47654
- }
47655
- function isDialogueGroupType(value) {
47656
- return value === 0 /* Standard */ || value === 1 /* Lookup */ || value === 2 /* Folder */;
47657
- }
47658
- function isDialogueGroupBase(value, expectedType) {
47659
- const v = value;
47660
- if (typeof v !== "object") return false;
47661
- if (v === null) return false;
47662
- if (typeof v.name !== "string") return false;
47663
- if (!isDialogueGroupType(v.type)) return false;
47664
- if (expectedType !== void 0 && v.type !== expectedType) return false;
47665
- if (!isOptionalNullableString3(v.parentDialogueGroupId)) return false;
47666
- if (!Array.isArray(v.conditions)) return false;
47667
- if (!v.conditions.every(isLogicCondition)) return false;
47668
- return isOptionalNullableString3(v.priorityGroupIdOverride);
47669
- }
47670
- function isStandardDialogueGroupBase(value) {
47671
- return isDialogueGroupBase(value, 0 /* Standard */);
47672
- }
47673
- function isLookupDialogueGroupBase(value) {
47674
- const v = value;
47675
- if (!isDialogueGroupBase(value, 1 /* Lookup */)) return false;
47676
- if (typeof v?.collectionMemberId !== "string") return false;
47677
- return isOptionalNullableString3(v.collectionValueId);
47678
- }
47679
- function isFolderDialogueGroupBase(value) {
47680
- return isDialogueGroupBase(value, 2 /* Folder */);
47681
- }
47682
- function isDialogueGroupProps(value, expectedType) {
47683
- const v = value;
47684
- if (!isDialogueGroupBase(value, expectedType)) return false;
47685
- if (!isWithId(value)) return false;
47686
- if (!isIWithTimestamps(value)) return false;
47687
- return typeof v?.projectId === "string";
47688
- }
47689
- function isDialogueGroup(value, expectedType) {
47690
- return isDialogueGroupProps(value, expectedType);
47691
- }
47692
- function isAnyDialogueGroup(value) {
47693
- if (!isDialogueGroup(value)) return false;
47694
- return isStandardDialogueGroupBase(value) || isLookupDialogueGroupBase(value) || isFolderDialogueGroupBase(value);
47695
- }
47696
-
47697
48343
  // ../src/models/dialogue/dialogue-types.ts
47698
48344
  function isNonArrayObject(value) {
47699
48345
  if (!isRequiredType(value, isObject)) return false;
@@ -54641,7 +55287,7 @@ var SPECIALIZED_RELATION_KINDS = /* @__PURE__ */ new Set([
54641
55287
 
54642
55288
  // ../packages/manifest/schema-contract/registry.mjs
54643
55289
  var PROJECT_SCHEMA_CONTRACT = Object.freeze({
54644
- cliVersion: "0.72.4",
55290
+ cliVersion: "0.73.0",
54645
55291
  projectFileUploadBatchSize: 32,
54646
55292
  documentRecords: {
54647
55293
  member: {
@@ -56123,6 +56769,7 @@ function createCliNeoScriptContext(options) {
56123
56769
  const vm = {
56124
56770
  project: options.documents.project,
56125
56771
  projectFiles: [...options.documents.projectFiles ?? []],
56772
+ dialogueGroups: [...options.documents.dialogueGroups ?? []],
56126
56773
  members,
56127
56774
  classes: [...options.documents.classes],
56128
56775
  enums: [...options.documents.enums],
@@ -56149,10 +56796,25 @@ function createCliNeoScriptContext(options) {
56149
56796
  // root placement is server context, not authored schema-manifest state.
56150
56797
  roots: compilerContext.project.roots,
56151
56798
  globals: compilerContext.project.globals,
56152
- version: compilerContext.project.version
56799
+ version: compilerContext.project.version,
56800
+ dialogueGroups: cliDialogueGroupSources(options.documents)
56153
56801
  });
56154
56802
  return { ...compilerContext, project: projection.project };
56155
56803
  }
56804
+ function cliDialogueGroupSources(documents) {
56805
+ if (!documents.dialogueGroups?.length) return [];
56806
+ const members = new Map(
56807
+ documents.members.map((member) => [member.id, member])
56808
+ );
56809
+ const classes = new Map(
56810
+ documents.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
56811
+ );
56812
+ return storedDialogueGroupSources(
56813
+ documents.dialogueGroups,
56814
+ (id) => members.get(id),
56815
+ (id) => classes.get(id)
56816
+ );
56817
+ }
56156
56818
  function compileCliNeoScript(uri, source, context, projectIndex) {
56157
56819
  const result = compileNeoScriptStrict(
56158
56820
  {
@@ -56387,7 +57049,7 @@ var WORLD_OBJECT_CONTRACT_WORLD_KINDS = /* @__PURE__ */ new Set([
56387
57049
  ]);
56388
57050
 
56389
57051
  // ../src/models/exports/unity-codegen-revision.ts
56390
- var UNITY_CODEGEN_REVISION = "45a0847addd4616acfc29f142556dcb2e0a27daae14d6aa456430228e66dbc07";
57052
+ var UNITY_CODEGEN_REVISION = "e4a632a177c87244e19da71c9840b8007735773ae5f81578f58ce246ec6cb03d";
56391
57053
 
56392
57054
  // src/export-cache.ts
56393
57055
  var CACHE_BUILD = JSON.stringify([
@@ -56585,6 +57247,7 @@ function sharedEvaluatorBase(rawDocument) {
56585
57247
  variants: document2.variants,
56586
57248
  variantFolders: document2.variantFolders,
56587
57249
  projectFiles: document2.projectFiles,
57250
+ dialogueGroups: document2.dialogueGroups,
56588
57251
  textureTemplates: document2.textureTemplates,
56589
57252
  localizationConfig: document2.localizationConfig,
56590
57253
  localizedTexts: document2.localizedTexts,