@neocompose/cli 0.72.4 → 0.73.1

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