@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.
package/dist/neo.mjs CHANGED
@@ -872,7 +872,42 @@ function generatedCSharpTypeName(value, fallback) {
872
872
  const safe = /^[0-9]/.test(candidate) ? `_${candidate}` : candidate;
873
873
  return isGeneratedCSharpReservedKeyword(safe) ? `${safe}Type` : safe;
874
874
  }
875
- var GENERATED_CSHARP_RESERVED_KEYWORDS, GENERATED_CSHARP_IDENTIFIER_REGEX;
875
+ function generatedCSharpShortId(id2) {
876
+ return id2.replace(/[^A-Za-z0-9_]/g, "").slice(0, 8) || "Id";
877
+ }
878
+ function dialogueGroupReservedNameError(name) {
879
+ const propertyName = generatedCSharpTypeName(name, "DialogueGroup");
880
+ if (!DIALOGUE_GROUP_RESERVED_NAMES.has(propertyName)) return void 0;
881
+ return `Dialogue group name "${name}" is reserved because ${propertyName} is a Dialogues member.`;
882
+ }
883
+ function dialogueGroupPropertyNames(groups, onCollision) {
884
+ const ordered = [...groups].sort(compareGroupIds);
885
+ const used = /* @__PURE__ */ new Set();
886
+ const names = /* @__PURE__ */ new Map();
887
+ for (const group of ordered) {
888
+ const propertyName = generatedCSharpTypeName(group.name, "DialogueGroup");
889
+ if (!used.has(propertyName)) {
890
+ used.add(propertyName);
891
+ names.set(group.id, propertyName);
892
+ continue;
893
+ }
894
+ const uniqueName = `${propertyName}_${generatedCSharpShortId(group.id)}`;
895
+ onCollision?.({
896
+ groupId: group.id,
897
+ groupName: group.name,
898
+ propertyName,
899
+ uniqueName
900
+ });
901
+ names.set(group.id, uniqueName);
902
+ }
903
+ return names;
904
+ }
905
+ function compareGroupIds(left, right) {
906
+ if (left.id < right.id) return -1;
907
+ if (left.id > right.id) return 1;
908
+ return 0;
909
+ }
910
+ var GENERATED_CSHARP_RESERVED_KEYWORDS, GENERATED_CSHARP_IDENTIFIER_REGEX, DIALOGUE_GROUP_RESERVED_NAMES;
876
911
  var init_generated_csharp_identifiers = __esm({
877
912
  "../packages/neoscript-language/src/generated-csharp-identifiers.ts"() {
878
913
  "use strict";
@@ -956,6 +991,239 @@ var init_generated_csharp_identifiers = __esm({
956
991
  "while"
957
992
  ]);
958
993
  GENERATED_CSHARP_IDENTIFIER_REGEX = /^[_A-Za-z][_A-Za-z0-9]*$/;
994
+ DIALOGUE_GROUP_RESERVED_NAMES = /* @__PURE__ */ new Set([
995
+ "TryTrigger",
996
+ "CanTrigger",
997
+ "VisitCount",
998
+ "HasVisited",
999
+ "OnTrigger",
1000
+ "OnEligible",
1001
+ "OnEligibleError"
1002
+ ]);
1003
+ }
1004
+ });
1005
+
1006
+ // ../packages/neoscript-language/src/dialogue-types.ts
1007
+ function renamedDialogueTypeMessage(name, position) {
1008
+ const replacement = RENAMED_DIALOGUE_TYPES.get(name)?.[position];
1009
+ if (replacement === void 0) return void 0;
1010
+ return `\`${name}\` was renamed to \`${replacement}\`.`;
1011
+ }
1012
+ function method(ownerId, name, returnType, parameters, documentation) {
1013
+ return {
1014
+ id: `${ownerId}:${name}`,
1015
+ name,
1016
+ kind: "method",
1017
+ type: returnType,
1018
+ returnType,
1019
+ parameters,
1020
+ documentation
1021
+ };
1022
+ }
1023
+ function neoScriptDialogueReferenceMethods(ownerId) {
1024
+ return [
1025
+ method(
1026
+ ownerId,
1027
+ "TryTrigger",
1028
+ BOOL_TYPE,
1029
+ [ON_FINISH_PARAMETER],
1030
+ "Triggers the referenced dialogue. Returns true when it started or was queued."
1031
+ ),
1032
+ method(
1033
+ ownerId,
1034
+ "CanTrigger",
1035
+ BOOL_TYPE,
1036
+ [],
1037
+ "Checks whether the referenced dialogue's conditions are met, without triggering it."
1038
+ )
1039
+ ];
1040
+ }
1041
+ function rootMethods() {
1042
+ const dialogueId = {
1043
+ name: "dialogueId",
1044
+ type: STRING_TYPE
1045
+ };
1046
+ const pointer = { name: "pointer", type: STRING_TYPE };
1047
+ return [
1048
+ method(
1049
+ NEOSCRIPT_DIALOGUES_TYPE_ID,
1050
+ "TryTrigger",
1051
+ BOOL_TYPE,
1052
+ [dialogueId, ON_FINISH_PARAMETER],
1053
+ "Triggers a direct dialogue. Returns true when it started or was queued."
1054
+ ),
1055
+ method(
1056
+ NEOSCRIPT_DIALOGUES_TYPE_ID,
1057
+ "CanTrigger",
1058
+ BOOL_TYPE,
1059
+ [dialogueId],
1060
+ "Checks whether a direct dialogue's conditions are met, without triggering it."
1061
+ ),
1062
+ method(
1063
+ NEOSCRIPT_DIALOGUES_TYPE_ID,
1064
+ "VisitCount",
1065
+ INT_TYPE,
1066
+ [pointer],
1067
+ "Returns how many times a dialogue or text node was visited."
1068
+ ),
1069
+ method(
1070
+ NEOSCRIPT_DIALOGUES_TYPE_ID,
1071
+ "HasVisited",
1072
+ BOOL_TYPE,
1073
+ [pointer],
1074
+ "Returns whether a dialogue or text node was visited."
1075
+ )
1076
+ ];
1077
+ }
1078
+ function groupMethods(typeId, receiver) {
1079
+ if (receiver.kind === "standard") {
1080
+ return [
1081
+ method(
1082
+ typeId,
1083
+ "TryTrigger",
1084
+ BOOL_TYPE,
1085
+ [ON_FINISH_PARAMETER],
1086
+ "Triggers this group's highest-priority eligible dialogue. Returns true when it started or was queued."
1087
+ ),
1088
+ method(
1089
+ typeId,
1090
+ "CanTrigger",
1091
+ BOOL_TYPE,
1092
+ [],
1093
+ "Checks whether this group has an eligible dialogue, without triggering it."
1094
+ )
1095
+ ];
1096
+ }
1097
+ if (receiver.kind !== "lookup" || receiver.entryType === void 0) return [];
1098
+ const value = {
1099
+ name: "value",
1100
+ type: receiver.entryType
1101
+ };
1102
+ return [
1103
+ method(
1104
+ typeId,
1105
+ "TryTrigger",
1106
+ BOOL_TYPE,
1107
+ [value, ON_FINISH_PARAMETER],
1108
+ "Triggers the highest-priority eligible dialogue for the lookup value. Returns true when it started or was queued."
1109
+ ),
1110
+ method(
1111
+ typeId,
1112
+ "CanTrigger",
1113
+ BOOL_TYPE,
1114
+ [value],
1115
+ "Checks whether the lookup value has an eligible dialogue, without triggering it."
1116
+ )
1117
+ ];
1118
+ }
1119
+ function neoScriptDialogueTypes(groups) {
1120
+ const names = dialogueGroupPropertyNames(groups);
1121
+ const children = /* @__PURE__ */ new Map();
1122
+ for (const group of groups) {
1123
+ const siblings = children.get(group.parentId);
1124
+ if (siblings === void 0) children.set(group.parentId, [group]);
1125
+ else siblings.push(group);
1126
+ }
1127
+ const rootPath = `root.${NEOSCRIPT_DIALOGUES_MEMBER_NAME}`;
1128
+ const types = [];
1129
+ const typeFor = (parentId, path) => {
1130
+ const members = [];
1131
+ for (const group of children.get(parentId) ?? []) {
1132
+ const name = names.get(group.id);
1133
+ const groupPath = `${path}.${name}`;
1134
+ const typeId = `${NEOSCRIPT_DIALOGUES_TYPE_ID}:${group.id}`;
1135
+ const receiver = {
1136
+ kind: group.kind,
1137
+ path: groupPath,
1138
+ groupId: group.id,
1139
+ ...group.lookup ? { entryType: group.lookup.entryType } : {}
1140
+ };
1141
+ const lookup = group.lookup ? ` Looks up ${group.lookup.entryTypeName} in \`${group.lookup.collection}\`.` : "";
1142
+ const documentation = `${KIND_LABELS[group.kind]} \`${groupPath}\`.${lookup}`;
1143
+ types.push({
1144
+ id: typeId,
1145
+ name: groupPath,
1146
+ kind: "synthetic",
1147
+ documentation,
1148
+ dialogues: receiver,
1149
+ members: [
1150
+ ...typeFor(group.id, groupPath),
1151
+ ...groupMethods(typeId, receiver)
1152
+ ]
1153
+ });
1154
+ members.push({
1155
+ id: `${typeId}:member`,
1156
+ name,
1157
+ kind: "property",
1158
+ type: { kind: "named", typeId },
1159
+ documentation,
1160
+ detail: KIND_LABELS[group.kind],
1161
+ writable: false,
1162
+ writability: "readOnly",
1163
+ ...group.location ? { location: group.location } : {},
1164
+ ...group.selectionLocation ? { selectionLocation: group.selectionLocation } : {}
1165
+ });
1166
+ }
1167
+ return members;
1168
+ };
1169
+ const topLevel = typeFor(null, rootPath);
1170
+ types.push({
1171
+ id: NEOSCRIPT_DIALOGUES_TYPE_ID,
1172
+ name: rootPath,
1173
+ kind: "synthetic",
1174
+ documentation: "The project's dialogues and dialogue groups, the same paths as the generated C# Dialogues.",
1175
+ dialogues: { kind: "root", path: rootPath },
1176
+ members: [...topLevel, ...rootMethods()]
1177
+ });
1178
+ return {
1179
+ member: {
1180
+ id: `${NEOSCRIPT_DIALOGUES_TYPE_ID}:member`,
1181
+ name: NEOSCRIPT_DIALOGUES_MEMBER_NAME,
1182
+ kind: "property",
1183
+ type: { kind: "named", typeId: NEOSCRIPT_DIALOGUES_TYPE_ID },
1184
+ documentation: "The project's dialogues. Trigger them, check them, and read dialogue memory.",
1185
+ writable: false,
1186
+ writability: "readOnly"
1187
+ },
1188
+ types
1189
+ };
1190
+ }
1191
+ var NEOSCRIPT_DIALOGUES_MEMBER_NAME, NEOSCRIPT_DIALOGUES_TYPE_ID, RENAMED_DIALOGUE_TYPES, BOOL_TYPE, INT_TYPE, STRING_TYPE, NEOSCRIPT_DIALOGUE_ON_FINISH_TYPE, ON_FINISH_PARAMETER, KIND_LABELS;
1192
+ var init_dialogue_types = __esm({
1193
+ "../packages/neoscript-language/src/dialogue-types.ts"() {
1194
+ "use strict";
1195
+ init_generated_csharp_identifiers();
1196
+ NEOSCRIPT_DIALOGUES_MEMBER_NAME = "Dialogues";
1197
+ NEOSCRIPT_DIALOGUES_TYPE_ID = "builtin:Dialogues";
1198
+ RENAMED_DIALOGUE_TYPES = /* @__PURE__ */ new Map([
1199
+ ["Dialogue", { base: "NeoDialogue", value: "NeoDialogueReference" }],
1200
+ [
1201
+ "DialogueRef",
1202
+ { base: "NeoDialogueReference", value: "NeoDialogueReference" }
1203
+ ],
1204
+ ["DialogueGroup", { base: "NeoDialogueGroup", value: "NeoDialogueGroup" }],
1205
+ ["PriorityGroup", { base: "NeoPriorityGroup", value: "NeoPriorityGroup" }]
1206
+ ]);
1207
+ BOOL_TYPE = { kind: "primitive", name: "bool" };
1208
+ INT_TYPE = { kind: "primitive", name: "int" };
1209
+ STRING_TYPE = { kind: "primitive", name: "string" };
1210
+ NEOSCRIPT_DIALOGUE_ON_FINISH_TYPE = {
1211
+ kind: "delegate",
1212
+ returnType: { kind: "primitive", name: "void" },
1213
+ parameterTypes: [],
1214
+ nullable: true
1215
+ };
1216
+ ON_FINISH_PARAMETER = {
1217
+ name: "onFinish",
1218
+ type: NEOSCRIPT_DIALOGUE_ON_FINISH_TYPE,
1219
+ defaultValue: { displayText: "null", value: null },
1220
+ documentation: "Runs once the dialogue ends, whether it finished, failed, or was disposed."
1221
+ };
1222
+ KIND_LABELS = {
1223
+ standard: "Dialogue group",
1224
+ lookup: "Lookup dialogue group",
1225
+ folder: "Dialogue folder"
1226
+ };
959
1227
  }
960
1228
  });
961
1229
 
@@ -1073,10 +1341,11 @@ function vectorTypes() {
1073
1341
  members: structuredLeafFieldProperties(name)
1074
1342
  }));
1075
1343
  }
1076
- var NEO_PROJECT_IGNORED_DIRECTORY_NAMES, NEOSCRIPT_KEYWORDS, NEOSCRIPT_INFERRED_LOCAL_KEYWORD, NEOSCRIPT_CONSTRUCTOR_KEYWORD, NEOSCRIPT_PRIMITIVE_TYPES, NEOSCRIPT_BUILTIN_ANNOTATION_TYPES, NEOSCRIPT_BUILTIN_NAMESPACES, NEOSCRIPT_BUILTIN_TYPES, NEO_VARIANT_TYPE_NAME, NEO_VARIANT_FOLDER_TYPE_NAME, NEO_LOOKUP_VARIANT_TYPE_NAME, NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME, NEO_VARIANT_SCOPE_NAME, NEO_VARIANT_RESERVED_NAME, NEO_VARIANT_FOLDER_PATH_SEPARATOR, NEOSCRIPT_OPERATORS, STRING_TYPE, INT_TYPE, FLOAT_TYPE, BOOL_TYPE, IMAGE_REF_TYPE, SPRITE_INFO_TYPE, FLOAT_OPTIONAL_TYPE, NEOSCRIPT_STRUCTURED_LEAF_FIELDS, NEOSCRIPT_IMAGE_REGISTRY_TYPE, NEOSCRIPT_AUDIO_CLIP_REGISTRY_TYPE, NEOSCRIPT_PENDING_SYMBOL_ID_PREFIX, REGISTRY_ENTRY_TYPES, NEOSCRIPT_GLOBALS, NEOSCRIPT_SPRITE_INFO_EMPTY_MEMBER_ID, NEOSCRIPT_SPRITE_INFO_EMPTY_VALUE, NEOSCRIPT_MATH_TYPE_ID, MATH_INFERENCE_RULE, MATH_INTEGRAL_RULE, NEOSCRIPT_LIST_TYPE_NAME, NEOSCRIPT_LIST_TYPE_ID, NEOSCRIPT_LIST_REPEAT_NAME, LIST_ENTRY_TYPE, NEOSCRIPT_BUILTIN_TYPE_SYMBOLS;
1344
+ var NEO_PROJECT_IGNORED_DIRECTORY_NAMES, NEOSCRIPT_KEYWORDS, NEOSCRIPT_INFERRED_LOCAL_KEYWORD, NEOSCRIPT_CONSTRUCTOR_KEYWORD, NEOSCRIPT_PRIMITIVE_TYPES, NEOSCRIPT_BUILTIN_ANNOTATION_TYPES, NEOSCRIPT_BUILTIN_NAMESPACES, NEOSCRIPT_BUILTIN_TYPES, NEO_VARIANT_TYPE_NAME, NEO_VARIANT_FOLDER_TYPE_NAME, NEO_LOOKUP_VARIANT_TYPE_NAME, NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME, NEO_VARIANT_SCOPE_NAME, NEO_VARIANT_RESERVED_NAME, NEO_VARIANT_FOLDER_PATH_SEPARATOR, NEOSCRIPT_OPERATORS, STRING_TYPE2, INT_TYPE2, FLOAT_TYPE, BOOL_TYPE2, IMAGE_REF_TYPE, SPRITE_INFO_TYPE, FLOAT_OPTIONAL_TYPE, NEOSCRIPT_STRUCTURED_LEAF_FIELDS, NEOSCRIPT_IMAGE_REGISTRY_TYPE, NEOSCRIPT_AUDIO_CLIP_REGISTRY_TYPE, NEOSCRIPT_PENDING_SYMBOL_ID_PREFIX, REGISTRY_ENTRY_TYPES, NEOSCRIPT_GLOBALS, NEOSCRIPT_SPRITE_INFO_EMPTY_MEMBER_ID, NEOSCRIPT_SPRITE_INFO_EMPTY_VALUE, NEOSCRIPT_MATH_TYPE_ID, MATH_INFERENCE_RULE, MATH_INTEGRAL_RULE, NEOSCRIPT_LIST_TYPE_NAME, NEOSCRIPT_LIST_TYPE_ID, NEOSCRIPT_LIST_REPEAT_NAME, LIST_ENTRY_TYPE, NEOSCRIPT_BUILTIN_TYPE_SYMBOLS;
1077
1345
  var init_language_spec = __esm({
1078
1346
  "../packages/neoscript-language/src/language-spec.ts"() {
1079
1347
  "use strict";
1348
+ init_dialogue_types();
1080
1349
  NEO_PROJECT_IGNORED_DIRECTORY_NAMES = /* @__PURE__ */ new Set(
1081
1350
  [
1082
1351
  ".git",
@@ -1147,7 +1416,7 @@ var init_language_spec = __esm({
1147
1416
  "FunctionRef",
1148
1417
  "NeoDelegate",
1149
1418
  "NeoAction",
1150
- "Dialogue",
1419
+ "NeoDialogue",
1151
1420
  "Trigger",
1152
1421
  "Node",
1153
1422
  "Text",
@@ -1157,7 +1426,7 @@ var init_language_spec = __esm({
1157
1426
  "Outcome",
1158
1427
  "SpriteInfo",
1159
1428
  "AudioClipInfo",
1160
- "DialogueRef",
1429
+ "NeoDialogueReference",
1161
1430
  "Vector2",
1162
1431
  "Vector2Int",
1163
1432
  "Vector3",
@@ -1206,10 +1475,10 @@ var init_language_spec = __esm({
1206
1475
  "<",
1207
1476
  ">"
1208
1477
  ];
1209
- STRING_TYPE = { kind: "primitive", name: "string" };
1210
- INT_TYPE = { kind: "primitive", name: "int" };
1478
+ STRING_TYPE2 = { kind: "primitive", name: "string" };
1479
+ INT_TYPE2 = { kind: "primitive", name: "int" };
1211
1480
  FLOAT_TYPE = { kind: "primitive", name: "float" };
1212
- BOOL_TYPE = { kind: "primitive", name: "bool" };
1481
+ BOOL_TYPE2 = { kind: "primitive", name: "bool" };
1213
1482
  IMAGE_REF_TYPE = {
1214
1483
  kind: "primitive",
1215
1484
  name: "ImageRef"
@@ -1234,7 +1503,7 @@ var init_language_spec = __esm({
1234
1503
  {
1235
1504
  name: "SliceIndex",
1236
1505
  key: "sliceIndex",
1237
- type: INT_TYPE,
1506
+ type: INT_TYPE2,
1238
1507
  documentation: "Index into the file's slices."
1239
1508
  }
1240
1509
  ],
@@ -1256,13 +1525,13 @@ var init_language_spec = __esm({
1256
1525
  {
1257
1526
  name: "x",
1258
1527
  key: "x",
1259
- type: INT_TYPE,
1528
+ type: INT_TYPE2,
1260
1529
  documentation: "Vector2Int x component."
1261
1530
  },
1262
1531
  {
1263
1532
  name: "y",
1264
1533
  key: "y",
1265
- type: INT_TYPE,
1534
+ type: INT_TYPE2,
1266
1535
  documentation: "Vector2Int y component."
1267
1536
  }
1268
1537
  ],
@@ -1290,19 +1559,19 @@ var init_language_spec = __esm({
1290
1559
  {
1291
1560
  name: "x",
1292
1561
  key: "x",
1293
- type: INT_TYPE,
1562
+ type: INT_TYPE2,
1294
1563
  documentation: "Vector3Int x component."
1295
1564
  },
1296
1565
  {
1297
1566
  name: "y",
1298
1567
  key: "y",
1299
- type: INT_TYPE,
1568
+ type: INT_TYPE2,
1300
1569
  documentation: "Vector3Int y component."
1301
1570
  },
1302
1571
  {
1303
1572
  name: "z",
1304
1573
  key: "z",
1305
- type: INT_TYPE,
1574
+ type: INT_TYPE2,
1306
1575
  documentation: "Vector3Int z component."
1307
1576
  }
1308
1577
  ],
@@ -1349,14 +1618,14 @@ var init_language_spec = __esm({
1349
1618
  NEOSCRIPT_GLOBALS = [
1350
1619
  builtinFunction(
1351
1620
  "VisitCount",
1352
- INT_TYPE,
1353
- [parameter("pointer", STRING_TYPE)],
1621
+ INT_TYPE2,
1622
+ [parameter("pointer", STRING_TYPE2)],
1354
1623
  "Returns the number of visits recorded for a dialogue pointer."
1355
1624
  ),
1356
1625
  builtinFunction(
1357
1626
  "HasVisited",
1358
- BOOL_TYPE,
1359
- [parameter("pointer", STRING_TYPE)],
1627
+ BOOL_TYPE2,
1628
+ [parameter("pointer", STRING_TYPE2)],
1360
1629
  "Returns whether a dialogue pointer has been visited."
1361
1630
  )
1362
1631
  ];
@@ -1395,8 +1664,8 @@ var init_language_spec = __esm({
1395
1664
  // `FileId` and `SliceIndex` come from the field table above — they are
1396
1665
  // the writable, addressable fields, not derived properties (D11).
1397
1666
  ...structuredLeafFieldProperties("SpriteInfo"),
1398
- property("SpriteInfo", "FileName", STRING_TYPE, "Asset file name."),
1399
- property("SpriteInfo", "Name", STRING_TYPE, "Sprite name."),
1667
+ property("SpriteInfo", "FileName", STRING_TYPE2, "Asset file name."),
1668
+ property("SpriteInfo", "Name", STRING_TYPE2, "Sprite name."),
1400
1669
  property(
1401
1670
  "SpriteInfo",
1402
1671
  "Size",
@@ -1426,8 +1695,8 @@ var init_language_spec = __esm({
1426
1695
  name: "AudioClipInfo",
1427
1696
  kind: "builtin",
1428
1697
  members: [
1429
- property("AudioClipInfo", "FileId", STRING_TYPE, "Asset file id."),
1430
- property("AudioClipInfo", "Name", STRING_TYPE, "Audio clip name."),
1698
+ property("AudioClipInfo", "FileId", STRING_TYPE2, "Asset file id."),
1699
+ property("AudioClipInfo", "Name", STRING_TYPE2, "Audio clip name."),
1431
1700
  property(
1432
1701
  "AudioClipInfo",
1433
1702
  "DurationSeconds",
@@ -1437,10 +1706,13 @@ var init_language_spec = __esm({
1437
1706
  ]
1438
1707
  },
1439
1708
  {
1440
- id: "builtin:DialogueRef",
1441
- name: "DialogueRef",
1709
+ id: "builtin:NeoDialogueReference",
1710
+ name: "NeoDialogueReference",
1442
1711
  kind: "builtin",
1443
- members: [property("DialogueRef", "id", STRING_TYPE, "Dialogue id.")]
1712
+ members: [
1713
+ property("NeoDialogueReference", "id", STRING_TYPE2, "Dialogue id."),
1714
+ ...neoScriptDialogueReferenceMethods("builtin:NeoDialogueReference")
1715
+ ]
1444
1716
  },
1445
1717
  ...vectorTypes(),
1446
1718
  {
@@ -1462,7 +1734,7 @@ var init_language_spec = __esm({
1462
1734
  returnType: { kind: "primitive", name: "void" },
1463
1735
  static: true,
1464
1736
  parameters: [
1465
- ...name === "Assert" ? [parameter("condition", BOOL_TYPE)] : [],
1737
+ ...name === "Assert" ? [parameter("condition", BOOL_TYPE2)] : [],
1466
1738
  parameter("message", { kind: "primitive", name: "unknown" })
1467
1739
  ],
1468
1740
  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."
@@ -1493,25 +1765,25 @@ var init_language_spec = __esm({
1493
1765
  "Round",
1494
1766
  ["x"],
1495
1767
  `Rounds to the nearest integer; midpoints round to even (banker's rounding). ${MATH_INTEGRAL_RULE}`,
1496
- INT_TYPE
1768
+ INT_TYPE2
1497
1769
  ),
1498
1770
  mathFunction(
1499
1771
  "Floor",
1500
1772
  ["x"],
1501
1773
  `Rounds toward negative infinity. ${MATH_INTEGRAL_RULE}`,
1502
- INT_TYPE
1774
+ INT_TYPE2
1503
1775
  ),
1504
1776
  mathFunction(
1505
1777
  "Ceiling",
1506
1778
  ["x"],
1507
1779
  `Rounds toward positive infinity. ${MATH_INTEGRAL_RULE}`,
1508
- INT_TYPE
1780
+ INT_TYPE2
1509
1781
  ),
1510
1782
  mathFunction(
1511
1783
  "Truncate",
1512
1784
  ["x"],
1513
1785
  `Rounds toward zero. ${MATH_INTEGRAL_RULE}`,
1514
- INT_TYPE
1786
+ INT_TYPE2
1515
1787
  ),
1516
1788
  mathFunction(
1517
1789
  "Abs",
@@ -1522,7 +1794,7 @@ var init_language_spec = __esm({
1522
1794
  "Sign",
1523
1795
  ["x"],
1524
1796
  "Returns -1, 0, or 1 for a negative, zero, or positive value. Accepts int, float, or decimal and always returns int.",
1525
- INT_TYPE
1797
+ INT_TYPE2
1526
1798
  ),
1527
1799
  mathFunction(
1528
1800
  "Sqrt",
@@ -1563,7 +1835,7 @@ var init_language_spec = __esm({
1563
1835
  returnType: { kind: "list", elementType: LIST_ENTRY_TYPE },
1564
1836
  parameters: [
1565
1837
  parameter("value", LIST_ENTRY_TYPE),
1566
- parameter("count", INT_TYPE)
1838
+ parameter("count", INT_TYPE2)
1567
1839
  ],
1568
1840
  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.",
1569
1841
  static: true
@@ -1675,12 +1947,17 @@ var init_debug_info = __esm({
1675
1947
  });
1676
1948
 
1677
1949
  // ../packages/neoscript-language/src/strict-ir.ts
1678
- var NEOSCRIPT_COMPILER_REVISION;
1950
+ var NEOSCRIPT_COMPILER_REVISION, NeoScriptDialogueOp;
1679
1951
  var init_strict_ir = __esm({
1680
1952
  "../packages/neoscript-language/src/strict-ir.ts"() {
1681
1953
  "use strict";
1682
1954
  init_debug_info();
1683
1955
  NEOSCRIPT_COMPILER_REVISION = 17;
1956
+ NeoScriptDialogueOp = /* @__PURE__ */ ((NeoScriptDialogueOp2) => {
1957
+ NeoScriptDialogueOp2["TryTrigger"] = "TryTrigger";
1958
+ NeoScriptDialogueOp2["CanTrigger"] = "CanTrigger";
1959
+ return NeoScriptDialogueOp2;
1960
+ })(NeoScriptDialogueOp || {});
1684
1961
  }
1685
1962
  });
1686
1963
 
@@ -2580,6 +2857,31 @@ function isNSFunctionHasVisited(value) {
2580
2857
  const v = value;
2581
2858
  return v?.type === "hasVisited" /* hasVisited */ && isNSDialogueMemoryFunctionInfo(v.info);
2582
2859
  }
2860
+ function isNSDialogueOp(value) {
2861
+ return value === "TryTrigger" || value === "CanTrigger";
2862
+ }
2863
+ function isOptionalNSPointer(value) {
2864
+ return value === void 0 || isNSPointer(value);
2865
+ }
2866
+ function isNSFunctionDialogueGroup(value) {
2867
+ const v = value;
2868
+ if (v?.type !== "dialogueGroup" /* dialogueGroup */) return false;
2869
+ const info = v.info;
2870
+ if (typeof info !== "object" || info === null) return false;
2871
+ if (!isNSDialogueOp(Reflect.get(info, "op"))) return false;
2872
+ if (typeof Reflect.get(info, "groupId") !== "string") return false;
2873
+ if (!isOptionalNSPointer(Reflect.get(info, "valuePointer"))) return false;
2874
+ return isOptionalNSPointer(Reflect.get(info, "onFinishPointer"));
2875
+ }
2876
+ function isNSFunctionDialogue(value) {
2877
+ const v = value;
2878
+ if (v?.type !== "dialogue" /* dialogue */) return false;
2879
+ const info = v.info;
2880
+ if (typeof info !== "object" || info === null) return false;
2881
+ if (!isNSDialogueOp(Reflect.get(info, "op"))) return false;
2882
+ if (!isNSPointer(Reflect.get(info, "dialogueIdPointer"))) return false;
2883
+ return isOptionalNSPointer(Reflect.get(info, "onFinishPointer"));
2884
+ }
2583
2885
  function isNSVectorConstructorType(value) {
2584
2886
  return value === 14 /* Vector2 */ || value === 15 /* Vector2Int */ || value === 16 /* Vector3 */ || value === 17 /* Vector3Int */;
2585
2887
  }
@@ -2639,7 +2941,7 @@ function isNSFunction(value) {
2639
2941
  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
2640
2942
  // compiled getter using ToLower()/StartsWith() would fail pointer
2641
2943
  // validation anywhere isNSFunction gates. Fixed alongside decimalOp.
2642
- isNSFunctionStringOp(value) || isNSFunctionDecimalOp(value) || isNSFunctionMathOp(value) || isNSFunctionListRepeat(value) || isNSFunctionCount(value) || isNSFunctionVisitCount(value) || isNSFunctionHasVisited(value) || isNSFunctionVectorConstructor(value) || isNSFunctionImageSlice(value) || isNSFunctionVariantInitialize(value) || isNSFunctionVariantApply(value) || isNSFunctionDeclaredConstructor(value);
2944
+ 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);
2643
2945
  }
2644
2946
  function isNSInstructionVariable(value) {
2645
2947
  const v = value;
@@ -15178,13 +15480,13 @@ function firstTokenAfter(tokens, offset) {
15178
15480
  function validateDocumentShape(kind, declarations, diagnostics) {
15179
15481
  if (kind === "definition") {
15180
15482
  for (const declaration2 of declarations) {
15181
- if (declaration2.kind === "class" && declaration2.baseTypes.some((type) => type.name === "Dialogue")) {
15483
+ if (declaration2.kind === "class" && declaration2.baseTypes.some((type) => type.name === "NeoDialogue")) {
15182
15484
  diagnostics.push({
15183
15485
  range: declaration2.nameRange,
15184
15486
  severity: "error",
15185
15487
  source: "neo-project",
15186
15488
  code: "dialogue-class-in-definition",
15187
- message: "A class that directly derives from `Dialogue` belongs in a `.neoflow` file."
15489
+ message: "A class that directly derives from `NeoDialogue` belongs in a `.neoflow` file."
15188
15490
  });
15189
15491
  }
15190
15492
  }
@@ -15196,7 +15498,7 @@ function validateDocumentShape(kind, declarations, diagnostics) {
15196
15498
  severity: "error",
15197
15499
  source: "neo-project",
15198
15500
  code: "neoflow-single-dialogue-class",
15199
- message: "A `.neoflow` file must contain exactly one sealed class that directly derives from `Dialogue`."
15501
+ message: "A `.neoflow` file must contain exactly one sealed class that directly derives from `NeoDialogue`."
15200
15502
  });
15201
15503
  return;
15202
15504
  }
@@ -15219,13 +15521,13 @@ function validateDocumentShape(kind, declarations, diagnostics) {
15219
15521
  message: "A `.neoflow` dialogue class cannot be generic."
15220
15522
  });
15221
15523
  }
15222
- if (declaration.baseTypes.length !== 1 || declaration.baseTypes[0]?.name !== "Dialogue") {
15524
+ if (declaration.baseTypes.length !== 1 || declaration.baseTypes[0]?.name !== "NeoDialogue") {
15223
15525
  diagnostics.push({
15224
15526
  range: declaration.nameRange,
15225
15527
  severity: "error",
15226
15528
  source: "neo-project",
15227
15529
  code: "neoflow-dialogue-base",
15228
- message: "A `.neoflow` class must directly derive from the system `Dialogue` type."
15530
+ message: "A `.neoflow` class must directly derive from the system `NeoDialogue` type."
15229
15531
  });
15230
15532
  }
15231
15533
  addIncompleteDraftDiagnostic(declaration.annotations, diagnostics);
@@ -16124,7 +16426,7 @@ var init_project_source_parser = __esm({
16124
16426
  this.expect("=");
16125
16427
  const initializerStart = this.cursor;
16126
16428
  const initializer = this.captureInitializer();
16127
- const dialogueGroup = type.name === "DialogueGroup" ? this.parseDialogueGroupBody(initializerStart, initializer) : void 0;
16429
+ const dialogueGroup = type.name === "NeoDialogueGroup" ? this.parseDialogueGroupBody(initializerStart, initializer) : void 0;
16128
16430
  this.reportNestedTypes(initializer);
16129
16431
  return {
16130
16432
  kind: "global",
@@ -16157,7 +16459,7 @@ var init_project_source_parser = __esm({
16157
16459
  while (!this.done() && !this.at("}") && !this.at("when") && this.cursor < end) {
16158
16460
  const before = this.cursor;
16159
16461
  try {
16160
- const member = this.parseMember("DialogueGroup", "class");
16462
+ const member = this.parseMember("NeoDialogueGroup", "class");
16161
16463
  if (member?.kind === "function") functions.push(member);
16162
16464
  } catch (error) {
16163
16465
  this.report(error);
@@ -18803,8 +19105,8 @@ var init_project_local_values = __esm({
18803
19105
  "AudioClipRegistry",
18804
19106
  "NeoImage",
18805
19107
  "NeoAudioClip",
18806
- "PriorityGroup",
18807
- "DialogueGroup",
19108
+ "NeoPriorityGroup",
19109
+ "NeoDialogueGroup",
18808
19110
  "Migration"
18809
19111
  ]);
18810
19112
  }
@@ -23079,26 +23381,13 @@ function buildDialogueGroupClassNameMap(groups, diagnostics) {
23079
23381
  return names;
23080
23382
  }
23081
23383
  function buildDialogueGroupPropertyNameMap(groups, diagnostics) {
23082
- const used = /* @__PURE__ */ new Map();
23083
- const names = /* @__PURE__ */ new Map();
23084
- for (const group of groups) {
23085
- const baseName = toCSharpTypeName(group.name, "DialogueGroup");
23086
- const safeName = isCSharpReservedKeyword(baseName) ? `${baseName}Value` : baseName;
23087
- const existing = used.get(safeName);
23088
- if (existing === void 0) {
23089
- used.set(safeName, group.id);
23090
- names.set(group.id, safeName);
23091
- continue;
23092
- }
23093
- const uniqueName = `${safeName}_${shortId(group.id)}`;
23384
+ return dialogueGroupPropertyNames(groups, (collision) => {
23094
23385
  diagnostics.push({
23095
23386
  severity: "warning",
23096
- message: `Generated C# dialogue group property "${safeName}" is duplicated; using "${uniqueName}" for "${group.name}".`,
23097
- path: `dialogueGroups.${group.id}.name`
23387
+ message: `Generated C# dialogue group property "${collision.propertyName}" is duplicated; using "${collision.uniqueName}" for "${collision.groupName}".`,
23388
+ path: `dialogueGroups.${collision.groupId}.name`
23098
23389
  });
23099
- names.set(group.id, uniqueName);
23100
- }
23101
- return names;
23390
+ });
23102
23391
  }
23103
23392
  function getExtendsClassId(classDef) {
23104
23393
  const value = classDef.extendsClassId;
@@ -25073,7 +25362,7 @@ function resolveLookupEntryMember(ctx, member) {
25073
25362
  return null;
25074
25363
  }
25075
25364
  function shortId(id2) {
25076
- return id2.replace(/[^A-Za-z0-9_]/g, "").slice(0, 8) || "Id";
25365
+ return generatedCSharpShortId(id2);
25077
25366
  }
25078
25367
  function variantTargetCSharpType(ctx, member, env) {
25079
25368
  const target = member.targetTypeInfo;
@@ -25163,6 +25452,7 @@ var init_unity_member_signatures = __esm({
25163
25452
  "use strict";
25164
25453
  init_neoscript_pattern_bindings();
25165
25454
  init_cell_pattern();
25455
+ init_generated_csharp_identifiers();
25166
25456
  init_members();
25167
25457
  init_world_system_classes();
25168
25458
  init_classes();
@@ -26905,7 +27195,7 @@ function sourceDialogueGroups(source) {
26905
27195
  const options = /* @__PURE__ */ new Map();
26906
27196
  for (const symbol of source.symbols) {
26907
27197
  if (symbol.kind !== "global") continue;
26908
- if (symbol.detail !== "DialogueGroup" && symbol.detail !== "PriorityGroup")
27198
+ if (symbol.detail !== "NeoDialogueGroup" && symbol.detail !== "NeoPriorityGroup")
26909
27199
  continue;
26910
27200
  const id2 = symbol.id ?? `${symbol.location.uri}#${symbol.name}`;
26911
27201
  globals.set(symbol.name, id2);
@@ -26928,7 +27218,7 @@ function sourceDialogueGroups(source) {
26928
27218
  for (const declaration of document.declarations) {
26929
27219
  if (declaration.kind !== "global") continue;
26930
27220
  const type = declaration.type.name;
26931
- if (type !== "DialogueGroup" && type !== "Project") continue;
27221
+ if (type !== "NeoDialogueGroup" && type !== "Project") continue;
26932
27222
  const args = constructorArgs(
26933
27223
  declaration.dialogueGroup?.constructor.text ?? declaration.initializer.text
26934
27224
  );
@@ -27009,12 +27299,30 @@ function validateDialogueGroupPaths(source) {
27009
27299
  }
27010
27300
  return diagnostics;
27011
27301
  }
27302
+ function validateDialogueGroupNames(source) {
27303
+ const diagnostics = [];
27304
+ const catalog = sourceDialogueGroups(source);
27305
+ for (const group of catalog.paths.byId.values()) {
27306
+ const message = dialogueGroupReservedNameError(group.name);
27307
+ const symbol = catalog.symbols.get(group.id);
27308
+ if (message === void 0 || symbol === void 0) continue;
27309
+ diagnostics.push({
27310
+ uri: symbol.location.uri,
27311
+ severity: "error",
27312
+ code: "reserved-dialogue-group-name",
27313
+ message,
27314
+ range: symbol.location.range
27315
+ });
27316
+ }
27317
+ return diagnostics;
27318
+ }
27012
27319
  var catalogs;
27013
27320
  var init_project_source_dialogue_groups = __esm({
27014
27321
  "../packages/neoscript-language/src/project-source-dialogue-groups.ts"() {
27015
27322
  "use strict";
27016
27323
  init_dialogue_group_paths();
27017
27324
  init_executable_parser();
27325
+ init_generated_csharp_identifiers();
27018
27326
  catalogs = /* @__PURE__ */ new WeakMap();
27019
27327
  }
27020
27328
  });
@@ -29640,6 +29948,43 @@ function enumLiteralKeyOptionId(pointer) {
29640
29948
  }
29641
29949
  return pointer.value.value[0];
29642
29950
  }
29951
+ function isDialogueRequestName(name) {
29952
+ return name === "TryTrigger" || name === "CanTrigger";
29953
+ }
29954
+ function dialogueBodyKindLabel(kind) {
29955
+ if (kind === "initializer" || kind === "initializerExpression")
29956
+ return "an initializer";
29957
+ return `a ${kind}`;
29958
+ }
29959
+ function capitalize(text) {
29960
+ return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
29961
+ }
29962
+ function requireDialogueArgCount(name, args, required2, acceptsOnFinish, pos) {
29963
+ if (!acceptsOnFinish) {
29964
+ requireArgCount(name, args, required2, pos);
29965
+ return;
29966
+ }
29967
+ if (args.length === required2 || args.length === required2 + 1) return;
29968
+ throw new CompileError(
29969
+ `${name} expects ${required2} or ${required2 + 1} arguments, got ${args.length}.`,
29970
+ pos
29971
+ );
29972
+ }
29973
+ function dialogueValueError(receiver) {
29974
+ if (receiver.kind === "root") {
29975
+ return `\`${receiver.path}\` is not a value. Use one of its members.`;
29976
+ }
29977
+ if (receiver.kind === "folder") {
29978
+ return `\`${receiver.path}\` is a dialogue folder, not a value. Use one of its groups' members.`;
29979
+ }
29980
+ return `\`${receiver.path}\` is a dialogue group, not a value. Use one of its members.`;
29981
+ }
29982
+ function dialogueIntrinsic(fn) {
29983
+ return {
29984
+ pointer: { type: "function" /* Function */, function: fn },
29985
+ type: { kind: "primitive", name: "bool" }
29986
+ };
29987
+ }
29643
29988
  function intrinsic(kind, info, type) {
29644
29989
  return {
29645
29990
  pointer: {
@@ -29846,7 +30191,7 @@ function primitiveValueKind(name) {
29846
30191
  return 11 /* Sprite */;
29847
30192
  case "AudioClipInfo":
29848
30193
  return 12 /* Audio */;
29849
- case "DialogueRef":
30194
+ case "NeoDialogueReference":
29850
30195
  return 18 /* DialogueLookup */;
29851
30196
  case "Vector2":
29852
30197
  return 14 /* Vector2 */;
@@ -29879,7 +30224,7 @@ function valueKindPrimitive(kind) {
29879
30224
  case 12 /* Audio */:
29880
30225
  return "AudioClipInfo";
29881
30226
  case 18 /* DialogueLookup */:
29882
- return "DialogueRef";
30227
+ return "NeoDialogueReference";
29883
30228
  case 14 /* Vector2 */:
29884
30229
  return "Vector2";
29885
30230
  case 15 /* Vector2Int */:
@@ -30059,7 +30404,7 @@ function resolvePrimitiveMember(type, name) {
30059
30404
  if (name === "length")
30060
30405
  return { type: { kind: "primitive", name: "float" } };
30061
30406
  }
30062
- if (type.name === "DialogueRef" && name === "id")
30407
+ if (type.name === "NeoDialogueReference" && name === "id")
30063
30408
  return { type: { kind: "primitive", name: "string" } };
30064
30409
  return null;
30065
30410
  }
@@ -30158,7 +30503,7 @@ function namedPrimitive(name) {
30158
30503
  case "decimal":
30159
30504
  case "SpriteInfo":
30160
30505
  case "AudioClipInfo":
30161
- case "DialogueRef":
30506
+ case "NeoDialogueReference":
30162
30507
  case "Vector2":
30163
30508
  case "Vector2Int":
30164
30509
  case "Vector3":
@@ -30393,7 +30738,10 @@ function resolveNeoScriptType(type, context, project) {
30393
30738
  }
30394
30739
  const named = project.typeByName.get(type.name);
30395
30740
  if (!named)
30396
- throw new CompileError(`Unknown type '${type.name}'`, type.pos);
30741
+ throw new CompileError(
30742
+ renamedDialogueTypeMessage(type.name, "value") ?? `Unknown type '${type.name}'`,
30743
+ type.pos
30744
+ );
30397
30745
  resolved = {
30398
30746
  kind: "named",
30399
30747
  typeId: named.id,
@@ -30459,6 +30807,7 @@ var init_strict_resolver = __esm({
30459
30807
  init_strict_compile_error();
30460
30808
  init_strict_ir();
30461
30809
  init_test_prelude();
30810
+ init_dialogue_types();
30462
30811
  init_tile_conversion();
30463
30812
  CONSTRUCTING_FUNCTION_KINDS = /* @__PURE__ */ new Set(
30464
30813
  [
@@ -31883,23 +32232,23 @@ var init_strict_resolver = __esm({
31883
32232
  resolveDebugStatement(expr, scope) {
31884
32233
  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"))
31885
32234
  return null;
31886
- const method2 = expr.callee.name;
32235
+ const method3 = expr.callee.name;
31887
32236
  const severities = {
31888
32237
  Log: "log",
31889
32238
  LogWarning: "warning",
31890
32239
  LogError: "error",
31891
32240
  Assert: "assert"
31892
32241
  };
31893
- if (!Object.hasOwn(severities, method2))
31894
- throw new CompileError(`Unknown Debug method '${method2}'.`, expr.pos);
31895
- const severity = severities[method2];
31896
- const expected = method2 === "Assert" ? 2 : 1;
32242
+ if (!Object.hasOwn(severities, method3))
32243
+ throw new CompileError(`Unknown Debug method '${method3}'.`, expr.pos);
32244
+ const severity = severities[method3];
32245
+ const expected = method3 === "Assert" ? 2 : 1;
31897
32246
  if (expr.args.length !== expected)
31898
32247
  throw new CompileError(
31899
- `Debug.${method2} expects ${expected} argument(s).`,
32248
+ `Debug.${method3} expects ${expected} argument(s).`,
31900
32249
  expr.pos
31901
32250
  );
31902
- const condition = method2 === "Assert" ? this.resolveExpression(requiredAt(expr.args, 0), scope) : void 0;
32251
+ const condition = method3 === "Assert" ? this.resolveExpression(requiredAt(expr.args, 0), scope) : void 0;
31903
32252
  if (condition && (!isPrimitive(condition.type, "bool") || isNullable(condition.type)))
31904
32253
  throw new CompileError(
31905
32254
  "Debug.Assert requires a non-null bool condition.",
@@ -32789,6 +33138,17 @@ var init_strict_resolver = __esm({
32789
33138
  }
32790
33139
  }
32791
33140
  resolveExpression(expression, scope, expected) {
33141
+ const result = this.resolveReceiverExpression(expression, scope, expected);
33142
+ if (result.dialogues !== void 0) {
33143
+ throw new CompileError(
33144
+ dialogueValueError(result.dialogues),
33145
+ expression.pos
33146
+ );
33147
+ }
33148
+ return result;
33149
+ }
33150
+ /** {@link resolveExpression} that also admits a `root.Dialogues` receiver. */
33151
+ resolveReceiverExpression(expression, scope, expected) {
32792
33152
  let result = this.resolveExpressionCore(expression, scope, expected);
32793
33153
  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 */) {
32794
33154
  result = {
@@ -34366,7 +34726,7 @@ var init_strict_resolver = __esm({
34366
34726
  return this.resolveStaticMemberValue(staticType, member, pos);
34367
34727
  }
34368
34728
  }
34369
- const resolvedReceiver = receiverValue ? receiverValue() : this.resolveExpression(receiverAst, scope);
34729
+ const resolvedReceiver = receiverValue ? receiverValue() : this.resolveReceiverExpression(receiverAst, scope);
34370
34730
  if (optional2 && !isNullable(resolvedReceiver.type)) {
34371
34731
  throw new CompileError(
34372
34732
  `\`?.\` requires an optional receiver; got ${this.describe(resolvedReceiver.type)}`,
@@ -34462,7 +34822,7 @@ var init_strict_resolver = __esm({
34462
34822
  }
34463
34823
  const primitiveMember = resolvePrimitiveMember(receiver.type, name);
34464
34824
  if (primitiveMember) {
34465
- if (isPrimitive(receiver.type, "DialogueRef")) {
34825
+ if (isPrimitive(receiver.type, "NeoDialogueReference")) {
34466
34826
  return {
34467
34827
  pointer: {
34468
34828
  type: "keyOf" /* KeyOf */,
@@ -34495,12 +34855,15 @@ var init_strict_resolver = __esm({
34495
34855
  pos
34496
34856
  );
34497
34857
  }
34498
- if (isPrimitive(receiver.type, "DialogueRef")) {
34858
+ if (isPrimitive(receiver.type, "NeoDialogueReference")) {
34499
34859
  throw new CompileError(
34500
34860
  `${this.describe(receiver.type)} has no member '${name}'`,
34501
34861
  pos
34502
34862
  );
34503
34863
  }
34864
+ if (receiver.dialogues !== void 0) {
34865
+ return this.resolveDialogueGroupRead(receiver, name, pos);
34866
+ }
34504
34867
  const memberReceiverType = neoScriptMemberLookupType(receiver.type);
34505
34868
  if (memberReceiverType.kind === "named") {
34506
34869
  const type = this.project.typeById.get(memberReceiverType.typeId);
@@ -34529,6 +34892,10 @@ var init_strict_resolver = __esm({
34529
34892
  if (this.userClassCode && type.id === this.rootTypeId && member.writability !== "user") {
34530
34893
  throw new CompileError("User code can only read `root.User`.", pos);
34531
34894
  }
34895
+ const dialogues = this.dialogueReceiverOf(member.type);
34896
+ if (dialogues !== void 0) {
34897
+ return { ...literal(member.type, null), dialogues, symbol: member };
34898
+ }
34532
34899
  if (member.static === true) {
34533
34900
  throw new CompileError(
34534
34901
  `Static member '${type.name}.${name}' must be accessed through the type name, not an instance.`,
@@ -34883,6 +35250,227 @@ var init_strict_resolver = __esm({
34883
35250
  );
34884
35251
  }
34885
35252
  }
35253
+ /** P105 §2.1. The receiver a value of this type is, if it is one. */
35254
+ dialogueReceiverOf(type) {
35255
+ if (type.kind !== "named") return void 0;
35256
+ return this.project.typeById.get(type.typeId)?.dialogues;
35257
+ }
35258
+ /** P105 §2.1. `<receiver>.<Group>`; the methods are only callable. */
35259
+ resolveDialogueGroupRead(receiver, name, pos) {
35260
+ const path = receiver.dialogues.path;
35261
+ const type = receiver.type.kind === "named" ? this.project.typeById.get(receiver.type.typeId) : void 0;
35262
+ const member = type?.members.find((candidate) => candidate.name === name);
35263
+ if (member === void 0) {
35264
+ throw new CompileError(`${path} has no dialogue group '${name}'.`, pos);
35265
+ }
35266
+ if (member.kind === "method") {
35267
+ throw new CompileError(
35268
+ `'${path}.${name}' must be called with \`()\`; it cannot be read as a value.`,
35269
+ pos
35270
+ );
35271
+ }
35272
+ const dialogues = this.dialogueReceiverOf(member.type);
35273
+ if (dialogues === void 0) {
35274
+ throw new Error(
35275
+ `Dialogue group member '${path}.${name}' has no group type.`
35276
+ );
35277
+ }
35278
+ return { ...literal(member.type, null), dialogues, symbol: member };
35279
+ }
35280
+ /** P105 §2.1. A call on `root.Dialogues` or one of its groups. */
35281
+ resolveDialogueReceiverCall(receiver, name, args, scope, pos) {
35282
+ if (receiver.kind === "root") {
35283
+ if (name === "VisitCount" || name === "HasVisited") {
35284
+ return this.resolveDialogueMemoryRead(name, args, scope, pos);
35285
+ }
35286
+ if (!isDialogueRequestName(name)) {
35287
+ throw new CompileError(
35288
+ `${receiver.path} has no method '${name}'.`,
35289
+ pos
35290
+ );
35291
+ }
35292
+ this.assertDialogueRequestAllowed(name, pos);
35293
+ requireDialogueArgCount(name, args, 1, name === "TryTrigger", pos);
35294
+ const dialogueId = this.resolveExpression(requiredAt(args, 0), scope, {
35295
+ kind: "primitive",
35296
+ name: "string"
35297
+ });
35298
+ this.requireAssignable(
35299
+ dialogueId.type,
35300
+ { kind: "primitive", name: "string" },
35301
+ requiredAt(args, 0).pos,
35302
+ "dialogueId"
35303
+ );
35304
+ return dialogueIntrinsic({
35305
+ type: "dialogue" /* Dialogue */,
35306
+ info: {
35307
+ op: NeoScriptDialogueOp[name],
35308
+ dialogueIdPointer: dialogueId.pointer,
35309
+ ...this.dialogueOnFinish(args[1], scope)
35310
+ }
35311
+ });
35312
+ }
35313
+ if (!isDialogueRequestName(name)) {
35314
+ throw new CompileError(`${receiver.path} has no member '${name}'.`, pos);
35315
+ }
35316
+ if (receiver.kind === "folder") {
35317
+ throw new CompileError(
35318
+ `${receiver.path} is a dialogue folder, so it has no '${name}'. Use one of its groups' members.`,
35319
+ pos
35320
+ );
35321
+ }
35322
+ this.assertDialogueRequestAllowed(name, pos);
35323
+ if (receiver.kind === "standard") {
35324
+ requireDialogueArgCount(name, args, 0, name === "TryTrigger", pos);
35325
+ return dialogueIntrinsic({
35326
+ type: "dialogueGroup" /* DialogueGroup */,
35327
+ info: {
35328
+ op: NeoScriptDialogueOp[name],
35329
+ groupId: receiver.groupId,
35330
+ ...this.dialogueOnFinish(args[0], scope)
35331
+ }
35332
+ });
35333
+ }
35334
+ const entryType = receiver.entryType;
35335
+ if (entryType === void 0) {
35336
+ throw new CompileError(
35337
+ `${receiver.path} can't be triggered: its lookup collection has no entry class.`,
35338
+ pos
35339
+ );
35340
+ }
35341
+ requireDialogueArgCount(name, args, 1, name === "TryTrigger", pos);
35342
+ const value = this.resolveExpression(requiredAt(args, 0), scope, entryType);
35343
+ this.requireAssignable(
35344
+ value.type,
35345
+ entryType,
35346
+ requiredAt(args, 0).pos,
35347
+ "lookup value"
35348
+ );
35349
+ return dialogueIntrinsic({
35350
+ type: "dialogueGroup" /* DialogueGroup */,
35351
+ info: {
35352
+ op: NeoScriptDialogueOp[name],
35353
+ groupId: receiver.groupId,
35354
+ valuePointer: value.pointer,
35355
+ ...this.dialogueOnFinish(args[1], scope)
35356
+ }
35357
+ });
35358
+ }
35359
+ /**
35360
+ * P105 §2.2. `NeoDialogueReference` methods request the dialogue by the
35361
+ * reference's `id`, the same index-0 read `.id` lowers to.
35362
+ */
35363
+ resolveDialogueReferenceCall(receiver, name, args, scope, pos, optional2) {
35364
+ if (this.userClassCode) {
35365
+ throw new CompileError(
35366
+ `User code can't use ${name}. Dialogues run against a save.`,
35367
+ pos
35368
+ );
35369
+ }
35370
+ const nullPropagating = optional2 || receiver.optionalChainType !== void 0;
35371
+ if (!optional2 && isNullable(receiver.type)) {
35372
+ throw new CompileError(
35373
+ `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.`,
35374
+ pos
35375
+ );
35376
+ }
35377
+ this.assertDialogueRequestAllowed(name, pos);
35378
+ requireDialogueArgCount(name, args, 0, name === "TryTrigger", pos);
35379
+ const resolved = dialogueIntrinsic({
35380
+ type: "dialogue" /* Dialogue */,
35381
+ info: {
35382
+ op: NeoScriptDialogueOp[name],
35383
+ dialogueIdPointer: {
35384
+ type: "keyOf" /* KeyOf */,
35385
+ keyOf: { pointer: receiver.pointer, key: numberPointer(0) },
35386
+ ...nullPropagating ? { optional: true } : {}
35387
+ },
35388
+ ...this.dialogueOnFinish(args[0], scope)
35389
+ }
35390
+ });
35391
+ if (!nullPropagating) return resolved;
35392
+ return {
35393
+ ...resolved,
35394
+ type: { ...resolved.type, nullable: true },
35395
+ optionalChainType: resolved.type
35396
+ };
35397
+ }
35398
+ dialogueOnFinish(argument2, scope) {
35399
+ if (argument2 === void 0) return {};
35400
+ const onFinish = this.resolveExpression(
35401
+ argument2,
35402
+ scope,
35403
+ NEOSCRIPT_DIALOGUE_ON_FINISH_TYPE
35404
+ );
35405
+ this.requireAssignable(
35406
+ onFinish.type,
35407
+ NEOSCRIPT_DIALOGUE_ON_FINISH_TYPE,
35408
+ argument2.pos,
35409
+ "onFinish"
35410
+ );
35411
+ return { onFinishPointer: onFinish.pointer };
35412
+ }
35413
+ /**
35414
+ * P105 §2.4. Requests run only from bodies that run once per call; reads
35415
+ * run wherever dialogue memory has a value.
35416
+ */
35417
+ assertDialogueRequestAllowed(name, pos) {
35418
+ if (name === "CanTrigger") {
35419
+ this.assertDialogueMemoryReadable(name, pos);
35420
+ return;
35421
+ }
35422
+ const kind = this.context.kind;
35423
+ if (kind === "function" || kind === "action") return;
35424
+ if (kind === "getter" || kind === "property" || kind === "condition") {
35425
+ throw new CompileError(
35426
+ "A getter can't trigger a dialogue. It runs whenever its value is read.",
35427
+ pos
35428
+ );
35429
+ }
35430
+ if (kind === "setter") {
35431
+ throw new CompileError(
35432
+ "A setter can't trigger a dialogue. Trigger it from a function.",
35433
+ pos
35434
+ );
35435
+ }
35436
+ throw new CompileError(
35437
+ `${capitalize(dialogueBodyKindLabel(kind))} body can't trigger a dialogue. Dialogues only run during play.`,
35438
+ pos
35439
+ );
35440
+ }
35441
+ /**
35442
+ * P43 §7.2.2. Dialogue memory is runtime state; it has no value at push
35443
+ * time, in a freshly constructed instance, or while migrating a save.
35444
+ */
35445
+ assertDialogueMemoryReadable(name, pos) {
35446
+ const kind = this.context.kind;
35447
+ if (!isNeoScriptConstructionDocumentKind(kind) && kind !== "migration") {
35448
+ return;
35449
+ }
35450
+ throw new CompileError(
35451
+ `${name} reads runtime dialogue memory, which has no meaning in ${dialogueBodyKindLabel(kind)} body.`,
35452
+ pos
35453
+ );
35454
+ }
35455
+ resolveDialogueMemoryRead(name, args, scope, pos) {
35456
+ this.assertDialogueMemoryReadable(name, pos);
35457
+ requireArgCount(name, args, 1, pos);
35458
+ const pointer = this.resolveExpression(requiredAt(args, 0), scope, {
35459
+ kind: "primitive",
35460
+ name: "string"
35461
+ });
35462
+ if (!isPrimitive(pointer.type, "string")) {
35463
+ throw new CompileError(
35464
+ `${name} pointer must be a string; got ${this.describe(pointer.type)}`,
35465
+ pos
35466
+ );
35467
+ }
35468
+ return intrinsic(
35469
+ name === "VisitCount" ? "visitCount" /* VisitCount */ : "hasVisited" /* HasVisited */,
35470
+ { pointer: pointer.pointer },
35471
+ { kind: "primitive", name: name === "VisitCount" ? "int" : "bool" }
35472
+ );
35473
+ }
34886
35474
  /**
34887
35475
  * P69 §2.7. A member read on the `Math` namespace: the two constants lower
34888
35476
  * to `float` literals, and nothing else on `Math` is readable as a value.
@@ -35088,7 +35676,9 @@ var init_strict_resolver = __esm({
35088
35676
  return () => {
35089
35677
  if (!result) {
35090
35678
  try {
35091
- result = { value: this.resolveExpression(callee.receiver, scope) };
35679
+ result = {
35680
+ value: this.resolveReceiverExpression(callee.receiver, scope)
35681
+ };
35092
35682
  } catch (error) {
35093
35683
  result = { error };
35094
35684
  }
@@ -35143,31 +35733,11 @@ var init_strict_resolver = __esm({
35143
35733
  if (vector3)
35144
35734
  return this.resolveVectorConstructor(vector3, argumentsList2, scope, pos);
35145
35735
  if (callee.name === "VisitCount" || callee.name === "HasVisited") {
35146
- if (isNeoScriptConstructionDocumentKind(this.context.kind)) {
35147
- throw new CompileError(
35148
- `${callee.name} reads runtime dialogue memory, which has no meaning in a ${this.context.kind} body.`,
35149
- pos
35150
- );
35151
- }
35152
- requireArgCount(callee.name, argumentsList2, 1, pos);
35153
- const pointer = this.resolveExpression(
35154
- requiredAt(argumentsList2, 0),
35736
+ return this.resolveDialogueMemoryRead(
35737
+ callee.name,
35738
+ argumentsList2,
35155
35739
  scope,
35156
- { kind: "primitive", name: "string" }
35157
- );
35158
- if (!isPrimitive(pointer.type, "string")) {
35159
- throw new CompileError(
35160
- `${callee.name} pointer must be a string; got ${this.describe(pointer.type)}`,
35161
- pos
35162
- );
35163
- }
35164
- return intrinsic(
35165
- callee.name === "VisitCount" ? "visitCount" /* VisitCount */ : "hasVisited" /* HasVisited */,
35166
- { pointer: pointer.pointer },
35167
- {
35168
- kind: "primitive",
35169
- name: callee.name === "VisitCount" ? "int" : "bool"
35170
- }
35740
+ pos
35171
35741
  );
35172
35742
  }
35173
35743
  const global = this.context.project.globals.find(
@@ -35272,12 +35842,37 @@ var init_strict_resolver = __esm({
35272
35842
  }
35273
35843
  const receiver = receiverValue();
35274
35844
  const optional2 = callee.optional === true;
35845
+ if (receiver.dialogues !== void 0) {
35846
+ if (optional2) {
35847
+ throw new CompileError(
35848
+ `\`?.\` is not valid on ${receiver.dialogues.path}; it is never null.`,
35849
+ pos
35850
+ );
35851
+ }
35852
+ return this.resolveDialogueReceiverCall(
35853
+ receiver.dialogues,
35854
+ callee.name,
35855
+ argumentsList2,
35856
+ scope,
35857
+ pos
35858
+ );
35859
+ }
35275
35860
  if (optional2 && !isNullable(receiver.type)) {
35276
35861
  throw new CompileError(
35277
35862
  `\`?.\` requires an optional receiver; got ${this.describe(receiver.type)}`,
35278
35863
  pos
35279
35864
  );
35280
35865
  }
35866
+ if (isPrimitive(receiver.type, "NeoDialogueReference") && isDialogueRequestName(callee.name)) {
35867
+ return this.resolveDialogueReferenceCall(
35868
+ receiver,
35869
+ callee.name,
35870
+ argumentsList2,
35871
+ scope,
35872
+ pos,
35873
+ optional2
35874
+ );
35875
+ }
35281
35876
  if (callee.name === "Slice" && isPrimitive(receiver.type, "ImageRef")) {
35282
35877
  return this.resolveImageSlice(receiver, argumentsList2, scope, pos);
35283
35878
  }
@@ -37559,6 +38154,7 @@ var init_strict_resolver = __esm({
37559
38154
  }
37560
38155
  }
37561
38156
  const receiver = receiverValue();
38157
+ if (receiver.dialogues !== void 0) return null;
37562
38158
  const memberReceiverType = neoScriptMemberLookupType(receiver.type);
37563
38159
  if (memberReceiverType.kind !== "named") return null;
37564
38160
  const type = this.project.typeById.get(memberReceiverType.typeId);
@@ -42586,7 +43182,7 @@ function createEnvironment(documents, project) {
42586
43182
  if (declaration.kind === "class") {
42587
43183
  types.set(declaration.name, declaration);
42588
43184
  const dialogue = declaration.baseTypes.some(
42589
- (base) => base.name === "Dialogue"
43185
+ (base) => base.name === "NeoDialogue"
42590
43186
  );
42591
43187
  if (dialogue) {
42592
43188
  referenceTargets.set(declaration.name, {
@@ -43303,7 +43899,9 @@ function fieldsForAnnotation(name, context, environment) {
43303
43899
  }
43304
43900
  if (name === "primary") return context.kind === "flowBinding" ? [] : null;
43305
43901
  if (name === "incomplete") {
43306
- return context.kind === "flowGraph" || context.kind === "flowMember" || context.kind === "class" && context.declaration.baseTypes.some((type) => type.name === "Dialogue") ? [{ name: "reason", type: "string" }] : null;
43902
+ return context.kind === "flowGraph" || context.kind === "flowMember" || context.kind === "class" && context.declaration.baseTypes.some(
43903
+ (type) => type.name === "NeoDialogue"
43904
+ ) ? [{ name: "reason", type: "string" }] : null;
43307
43905
  }
43308
43906
  if (name === "visibility") {
43309
43907
  return context.kind === "class" ? [{ name: "visibility", type: "NeoClassVisibility" }] : null;
@@ -43347,7 +43945,7 @@ function settingsFields(context) {
43347
43945
  ];
43348
43946
  }
43349
43947
  if (context.kind === "class") {
43350
- if (context.declaration.baseTypes.some((type2) => type2.name === "Dialogue")) {
43948
+ if (context.declaration.baseTypes.some((type2) => type2.name === "NeoDialogue")) {
43351
43949
  return [
43352
43950
  { name: "name", type: "string" },
43353
43951
  { name: "description", type: "string" },
@@ -43382,7 +43980,7 @@ function settingsFields(context) {
43382
43980
  );
43383
43981
  }
43384
43982
  if (type.name === "Lookup") return lookupSettingsFields();
43385
- if (type.name === "Dialogue")
43983
+ if (type.name === "NeoDialogueReference")
43386
43984
  return settingsClassFields("NeoDialogueSettings");
43387
43985
  if (type.name === "NeoImage" || type.name === "NeoAudioClip" || type.name === "SpriteInfo" || type.name === "AudioClipInfo") {
43388
43986
  return settingsClassFields("NeoFileSettings").filter(
@@ -44815,7 +45413,8 @@ function subscriptKeyType(receiver) {
44815
45413
  if (receiver?.name === "List") return primitiveType("int");
44816
45414
  return void 0;
44817
45415
  }
44818
- function validateReferenceExpression(expression, expected, environment, uri, range2, diagnostics) {
45416
+ function validateReferenceExpression(expression, declared, environment, uri, range2, diagnostics) {
45417
+ const expected = declared?.name === "NeoDialogueReference" ? { ...declared, name: "NeoDialogue" } : declared;
44819
45418
  const typeArguments = expression.typeArguments ?? [];
44820
45419
  const names = expression.argumentNames ?? [];
44821
45420
  const idIndex = names.findIndex((name) => name === "id");
@@ -44907,7 +45506,7 @@ function validateReferenceExpression(expression, expected, environment, uri, ran
44907
45506
  );
44908
45507
  return;
44909
45508
  }
44910
- if (target.kind === "dialogue" && expected && expected.name !== "Dialogue") {
45509
+ if (target.kind === "dialogue" && expected && expected.name !== "NeoDialogue") {
44911
45510
  if (!referenceTypeAssignable(target.type, expected, environment)) {
44912
45511
  malformed(
44913
45512
  `Dialogue target ${path} is incompatible with expected target ${describeType(expected)}.`
@@ -44941,8 +45540,8 @@ function referenceTargetPath(expression) {
44941
45540
  return receiver === null ? null : `${receiver}.${expression.name}`;
44942
45541
  }
44943
45542
  function isDialogueReferenceType(type, environment) {
44944
- if (type.name === "Dialogue") return true;
44945
- return classExtends(type.name, "Dialogue", environment, /* @__PURE__ */ new Set());
45543
+ if (type.name === "NeoDialogue") return true;
45544
+ return classExtends(type.name, "NeoDialogue", environment, /* @__PURE__ */ new Set());
44946
45545
  }
44947
45546
  function referenceTypeAssignable(actual, expected, environment) {
44948
45547
  if (actual.name === expected.name) {
@@ -45876,14 +46475,18 @@ function successfulBodyCache(project) {
45876
46475
  }
45877
46476
  function compileProjectSourceBodies(documents) {
45878
46477
  const graph = buildProjectGraph(documents);
45879
- const groupContexts = dialogueGroupContexts(documents, graph);
45880
- const project = {
45881
- ...graph.project,
45882
- types: [
45883
- ...graph.project.types,
45884
- ...[...groupContexts.values()].map((group) => group.contextType)
45885
- ]
45886
- };
46478
+ const groups = sourceDialogueGroups2(documents, graph);
46479
+ const groupContexts = groups.contexts;
46480
+ const dialogues = neoScriptDialogueTypes(groups.sources);
46481
+ const types = [];
46482
+ for (const type of graph.project.types) {
46483
+ types.push(
46484
+ type.id === PROJECT_ROOT_TYPE_ID ? { ...type, members: [...type.members, dialogues.member] } : type
46485
+ );
46486
+ }
46487
+ for (const group of groupContexts.values()) types.push(group.contextType);
46488
+ types.push(...dialogues.types);
46489
+ const project = { ...graph.project, types };
45887
46490
  const projectIndex = createProjectIndex(project);
45888
46491
  const bodyCache = successfulBodyCache(project);
45889
46492
  const bodies = [];
@@ -46100,76 +46703,78 @@ function compileProjectSourceBodies(documents) {
46100
46703
  }
46101
46704
  return { project, bodies, contexts, diagnostics };
46102
46705
  }
46103
- function dialogueGroupContexts(documents, graph) {
46104
- const result = /* @__PURE__ */ new Map();
46105
- let index;
46106
- let membersByType;
46107
- const collectionMembersByType = () => membersByType ??= new Map(
46108
- graph.project.types.map((type) => [
46109
- type.name,
46110
- new Map(type.members.map((member) => [member.name, member]))
46111
- ])
46112
- );
46706
+ function sourceDialogueGroups2(documents, graph) {
46707
+ const declarations = [];
46708
+ const idsByName = /* @__PURE__ */ new Map();
46113
46709
  for (const [uri, document] of documents) {
46114
46710
  for (const declaration of document.declarations) {
46115
- if (declaration.kind !== "global" || !declaration.dialogueGroup) continue;
46116
- let thisType;
46117
- try {
46118
- const constructor2 = parseExpression(
46119
- declaration.dialogueGroup.constructor.text
46120
- );
46121
- if (constructor2.kind === "new") {
46122
- const kind = constructor2.args[constructor2.argumentNames?.indexOf("kind") ?? -1];
46123
- const collection = constructor2.args[constructor2.argumentNames?.indexOf("collection") ?? -1];
46124
- if (kind?.kind === "contextualEnum" && kind.name === "Lookup") {
46125
- let member;
46126
- if (collection?.kind === "member" && collection.receiver.kind === "ident") {
46127
- member = collectionMembersByType().get(collection.receiver.name)?.get(collection.name);
46128
- } else if (collection?.kind === "call" && collection.callee.kind === "ident" && collection.callee.name === "Reference") {
46129
- const id3 = collection.args[collection.argumentNames?.indexOf("id") ?? -1];
46130
- if (id3?.kind === "litString")
46131
- member = (index ??= createProjectIndex(
46132
- graph.project
46133
- )).symbolById.get(id3.value);
46134
- }
46135
- let entry;
46136
- if (member?.type.kind === "list") entry = member.type.elementType;
46137
- if (member?.type.kind === "dictionary")
46138
- entry = member.type.valueType;
46139
- if (entry?.kind === "named")
46140
- thisType = { ...entry, nullable: false };
46141
- }
46142
- }
46143
- } catch {
46144
- }
46145
- const id2 = `dialogue-context:${uri}:${declaration.name}`;
46146
- result.set(declaration, {
46147
- ...thisType ? { thisType } : {},
46148
- contextType: {
46149
- id: id2,
46150
- name: "DialogueContext",
46151
- kind: "synthetic",
46152
- members: [
46153
- {
46154
- id: `${id2}:primary`,
46155
- name: "primary",
46156
- kind: "property",
46157
- type: { kind: "primitive", name: "unknown" },
46158
- writable: false
46159
- },
46160
- {
46161
- id: `${id2}:trigger`,
46162
- name: "trigger",
46163
- kind: "property",
46164
- type: thisType ?? { kind: "primitive", name: "null" },
46165
- writable: false
46166
- }
46167
- ]
46168
- }
46169
- });
46711
+ if (declaration.kind !== "global") continue;
46712
+ if (declaration.type.name !== "NeoDialogueGroup") continue;
46713
+ const id2 = sourceIdentity2(
46714
+ declaration.annotations,
46715
+ `dialogue-group:${uri}:${declaration.name}`
46716
+ );
46717
+ idsByName.set(declaration.name, id2);
46718
+ declarations.push({ uri, declaration, id: id2 });
46170
46719
  }
46171
46720
  }
46172
- return result;
46721
+ const lookups = new SourceDialogueGroupLookups(graph);
46722
+ const contexts = /* @__PURE__ */ new Map();
46723
+ const sources2 = [];
46724
+ for (const { uri, declaration, id: id2 } of declarations) {
46725
+ const args = constructorArgs(
46726
+ declaration.dialogueGroup?.constructor.text ?? declaration.initializer.text
46727
+ );
46728
+ const kindArgument = args.get("kind");
46729
+ const kind = kindArgument?.kind === "contextualEnum" ? SOURCE_DIALOGUE_GROUP_KINDS[kindArgument.name] : void 0;
46730
+ const lookup = kind === "lookup" ? lookups.resolve(args.get("collection")) : void 0;
46731
+ if (declaration.dialogueGroup)
46732
+ contexts.set(
46733
+ declaration,
46734
+ dialogueGroupContext(
46735
+ `dialogue-context:${uri}:${declaration.name}`,
46736
+ lookup?.entryType
46737
+ )
46738
+ );
46739
+ if (kind === void 0) continue;
46740
+ const name = args.get("name");
46741
+ sources2.push({
46742
+ id: id2,
46743
+ name: name?.kind === "litString" ? name.value : declaration.name,
46744
+ parentId: referenceId(args.get("parent"), idsByName),
46745
+ kind,
46746
+ ...lookup ? { lookup } : {},
46747
+ location: location(uri, declaration.range),
46748
+ selectionLocation: location(uri, declaration.nameRange)
46749
+ });
46750
+ }
46751
+ return { contexts, sources: sources2 };
46752
+ }
46753
+ function dialogueGroupContext(id2, thisType) {
46754
+ return {
46755
+ ...thisType ? { thisType } : {},
46756
+ contextType: {
46757
+ id: id2,
46758
+ name: "DialogueContext",
46759
+ kind: "synthetic",
46760
+ members: [
46761
+ {
46762
+ id: `${id2}:primary`,
46763
+ name: "primary",
46764
+ kind: "property",
46765
+ type: { kind: "primitive", name: "unknown" },
46766
+ writable: false
46767
+ },
46768
+ {
46769
+ id: `${id2}:trigger`,
46770
+ name: "trigger",
46771
+ kind: "property",
46772
+ type: thisType ?? { kind: "primitive", name: "null" },
46773
+ writable: false
46774
+ }
46775
+ ]
46776
+ }
46777
+ };
46173
46778
  }
46174
46779
  function compileBody(args) {
46175
46780
  args.contexts.push({
@@ -46233,7 +46838,7 @@ function compileBody(args) {
46233
46838
  uri: args.uri,
46234
46839
  source: "neo-project",
46235
46840
  code: projectBodyDiagnosticCode(diagnostic.message, args.unit),
46236
- message: `${capitalize(args.unit)} '${args.owner.declaration.name}.${args.memberName}': ${diagnostic.message}`,
46841
+ message: `${capitalize2(args.unit)} '${args.owner.declaration.name}.${args.memberName}': ${diagnostic.message}`,
46237
46842
  relatedInformation: [
46238
46843
  {
46239
46844
  location: location(args.uri, args.declarationRange),
@@ -46779,7 +47384,7 @@ function projectRootType(documents, declarations) {
46779
47384
  }
46780
47385
  }
46781
47386
  }
46782
- return { id: "builtin:Root", name: "Root", kind: "synthetic", members };
47387
+ return { id: PROJECT_ROOT_TYPE_ID, name: "Root", kind: "synthetic", members };
46783
47388
  }
46784
47389
  function sourceTypeRef(type, owner, typeIds, resolvingTypeParameters = /* @__PURE__ */ new Set()) {
46785
47390
  const nullable2 = type.nullable || void 0;
@@ -46792,9 +47397,11 @@ function sourceTypeRef(type, owner, typeIds, resolvingTypeParameters = /* @__PUR
46792
47397
  };
46793
47398
  }
46794
47399
  if (type.name === "Set") {
47400
+ const element = type.typeArguments[0];
46795
47401
  return {
46796
47402
  kind: "set",
46797
- elementType: type.typeArguments[0] ? resolveNested(type.typeArguments[0]) : { kind: "primitive", name: "unknown" },
47403
+ // P105 §2.2. Multiselect dialogue elements are bare dialogue ids.
47404
+ elementType: element?.name === "NeoDialogueReference" ? { kind: "primitive", name: "string" } : element ? resolveNested(element) : { kind: "primitive", name: "unknown" },
46798
47405
  ...nullable2 ? { nullable: nullable2 } : {}
46799
47406
  };
46800
47407
  }
@@ -46996,16 +47603,15 @@ function sourceIdentity2(annotations, fallback) {
46996
47603
  function location(uri, range2) {
46997
47604
  return { uri, range: range2 };
46998
47605
  }
46999
- function capitalize(value) {
47606
+ function capitalize2(value) {
47000
47607
  return `${value[0]?.toUpperCase() ?? ""}${value.slice(1)}`;
47001
47608
  }
47002
- var PRIMITIVE_NAME_LIST, PRIMITIVE_NAMES, STORAGE_WRITABILITY, successfulBodiesByProject;
47609
+ var PRIMITIVE_NAME_LIST, PRIMITIVE_NAMES, STORAGE_WRITABILITY, successfulBodiesByProject, SOURCE_DIALOGUE_GROUP_KINDS, SourceDialogueGroupLookups, PROJECT_ROOT_TYPE_ID;
47003
47610
  var init_project_source_script_compiler = __esm({
47004
47611
  "../packages/neoscript-language/src/project-source-script-compiler.ts"() {
47005
47612
  "use strict";
47006
47613
  init_project_source_settlement();
47007
47614
  init_debug_info();
47008
- init_executable_parser();
47009
47615
  init_compiler();
47010
47616
  init_declared_constructors();
47011
47617
  init_language_spec();
@@ -47016,13 +47622,15 @@ var init_project_source_script_compiler = __esm({
47016
47622
  init_project_source_registry();
47017
47623
  init_source_text();
47018
47624
  init_lexer();
47625
+ init_dialogue_types();
47626
+ init_project_source_dialogue_groups();
47019
47627
  PRIMITIVE_NAME_LIST = [
47020
47628
  ...NEOSCRIPT_PRIMITIVE_TYPES,
47021
47629
  "void",
47022
47630
  "null",
47023
47631
  "SpriteInfo",
47024
47632
  "AudioClipInfo",
47025
- "DialogueRef",
47633
+ "NeoDialogueReference",
47026
47634
  "Vector2",
47027
47635
  "Vector2Int",
47028
47636
  "Vector3",
@@ -47036,6 +47644,46 @@ var init_project_source_script_compiler = __esm({
47036
47644
  User: "user"
47037
47645
  };
47038
47646
  successfulBodiesByProject = /* @__PURE__ */ new Map();
47647
+ SOURCE_DIALOGUE_GROUP_KINDS = { Standard: "standard", Lookup: "lookup", Folder: "folder" };
47648
+ SourceDialogueGroupLookups = class {
47649
+ constructor(graph) {
47650
+ this.graph = graph;
47651
+ }
47652
+ graph;
47653
+ index;
47654
+ membersByType;
47655
+ resolve(collection) {
47656
+ let member;
47657
+ if (collection?.kind === "member" && collection.receiver.kind === "ident") {
47658
+ member = (this.membersByType ??= new Map(
47659
+ this.graph.project.types.map((type) => [
47660
+ type.name,
47661
+ new Map(type.members.map((candidate) => [candidate.name, candidate]))
47662
+ ])
47663
+ )).get(collection.receiver.name)?.get(collection.name);
47664
+ } else if (collection?.kind === "call" && collection.callee.kind === "ident" && collection.callee.name === "Reference") {
47665
+ const id2 = collection.args[collection.argumentNames?.indexOf("id") ?? -1];
47666
+ if (id2?.kind === "litString")
47667
+ member = this.projectIndex().symbolById.get(id2.value);
47668
+ }
47669
+ if (member === void 0) return void 0;
47670
+ let entry;
47671
+ if (member.type.kind === "list") entry = member.type.elementType;
47672
+ if (member.type.kind === "dictionary") entry = member.type.valueType;
47673
+ if (entry?.kind !== "named") return void 0;
47674
+ const entryTypeName = this.projectIndex().typeById.get(entry.typeId)?.name;
47675
+ if (entryTypeName === void 0) return void 0;
47676
+ return {
47677
+ collection: member.name,
47678
+ entryType: { ...entry, nullable: false },
47679
+ entryTypeName
47680
+ };
47681
+ }
47682
+ projectIndex() {
47683
+ return this.index ??= createProjectIndex(this.graph.project);
47684
+ }
47685
+ };
47686
+ PROJECT_ROOT_TYPE_ID = "builtin:Root";
47039
47687
  }
47040
47688
  });
47041
47689
 
@@ -48028,7 +48676,7 @@ function validateClassOverrides(ref, environment, diagnostics) {
48028
48676
  }
48029
48677
  const target = candidates[candidates.length - 1];
48030
48678
  if (!target) {
48031
- const isDialogueTriggerOverride = ref.declaration.baseTypes.some((base) => base.name === "Dialogue") && member.kind === "field" && member.name === "Trigger" && member.type.name === "Trigger";
48679
+ const isDialogueTriggerOverride = ref.declaration.baseTypes.some((base) => base.name === "NeoDialogue") && member.kind === "field" && member.name === "Trigger" && member.type.name === "Trigger";
48032
48680
  if (isDialogueTriggerOverride) continue;
48033
48681
  const opaqueBase = ref.declaration.baseTypes.find(
48034
48682
  (base) => BUILTIN_TYPES.has(base.name) && !environment.declarations.has(base.name)
@@ -48841,9 +49489,9 @@ var init_project_source_type_checker = __esm({
48841
49489
  "AudioTemplate",
48842
49490
  "Localization",
48843
49491
  "LocalizationStatus",
48844
- "PriorityGroup",
49492
+ "NeoPriorityGroup",
48845
49493
  "PriorityOption",
48846
- "DialogueGroup",
49494
+ "NeoDialogueGroup",
48847
49495
  "ImageRegistry",
48848
49496
  "AudioClipRegistry",
48849
49497
  "NeoImage",
@@ -49122,6 +49770,7 @@ function analyzeNeoProjectSources(inputs, parsedDocuments = /* @__PURE__ */ new
49122
49770
  }
49123
49771
  validateSymbolUniqueness(symbols, diagnostics);
49124
49772
  diagnostics.push(...validateDialogueGroupPaths({ documents, symbols }));
49773
+ diagnostics.push(...validateDialogueGroupNames({ documents, symbols }));
49125
49774
  diagnostics.push(...validateLocalValueInitializers(documents));
49126
49775
  diagnostics.push(...validateVariantDeclarations(documents));
49127
49776
  validateSystemAnnotationAuthoring(documents, diagnostics);
@@ -49625,7 +50274,7 @@ function validateTypeReferences(documents, symbols, diagnostics) {
49625
50274
  declaration.genericParameters.map((parameter4) => parameter4.name)
49626
50275
  ) : /* @__PURE__ */ new Set();
49627
50276
  for (const base of declaration.baseTypes) {
49628
- validateType(uri, base, generics, projectTypes, diagnostics);
50277
+ validateType(uri, base, generics, projectTypes, diagnostics, "base");
49629
50278
  }
49630
50279
  if (declaration.kind === "class") {
49631
50280
  for (const parameter4 of declaration.genericParameters) {
@@ -49635,7 +50284,8 @@ function validateTypeReferences(documents, symbols, diagnostics) {
49635
50284
  parameter4.constraint,
49636
50285
  generics,
49637
50286
  projectTypes,
49638
- diagnostics
50287
+ diagnostics,
50288
+ "base"
49639
50289
  );
49640
50290
  }
49641
50291
  }
@@ -49699,7 +50349,7 @@ function validateMemberTypes(uri, owner, member, genericParameters, projectTypes
49699
50349
  });
49700
50350
  }
49701
50351
  }
49702
- function validateType(uri, type, genericParameters, projectTypes, diagnostics) {
50352
+ function validateType(uri, type, genericParameters, projectTypes, diagnostics, position = "value") {
49703
50353
  if (!BUILTIN_TYPE_NAMES.has(type.name) && !genericParameters.has(type.name) && !projectTypes.has(type.name)) {
49704
50354
  diagnostics.push({
49705
50355
  uri,
@@ -49707,7 +50357,7 @@ function validateType(uri, type, genericParameters, projectTypes, diagnostics) {
49707
50357
  severity: "error",
49708
50358
  source: "neo-project",
49709
50359
  code: "unknown-project-type",
49710
- message: `Unknown project type '${type.name}'. Declare it in a top-level .neo file or correct the type name.`
50360
+ message: renamedDialogueTypeMessage(type.name, position) ?? `Unknown project type '${type.name}'. Declare it in a top-level .neo file or correct the type name.`
49711
50361
  });
49712
50362
  }
49713
50363
  for (const argument2 of type.typeArguments) {
@@ -49740,6 +50390,7 @@ var BUILTIN_TYPE_NAMES, SYSTEM_RECORD_ID_PREFIX2, RFC_4122_UUID, QUARANTINED_LEG
49740
50390
  var init_project_source_analysis = __esm({
49741
50391
  "../packages/neoscript-language/src/project-source-analysis.ts"() {
49742
50392
  "use strict";
50393
+ init_dialogue_types();
49743
50394
  init_project_source_dialogue_groups();
49744
50395
  init_project_local_values();
49745
50396
  init_language_spec();
@@ -49764,9 +50415,9 @@ var init_project_source_analysis = __esm({
49764
50415
  "AudioTemplate",
49765
50416
  "Localization",
49766
50417
  "LocalizationStatus",
49767
- "PriorityGroup",
50418
+ "NeoPriorityGroup",
49768
50419
  "PriorityOption",
49769
- "DialogueGroup",
50420
+ "NeoDialogueGroup",
49770
50421
  "ImageRegistry",
49771
50422
  "AudioClipRegistry",
49772
50423
  "NeoImage",
@@ -50910,7 +51561,7 @@ var init_project_source_manifest = __esm({
50910
51561
  ]);
50911
51562
  FILE_REGISTRY_TYPES = /* @__PURE__ */ new Set(["ImageRegistry", "AudioClipRegistry"]);
50912
51563
  FILE_DECLARATION_TYPES = /* @__PURE__ */ new Set(["NeoImage", "NeoAudioClip"]);
50913
- GROUP_TYPES = /* @__PURE__ */ new Set(["PriorityGroup", "DialogueGroup"]);
51564
+ GROUP_TYPES = /* @__PURE__ */ new Set(["NeoPriorityGroup", "NeoDialogueGroup"]);
50914
51565
  MIGRATION_TYPES = /* @__PURE__ */ new Set(["Migration"]);
50915
51566
  }
50916
51567
  });
@@ -50975,7 +51626,7 @@ var init_registry = __esm({
50975
51626
  "../packages/manifest/schema-contract/registry.mjs"() {
50976
51627
  "use strict";
50977
51628
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
50978
- cliVersion: "0.72.4",
51629
+ cliVersion: "0.73.0",
50979
51630
  projectFileUploadBatchSize: 32,
50980
51631
  documentRecords: {
50981
51632
  member: {
@@ -62280,7 +62931,7 @@ var init_ui_action_source = __esm({
62280
62931
  // src/project-source/dialogue-group-symbols.ts
62281
62932
  function authoredDialogueGroupSymbols(analysis) {
62282
62933
  return new Map(
62283
- analysis?.dialogueGroups.globals.filter((global) => global.type.name === "DialogueGroup").map((global) => [
62934
+ analysis?.dialogueGroups.globals.filter((global) => global.type.name === "NeoDialogueGroup").map((global) => [
62284
62935
  global.id ?? `__pending__:dialogue-group:${encodeURIComponent(global.source.uri)}:${global.source.range.start.line}:${global.source.range.start.character}:${encodeURIComponent(global.name)}`,
62285
62936
  global.name
62286
62937
  ])
@@ -63453,7 +64104,7 @@ function memberSettings(context, member) {
63453
64104
  } else if (member.kind === "dialogueLookup") {
63454
64105
  if (member.dialogueGroupId) {
63455
64106
  settings.push(
63456
- `group: Reference<DialogueGroup>(id: ${quote(member.dialogueGroupId)})`
64107
+ `group: Reference<NeoDialogueGroup>(id: ${quote(member.dialogueGroupId)})`
63457
64108
  );
63458
64109
  }
63459
64110
  if (member.multiselect) settings.push("selection: .Multi");
@@ -63605,7 +64256,7 @@ function renderMemberType(context, member, enclosingClassId, elementSettings = f
63605
64256
  break;
63606
64257
  }
63607
64258
  case "dialogueLookup":
63608
- value = member.multiselect ? "Set<Dialogue>" : "Dialogue";
64259
+ value = member.multiselect ? "Set<NeoDialogueReference>" : "NeoDialogueReference";
63609
64260
  break;
63610
64261
  case "generic":
63611
64262
  value = genericName(context, member.genericParamId);
@@ -63702,7 +64353,7 @@ function renderType(context, type, enclosingClassId) {
63702
64353
  value = "Color";
63703
64354
  break;
63704
64355
  case "dialogueLookup":
63705
- value = "Dialogue";
64356
+ value = "NeoDialogueReference";
63706
64357
  break;
63707
64358
  case "class": {
63708
64359
  const schemaClass2 = required(context.classes, type.classId, "class");
@@ -63896,11 +64547,7 @@ function renderDefaultValue(context, member, wrapper, enclosingClassId) {
63896
64547
  ).name;
63897
64548
  }
63898
64549
  if ((member.kind === "lookup" || member.kind === "dialogueLookup") && Array.isArray(value)) {
63899
- const renderedType = renderMemberType(
63900
- context,
63901
- member,
63902
- enclosingClassId
63903
- ).replace(/\?$/u, "");
64550
+ const renderedType = referenceTargetType(context, member, enclosingClassId);
63904
64551
  const targetType = member.multiselect ? /^Set<(.+)>$/u.exec(renderedType)?.[1] ?? renderedType : renderedType;
63905
64552
  const refs = value.filter((entry) => typeof entry === "string").map((entry) => `Reference<${targetType}>(id: ${quote(entry)})`);
63906
64553
  if (refs.length === 0 && value.length === 0) return "[]";
@@ -63955,9 +64602,16 @@ function renderDefaultValue(context, member, wrapper, enclosingClassId) {
63955
64602
  function spriteFileSource(context, fileId) {
63956
64603
  return context.fileSymbols.get(fileId) ?? `Reference<NeoImage>(id: ${quote(fileId)})`;
63957
64604
  }
64605
+ function referenceTargetType(context, member, enclosingClassId) {
64606
+ if (member.kind === "dialogueLookup") return "NeoDialogue";
64607
+ return renderMemberType(context, member, enclosingClassId).replace(
64608
+ /\?$/u,
64609
+ ""
64610
+ );
64611
+ }
63958
64612
  function renderNestedValue(context, member, value, enclosingClassId) {
63959
64613
  if (typeof value === "string" && member.kind !== "string" && member.kind !== "decimal" && member.kind !== "enum") {
63960
- return `Reference<${renderMemberType(context, member, enclosingClassId).replace(/\?$/, "")}>(id: ${quote(value)})`;
64614
+ return `Reference<${referenceTargetType(context, member, enclosingClassId)}>(id: ${quote(value)})`;
63961
64615
  }
63962
64616
  return renderDefaultValue(
63963
64617
  context,
@@ -66239,7 +66893,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
66239
66893
  const storedStatic = declaration.modifiers.includes("static") && !declaration.modifiers.includes("readonly");
66240
66894
  const settings = annotation(declaration.annotations, "settings");
66241
66895
  const inherited = inheritedMember(context, commonInput.overrideOf);
66242
- const storesSelectionArray = context.enumIdsByName.has(fieldType.name) || fieldType.name === "Dialogue" || Boolean(settings && argument(settings, "collection"));
66896
+ const storesSelectionArray = context.enumIdsByName.has(fieldType.name) || fieldType.name === "NeoDialogueReference" || Boolean(settings && argument(settings, "collection"));
66243
66897
  const common = {
66244
66898
  ...commonInput,
66245
66899
  // A stored static initializer authors the live value binding, never an
@@ -66435,7 +67089,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
66435
67089
  assertNoElementSettings(fieldType, ownerClass, declaration, "enum");
66436
67090
  return { ...common, kind: "enum", enumId: enumId2, multiselect: true };
66437
67091
  }
66438
- if (entryType.name === "Dialogue" && multiselect) {
67092
+ if (entryType.name === "NeoDialogueReference" && multiselect) {
66439
67093
  assertNoElementSettings(fieldType, ownerClass, declaration, "dialogue");
66440
67094
  return {
66441
67095
  ...common,
@@ -66504,7 +67158,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
66504
67158
  }
66505
67159
  };
66506
67160
  }
66507
- if (name === "Dialogue") {
67161
+ if (name === "NeoDialogueReference") {
66508
67162
  return {
66509
67163
  ...common,
66510
67164
  kind: "dialogueLookup",
@@ -67111,7 +67765,8 @@ function lowerType(context, type, ownerClass) {
67111
67765
  };
67112
67766
  }
67113
67767
  }
67114
- if (type.name === "Dialogue") return { kind: "dialogueLookup", nullable: nullable2 };
67768
+ if (type.name === "NeoDialogueReference")
67769
+ return { kind: "dialogueLookup", nullable: nullable2 };
67115
67770
  if (type.name === "object") return { kind: "unknown", nullable: nullable2 };
67116
67771
  throw new Error(`Unknown Neo type ${JSON.stringify(type.name)}.`);
67117
67772
  }
@@ -67910,7 +68565,7 @@ function manifestTypeForSchemaType(context, type) {
67910
68565
  case "vector3Int":
67911
68566
  return { name: "Vector3Int", nullable: nullable2, arguments: [] };
67912
68567
  case "dialogueLookup":
67913
- return { name: "Dialogue", nullable: nullable2, arguments: [] };
68568
+ return { name: "NeoDialogueReference", nullable: nullable2, arguments: [] };
67914
68569
  case "color":
67915
68570
  return { name: "Color", nullable: nullable2, arguments: [] };
67916
68571
  case "class": {
@@ -69453,7 +70108,7 @@ function lowerSupplementalProjectRecordsV4(state, analysis, projectFileRecords)
69453
70108
  );
69454
70109
  }
69455
70110
  const priorityGlobals = analysis.dialogueGroups.globals.filter(
69456
- (global) => global.type.name === "PriorityGroup"
70111
+ (global) => global.type.name === "NeoPriorityGroup"
69457
70112
  );
69458
70113
  const priorityIds = globalIds(priorityGlobals, "priority-group");
69459
70114
  for (const global of priorityGlobals) {
@@ -69468,7 +70123,7 @@ function lowerSupplementalProjectRecordsV4(state, analysis, projectFileRecords)
69468
70123
  );
69469
70124
  }
69470
70125
  const dialogueGlobals = analysis.dialogueGroups.globals.filter(
69471
- (global) => global.type.name === "DialogueGroup"
70126
+ (global) => global.type.name === "NeoDialogueGroup"
69472
70127
  );
69473
70128
  const dialogueIds = globalIds(dialogueGlobals, "dialogue-group");
69474
70129
  const uiLogicResolver = analysisUILogicResolver(analysis);
@@ -69514,7 +70169,7 @@ function emitProjectGlobal(data, textureNames, audioNames, priorityNames) {
69514
70169
  ],
69515
70170
  [
69516
70171
  "defaultPriorityGroup",
69517
- reference(data.defaultPriorityGroupId, priorityNames, "PriorityGroup")
70172
+ reference(data.defaultPriorityGroupId, priorityNames, "NeoPriorityGroup")
69518
70173
  ]
69519
70174
  ].filter((entry) => entry[1] !== null);
69520
70175
  return `Project Project = new(${args.length === 0 ? "" : `
@@ -69540,7 +70195,7 @@ function emitPriorityGroup(data, recordId, name) {
69540
70195
  ...isObjectRecord2(data.system) ? [emitSystemAnnotation(data.system)] : []
69541
70196
  ];
69542
70197
  return `${annotations.join("\n")}
69543
- PriorityGroup ${name} = new() {
70198
+ NeoPriorityGroup ${name} = new() {
69544
70199
  ${body.join("\n\n")}
69545
70200
  }
69546
70201
  `;
@@ -69554,13 +70209,13 @@ function emitDialogueGroup(data, recordId, name, priorityNames, dialogueNames, u
69554
70209
  const priority = reference(
69555
70210
  data.priorityGroupIdOverride,
69556
70211
  priorityNames,
69557
- "PriorityGroup"
70212
+ "NeoPriorityGroup"
69558
70213
  );
69559
70214
  if (priority) args.push(["priorityGroup", priority]);
69560
70215
  const parent = reference(
69561
70216
  data.parentDialogueGroupId,
69562
70217
  dialogueNames,
69563
- "DialogueGroup"
70218
+ "NeoDialogueGroup"
69564
70219
  );
69565
70220
  if (parent) args.push(["parent", parent]);
69566
70221
  if (typeof data.collectionMemberId === "string") {
@@ -69585,7 +70240,7 @@ function emitDialogueGroup(data, recordId, name, priorityNames, dialogueNames, u
69585
70240
  ${args.map(([argument2, value]) => ` ${argument2}: ${value},`).join("\n")}
69586
70241
  )`;
69587
70242
  return `@id(${quote2(recordId)})
69588
- DialogueGroup ${name} = ${constructor2}${body.length > 0 ? ` {
70243
+ NeoDialogueGroup ${name} = ${constructor2}${body.length > 0 ? ` {
69589
70244
  ${body.map((entry) => indentNeoSource(entry, 2)).join("\n\n")}
69590
70245
  }` : ";"}
69591
70246
  `;
@@ -69629,7 +70284,7 @@ function collectDialogueGroupFunctions(data, groupId, resolver) {
69629
70284
  const existing = functions.get(functionId);
69630
70285
  if (existing.code !== code) {
69631
70286
  throw new Error(
69632
- `DialogueGroup function ${functionId} has divergent persisted uses.`
70287
+ `NeoDialogueGroup function ${functionId} has divergent persisted uses.`
69633
70288
  );
69634
70289
  }
69635
70290
  }
@@ -69646,7 +70301,7 @@ function requiredStringField(value, field, owner) {
69646
70301
  }
69647
70302
  function emitDialogueGroupFunction(fn) {
69648
70303
  if (fn.id === null) {
69649
- throw new Error(`Pulled DialogueGroup function ${fn.name} has no id.`);
70304
+ throw new Error(`Pulled NeoDialogueGroup function ${fn.name} has no id.`);
69650
70305
  }
69651
70306
  const annotation2 = `@id(${quote2(fn.id)})`;
69652
70307
  if (fn.code === null) {
@@ -69664,7 +70319,7 @@ function emitDialogueGroupUseList(uses) {
69664
70319
  ${uses.map((use) => {
69665
70320
  if (use.id === null) {
69666
70321
  throw new Error(
69667
- `Pulled DialogueGroup condition ${use.functionName} has no id.`
70322
+ `Pulled NeoDialogueGroup condition ${use.functionName} has no id.`
69668
70323
  );
69669
70324
  }
69670
70325
  return ` @id(${quote2(use.id)})
@@ -69699,7 +70354,7 @@ function lowerProjectGlobal(baseValue, global, analysis) {
69699
70354
  args.get("defaultPriorityGroup"),
69700
70355
  globalIds(
69701
70356
  analysis.dialogueGroups.globals.filter(
69702
- (entry) => entry.type.name === "PriorityGroup"
70357
+ (entry) => entry.type.name === "NeoPriorityGroup"
69703
70358
  ),
69704
70359
  "priority-group"
69705
70360
  )
@@ -69714,7 +70369,7 @@ function lowerPriorityGroup(baseValue, global) {
69714
70369
  const initializer = global.initializer.trim();
69715
70370
  const bodyMatch = /^new\s*\(\s*\)\s*\{([\s\S]*)\}$/.exec(initializer);
69716
70371
  if (!bodyMatch) {
69717
- throw new Error(`PriorityGroup ${global.name} must use new() { ... }.`);
70372
+ throw new Error(`NeoPriorityGroup ${global.name} must use new() { ... }.`);
69718
70373
  }
69719
70374
  let body = bodyMatch[1];
69720
70375
  while (body.trim().length > 0) {
@@ -69723,16 +70378,20 @@ function lowerPriorityGroup(baseValue, global) {
69723
70378
  const match = PRIORITY_OPTION_PATTERN.exec(body);
69724
70379
  if (!match) {
69725
70380
  throw new Error(
69726
- `PriorityGroup ${global.name} contains an unsupported option declaration near ${JSON.stringify(body.slice(0, 80))}.`
70381
+ `NeoPriorityGroup ${global.name} contains an unsupported option declaration near ${JSON.stringify(body.slice(0, 80))}.`
69727
70382
  );
69728
70383
  }
69729
70384
  const name = match[2];
69730
70385
  const id2 = match[1] ? JSON.parse(`"${match[1]}"`) : `__pending__:priority-option:${encodeURIComponent(globalId(global, "priority-group"))}:${encodeURIComponent(name)}`;
69731
70386
  if (seenNames.has(name)) {
69732
- throw new Error(`PriorityGroup ${global.name} repeats option ${name}.`);
70387
+ throw new Error(
70388
+ `NeoPriorityGroup ${global.name} repeats option ${name}.`
70389
+ );
69733
70390
  }
69734
70391
  if (seenIds.has(id2)) {
69735
- throw new Error(`PriorityGroup ${global.name} repeats option id ${id2}.`);
70392
+ throw new Error(
70393
+ `NeoPriorityGroup ${global.name} repeats option id ${id2}.`
70394
+ );
69736
70395
  }
69737
70396
  seenNames.add(name);
69738
70397
  seenIds.add(id2);
@@ -69762,14 +70421,14 @@ function sourceDialogueGroupType(global) {
69762
70421
  const authored = parseDialogueGroupInitializer(global.initializer);
69763
70422
  return dialogueGroupType(
69764
70423
  global.name,
69765
- constructorArguments(authored.constructor, "DialogueGroup")
70424
+ constructorArguments(authored.constructor, "NeoDialogueGroup")
69766
70425
  );
69767
70426
  }
69768
70427
  function dialogueGroupType(name, args) {
69769
70428
  const kind = args.get("kind");
69770
70429
  if (kind?.kind !== "contextualEnum") {
69771
70430
  throw new Error(
69772
- `DialogueGroup ${name} requires kind: .Standard, .Lookup, or .Folder.`
70431
+ `NeoDialogueGroup ${name} requires kind: .Standard, .Lookup, or .Folder.`
69773
70432
  );
69774
70433
  }
69775
70434
  const type = kind.name === "Lookup" ? 1 /* Lookup */ : kind.name === "Folder" ? 2 /* Folder */ : kind.name === "Standard" ? 0 /* Standard */ : null;
@@ -69780,7 +70439,7 @@ function dialogueGroupType(name, args) {
69780
70439
  function dialogueGroupDisplayName(expression, symbol) {
69781
70440
  if (expression?.kind !== "litString" || expression.value.trim().length === 0)
69782
70441
  throw new Error(
69783
- `DialogueGroup ${symbol} name must be a non-empty string literal.`
70442
+ `NeoDialogueGroup ${symbol} name must be a non-empty string literal.`
69784
70443
  );
69785
70444
  return expression.value;
69786
70445
  }
@@ -69790,7 +70449,7 @@ function lowerDialogueGroup(baseValue, global, priorityIds, dialogueIds, uiLogic
69790
70449
  Reflect.deleteProperty(baseWithoutLookup, "collectionMemberId");
69791
70450
  Reflect.deleteProperty(baseWithoutLookup, "collectionValueId");
69792
70451
  const authored = parseDialogueGroupInitializer(global.initializer);
69793
- const args = constructorArguments(authored.constructor, "DialogueGroup");
70452
+ const args = constructorArguments(authored.constructor, "NeoDialogueGroup");
69794
70453
  const type = dialogueGroupType(global.name, args);
69795
70454
  const collection = args.get("collection");
69796
70455
  let collectionMemberId;
@@ -69858,7 +70517,7 @@ function lowerDialogueGroupConditions(base, global, authored, uiLogicResolver) {
69858
70517
  for (const fn of authored.functions) {
69859
70518
  if (functions.has(fn.name)) {
69860
70519
  throw new Error(
69861
- `DialogueGroup ${global.name} repeats function ${fn.name}.`
70520
+ `NeoDialogueGroup ${global.name} repeats function ${fn.name}.`
69862
70521
  );
69863
70522
  }
69864
70523
  functions.set(fn.name, fn);
@@ -69874,14 +70533,14 @@ function lowerDialogueGroupConditions(base, global, authored, uiLogicResolver) {
69874
70533
  );
69875
70534
  if (usedIds.has(id2)) {
69876
70535
  throw new Error(
69877
- `DialogueGroup ${global.name} repeats condition id ${id2}.`
70536
+ `NeoDialogueGroup ${global.name} repeats condition id ${id2}.`
69878
70537
  );
69879
70538
  }
69880
70539
  usedIds.add(id2);
69881
70540
  const fn = functions.get(use.functionName);
69882
70541
  if (!fn) {
69883
70542
  throw new Error(
69884
- `DialogueGroup ${global.name} condition ${use.functionName} has no body function.`
70543
+ `NeoDialogueGroup ${global.name} condition ${use.functionName} has no body function.`
69885
70544
  );
69886
70545
  }
69887
70546
  usedFunctions.add(fn.name);
@@ -69919,7 +70578,7 @@ function lowerDialogueGroupConditions(base, global, authored, uiLogicResolver) {
69919
70578
  for (const fn of authored.functions) {
69920
70579
  if (!usedFunctions.has(fn.name)) {
69921
70580
  throw new Error(
69922
- `DialogueGroup ${global.name} function ${fn.name} is not referenced by when.`
70581
+ `NeoDialogueGroup ${global.name} function ${fn.name} is not referenced by when.`
69923
70582
  );
69924
70583
  }
69925
70584
  }
@@ -70000,12 +70659,12 @@ function parseDialogueGroupInitializer(initializer) {
70000
70659
  }
70001
70660
  }
70002
70661
  if (closeIndex < 0) {
70003
- throw new Error("DialogueGroup initializer has an unclosed body.");
70662
+ throw new Error("NeoDialogueGroup initializer has an unclosed body.");
70004
70663
  }
70005
70664
  const close = tokens[closeIndex];
70006
70665
  const trailing = tokens.slice(closeIndex + 1);
70007
70666
  if (trailing.length > 1 || trailing[0] && trailing[0].text !== ";") {
70008
- throw new Error("Nothing may follow a DialogueGroup body.");
70667
+ throw new Error("Nothing may follow a NeoDialogueGroup body.");
70009
70668
  }
70010
70669
  let depth = 0;
70011
70670
  let whenIndex = -1;
@@ -70015,7 +70674,7 @@ function parseDialogueGroupInitializer(initializer) {
70015
70674
  else if (token.text === "}") depth -= 1;
70016
70675
  else if (depth === 0 && token.text === "when") {
70017
70676
  if (whenIndex >= 0) {
70018
- throw new Error("DialogueGroup body may declare when only once.");
70677
+ throw new Error("NeoDialogueGroup body may declare when only once.");
70019
70678
  }
70020
70679
  whenIndex = index;
70021
70680
  }
@@ -70026,7 +70685,7 @@ function parseDialogueGroupInitializer(initializer) {
70026
70685
  if (whenIndex < 0) {
70027
70686
  if (parsedFunctions.length > 0) {
70028
70687
  throw new Error(
70029
- "DialogueGroup body functions require a final when: [...] use list."
70688
+ "NeoDialogueGroup body functions require a final when: [...] use list."
70030
70689
  );
70031
70690
  }
70032
70691
  return {
@@ -70038,7 +70697,7 @@ function parseDialogueGroupInitializer(initializer) {
70038
70697
  const colon = tokens[whenIndex + 1];
70039
70698
  if (colon?.text !== ":") {
70040
70699
  throw new Error(
70041
- "DialogueGroup condition uses must be written as when: [...]."
70700
+ "NeoDialogueGroup condition uses must be written as when: [...]."
70042
70701
  );
70043
70702
  }
70044
70703
  let parenDepth = 0;
@@ -70059,10 +70718,12 @@ function parseDialogueGroupInitializer(initializer) {
70059
70718
  }
70060
70719
  }
70061
70720
  if (semicolonIndex < 0) {
70062
- throw new Error("DialogueGroup when: [...] must end with a semicolon.");
70721
+ throw new Error("NeoDialogueGroup when: [...] must end with a semicolon.");
70063
70722
  }
70064
70723
  if (tokens.slice(semicolonIndex + 1, closeIndex).length > 0) {
70065
- throw new Error("DialogueGroup when: [...] must be the final body entry.");
70724
+ throw new Error(
70725
+ "NeoDialogueGroup when: [...] must be the final body entry."
70726
+ );
70066
70727
  }
70067
70728
  const semicolon = tokens[semicolonIndex];
70068
70729
  return {
@@ -70084,17 +70745,17 @@ function parseDialogueGroupFunctions(source) {
70084
70745
  );
70085
70746
  if (errors.length > 0) {
70086
70747
  throw new Error(
70087
- `Invalid DialogueGroup body: ${errors.map((diagnostic) => diagnostic.message).join(" ")}`
70748
+ `Invalid NeoDialogueGroup body: ${errors.map((diagnostic) => diagnostic.message).join(" ")}`
70088
70749
  );
70089
70750
  }
70090
70751
  const declaration = parsed.declarations[0];
70091
70752
  if (declaration?.kind !== "class") {
70092
- throw new Error("DialogueGroup body could not be parsed.");
70753
+ throw new Error("NeoDialogueGroup body could not be parsed.");
70093
70754
  }
70094
70755
  return declaration.members.map((member) => {
70095
70756
  if (member.kind !== "function") {
70096
70757
  throw new Error(
70097
- "DialogueGroup bodies may contain only zero-argument bool functions and a final when: [...] list."
70758
+ "NeoDialogueGroup bodies may contain only zero-argument bool functions and a final when: [...] list."
70098
70759
  );
70099
70760
  }
70100
70761
  assertDialogueGroupFunctionSignature(member);
@@ -70108,19 +70769,19 @@ function parseDialogueGroupFunctions(source) {
70108
70769
  function assertDialogueGroupFunctionSignature(member) {
70109
70770
  if (member.type.name !== "bool" || member.type.nullable || member.type.typeArguments.length > 0 || member.parameters.length > 0 || member.modifiers.includes("async")) {
70110
70771
  throw new Error(
70111
- `DialogueGroup function ${member.name} must be a synchronous zero-argument bool function.`
70772
+ `NeoDialogueGroup function ${member.name} must be a synchronous zero-argument bool function.`
70112
70773
  );
70113
70774
  }
70114
70775
  if (member.body === void 0 && !member.modifiers.includes("native")) {
70115
70776
  throw new Error(
70116
- `DialogueGroup function ${member.name} requires a body or the native modifier.`
70777
+ `NeoDialogueGroup function ${member.name} requires a body or the native modifier.`
70117
70778
  );
70118
70779
  }
70119
70780
  }
70120
70781
  function parseDialogueGroupUseList(expression) {
70121
70782
  const trimmed = expression.trim();
70122
70783
  if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) {
70123
- throw new Error("DialogueGroup when uses must use bracket list syntax.");
70784
+ throw new Error("NeoDialogueGroup when uses must use bracket list syntax.");
70124
70785
  }
70125
70786
  const body = trimmed.slice(1, -1);
70126
70787
  const pattern = /\s*(?:@id\(\s*("(?:[^"\\]|\\.)*")\s*\)\s*)?([A-Za-z_][A-Za-z0-9_]*)\s*(?:,|$)/gy;
@@ -70132,7 +70793,7 @@ function parseDialogueGroupUseList(expression) {
70132
70793
  if (!match) {
70133
70794
  if (body.slice(consumed).trim().length === 0) break;
70134
70795
  throw new Error(
70135
- `Invalid DialogueGroup condition-use list near ${JSON.stringify(body.slice(consumed))}.`
70796
+ `Invalid NeoDialogueGroup condition-use list near ${JSON.stringify(body.slice(consumed))}.`
70136
70797
  );
70137
70798
  }
70138
70799
  result.push({
@@ -70149,7 +70810,7 @@ function annotationId(annotations) {
70149
70810
  const parsed = JSON.parse(expression);
70150
70811
  if (typeof parsed !== "string" || parsed.length === 0) {
70151
70812
  throw new Error(
70152
- "DialogueGroup function @id must contain a non-empty string."
70813
+ "NeoDialogueGroup function @id must contain a non-empty string."
70153
70814
  );
70154
70815
  }
70155
70816
  return parsed;
@@ -70441,7 +71102,7 @@ function builtinTextVariableMember(receiver, name) {
70441
71102
  function createDialogueLoweringIndexesV4(state, analysis, options = {}) {
70442
71103
  const mainLocale = readMainLocale(state);
70443
71104
  const dialogueGroups = analysis.dialogueGroups.globals.filter(
70444
- (global) => global.type.name === "DialogueGroup"
71105
+ (global) => global.type.name === "NeoDialogueGroup"
70445
71106
  );
70446
71107
  const dialogueGroupIds = globalIds2(dialogueGroups, "dialogue-group");
70447
71108
  const lookupDialogueGroupIds = new Set(
@@ -71819,7 +72480,7 @@ function lowerDialogueGroupSettings(context, member, base) {
71819
72480
  const expression = constructorExpression(member.arguments, "group");
71820
72481
  if (expression === null) return null;
71821
72482
  const old = isObjectRecord2(base.dialogueGroupSettings) ? base.dialogueGroupSettings : {};
71822
- const referencedGroupId = referenceId3(expression, "DialogueGroup");
72483
+ const referencedGroupId = referenceId3(expression, "NeoDialogueGroup");
71823
72484
  if (referencedGroupId !== null) {
71824
72485
  if (!context.groupPaths.byId.has(referencedGroupId)) {
71825
72486
  throw dialogueSourceError(
@@ -72723,7 +73384,7 @@ var init_dialogue_lower = __esm({
72723
73384
  required: required2
72724
73385
  };
72725
73386
  }
72726
- if (type.name === "Dialogue") {
73387
+ if (type.name === "NeoDialogueReference") {
72727
73388
  return { type: 18 /* DialogueLookup */, required: required2 };
72728
73389
  }
72729
73390
  return null;
@@ -72864,7 +73525,8 @@ function projectSchemaManifest(input, options = {}) {
72864
73525
  (item, index) => enumType(item, environment, `enums[${index}]`)
72865
73526
  )
72866
73527
  ];
72867
- const rootType = createRootType(rootMemberIds, environment);
73528
+ const dialogues = neoScriptDialogueTypes(options.dialogueGroups ?? []);
73529
+ const rootType = createRootType(rootMemberIds, environment, dialogues.member);
72868
73530
  declaredTypes.push(rootType);
72869
73531
  const roots = options.roots ?? [
72870
73532
  {
@@ -72883,7 +73545,7 @@ function projectSchemaManifest(input, options = {}) {
72883
73545
  return {
72884
73546
  project: {
72885
73547
  version: options.version ?? `manifest:${nextManifestProjectionVersion++}`,
72886
- types: languageTypes,
73548
+ types: [...languageTypes, ...dialogues.types],
72887
73549
  globals: options.globals ?? [],
72888
73550
  roots,
72889
73551
  listIndexes: members.flatMap(
@@ -73018,7 +73680,7 @@ function staticDefaultWritability(classId, environment) {
73018
73680
  resolvedAllowedStorage(classId, environment)
73019
73681
  );
73020
73682
  }
73021
- function createRootType(ids, environment) {
73683
+ function createRootType(ids, environment, dialogues) {
73022
73684
  const definitions = [
73023
73685
  ["Assets", ids.assets, false, "immutable"],
73024
73686
  ["Save", ids.save, true, "save"],
@@ -73041,6 +73703,7 @@ function createRootType(ids, environment) {
73041
73703
  ...sourceLocation(member.source, environment, `root.${name}.source`)
73042
73704
  });
73043
73705
  }
73706
+ members.push(dialogues);
73044
73707
  return {
73045
73708
  id: "__root__",
73046
73709
  name: "Root",
@@ -73817,8 +74480,7 @@ function memberType(member, environment, visiting, field) {
73817
74480
  return member.multiselect === true ? { kind: "set", elementType: entryType, nullable: nullable2 } : { ...entryType, nullable: nullable2 };
73818
74481
  }
73819
74482
  if (kind === "dialogueLookup") {
73820
- const dialogue = primitive("DialogueRef", false);
73821
- return member.multiselect === true ? { kind: "set", elementType: dialogue, nullable: nullable2 } : { ...dialogue, nullable: nullable2 };
74483
+ return member.multiselect === true ? { kind: "set", elementType: primitive("string", false), nullable: nullable2 } : { ...primitive("NeoDialogueReference", false), nullable: nullable2 };
73822
74484
  }
73823
74485
  if (kind === "computed") {
73824
74486
  return manifestType2(member.returnType, environment, `${field}.returnType`);
@@ -74300,7 +74962,7 @@ function manifestPrimitive(kind) {
74300
74962
  case "vector3Int":
74301
74963
  return "Vector3Int";
74302
74964
  case "dialogueLookup":
74303
- return "DialogueRef";
74965
+ return "NeoDialogueReference";
74304
74966
  case "color":
74305
74967
  return "Color";
74306
74968
  default:
@@ -74467,6 +75129,7 @@ var init_project_schema_manifest = __esm({
74467
75129
  init_project2();
74468
75130
  init_project2();
74469
75131
  init_language_spec();
75132
+ init_dialogue_types();
74470
75133
  nextManifestProjectionVersion = 1;
74471
75134
  }
74472
75135
  });
@@ -74598,6 +75261,58 @@ var init_interface_types = __esm({
74598
75261
  }
74599
75262
  });
74600
75263
 
75264
+ // ../src/models/dialogue/dialogue-group-language.ts
75265
+ function dialogueGroupLanguageContract(group) {
75266
+ return {
75267
+ id: group.id,
75268
+ name: group.name,
75269
+ type: group.type,
75270
+ parentDialogueGroupId: group.parentDialogueGroupId ?? null,
75271
+ collectionMemberId: group.type === 1 /* Lookup */ ? group.collectionMemberId : null
75272
+ };
75273
+ }
75274
+ function storedDialogueGroupSources(groups, memberById2, classById) {
75275
+ const sources2 = [];
75276
+ for (const group of groups) {
75277
+ const lookup = group.type === 1 /* Lookup */ ? lookupEntry(group.collectionMemberId, memberById2, classById) : void 0;
75278
+ sources2.push({
75279
+ id: group.id,
75280
+ name: group.name,
75281
+ parentId: group.parentDialogueGroupId ?? null,
75282
+ kind: KINDS[group.type],
75283
+ ...lookup ? { lookup } : {}
75284
+ });
75285
+ }
75286
+ return sources2;
75287
+ }
75288
+ function lookupEntry(collectionMemberId, memberById2, classById) {
75289
+ const collection = memberById2(collectionMemberId);
75290
+ if (!isMemberListBase(collection) && !isMemberDictionaryBase(collection))
75291
+ return void 0;
75292
+ const entry = memberById2(collection.entryMemberId);
75293
+ if (!isMemberClassBase(entry)) return void 0;
75294
+ const entryClass = classById(entry.classId);
75295
+ if (!entryClass) return void 0;
75296
+ return {
75297
+ collection: collection.name,
75298
+ entryType: { kind: "named", typeId: entryClass.id },
75299
+ entryTypeName: entryClass.name
75300
+ };
75301
+ }
75302
+ var KINDS;
75303
+ var init_dialogue_group_language = __esm({
75304
+ "../src/models/dialogue/dialogue-group-language.ts"() {
75305
+ "use strict";
75306
+ init_members();
75307
+ init_dialogue_group_types();
75308
+ KINDS = {
75309
+ [0 /* Standard */]: "standard",
75310
+ [1 /* Lookup */]: "lookup",
75311
+ [2 /* Folder */]: "folder"
75312
+ };
75313
+ }
75314
+ });
75315
+
74601
75316
  // ../src/runtime/neoscript/analyzer-types.ts
74602
75317
  function createAnalyzerSchemaIndex(context) {
74603
75318
  return projectSchemaIndexFor({
@@ -74817,8 +75532,15 @@ function createNeoScriptProjectInScope(context) {
74817
75532
  })
74818
75533
  });
74819
75534
  }
74820
- const rootType = createRootType2(context);
74821
- languageTypes.push(rootType);
75535
+ const dialogues = neoScriptDialogueTypes(
75536
+ storedDialogueGroupSources(
75537
+ context.vm.dialogueGroups ?? [],
75538
+ (id2) => analyzerMemberById(context, id2),
75539
+ (id2) => analyzerSchemaIndex(context).classesById.get(id2)
75540
+ )
75541
+ );
75542
+ const rootType = createRootType2(context, dialogues.member);
75543
+ languageTypes.push(rootType, ...dialogues.types);
74822
75544
  if (context.dialogueContext) {
74823
75545
  languageTypes.push(createDialogueContextType(context));
74824
75546
  }
@@ -75346,7 +76068,7 @@ function interfaceMemberToSymbol(neoInterface, key, member, context, inherited)
75346
76068
  ...inheritedFrom ? { inheritedFrom } : {}
75347
76069
  };
75348
76070
  }
75349
- function createRootType2(context) {
76071
+ function createRootType2(context, dialogues) {
75350
76072
  const members = [];
75351
76073
  for (const [index, root] of PROJECT_ROOTS.entries()) {
75352
76074
  const name = root.key;
@@ -75371,6 +76093,7 @@ function createRootType2(context) {
75371
76093
  )
75372
76094
  });
75373
76095
  }
76096
+ members.push(dialogues);
75374
76097
  return {
75375
76098
  id: AnalyzerRootClassId,
75376
76099
  name: "Root",
@@ -75473,11 +76196,11 @@ function memberRuntimeType(record7, context, seen = /* @__PURE__ */ new Set(), g
75473
76196
  if (isMemberDialogueLookupBase(member) && isMultiSelectionMember(member)) {
75474
76197
  return {
75475
76198
  kind: "set",
75476
- elementType: primitive2("DialogueRef", true),
76199
+ elementType: primitive2("string", true),
75477
76200
  nullable: !required2
75478
76201
  };
75479
76202
  }
75480
- return primitive2("DialogueRef", required2);
76203
+ return primitive2("NeoDialogueReference", required2);
75481
76204
  case 14 /* Vector2 */:
75482
76205
  return primitive2("Vector2", required2);
75483
76206
  case 15 /* Vector2Int */:
@@ -75725,7 +76448,7 @@ function toLanguageType(type, context, genericEnvironment) {
75725
76448
  case 12 /* Audio */:
75726
76449
  return primitive2("AudioClipInfo", required2);
75727
76450
  case 18 /* DialogueLookup */:
75728
- return primitive2("DialogueRef", required2);
76451
+ return primitive2("NeoDialogueReference", required2);
75729
76452
  case 14 /* Vector2 */:
75730
76453
  return primitive2("Vector2", required2);
75731
76454
  case 15 /* Vector2Int */:
@@ -75925,7 +76648,9 @@ function projectLanguageVersion(context) {
75925
76648
  ...context.vm.projectFiles ?? [],
75926
76649
  // P43 §6. Editing a constructor's parameters changes what a `new Foo(…)`
75927
76650
  // call site resolves to, so an open editor's cached context must rebuild.
75928
- ...context.constructors ?? []
76651
+ ...context.constructors ?? [],
76652
+ // P105 §2.6. Group names, parents, and kinds shape `root.Dialogues`.
76653
+ ...context.vm.dialogueGroups ?? []
75929
76654
  ];
75930
76655
  return [
75931
76656
  `adapter:${NEOSCRIPT_COMPILER_ADAPTER_REVISION}`,
@@ -76133,8 +76858,10 @@ var init_neoscript_language_context_adapter = __esm({
76133
76858
  init_variant_member();
76134
76859
  init_project_root_members();
76135
76860
  init_project_file_registry();
76861
+ init_dialogue_types();
76862
+ init_dialogue_group_language();
76136
76863
  init_analyzer_types();
76137
- NEOSCRIPT_COMPILER_ADAPTER_REVISION = 5;
76864
+ NEOSCRIPT_COMPILER_ADAPTER_REVISION = 6;
76138
76865
  UNKNOWN_TYPE2 = {
76139
76866
  kind: "primitive",
76140
76867
  name: "unknown"
@@ -86405,6 +87132,26 @@ function evalFunction(fn, scope, ctx) {
86405
87132
  const pointer = evalPointer(fn.info.pointer, scope, ctx);
86406
87133
  return dialogueMemoryVisitCount(pointer, ctx) > 0;
86407
87134
  }
87135
+ case "dialogueGroup" /* dialogueGroup */: {
87136
+ if (fn.info.valuePointer !== void 0)
87137
+ evalPointer(fn.info.valuePointer, scope, ctx);
87138
+ if (fn.info.onFinishPointer !== void 0)
87139
+ evalPointer(fn.info.onFinishPointer, scope, ctx);
87140
+ return false;
87141
+ }
87142
+ case "dialogue" /* dialogue */: {
87143
+ const idPointer = fn.info.dialogueIdPointer;
87144
+ const dialogueId = evalPointer(idPointer, scope, ctx);
87145
+ if (dialogueId === null && idPointer.type === "keyOf" /* keyOf */ && idPointer.optional === true)
87146
+ return null;
87147
+ if (typeof dialogueId !== "string")
87148
+ throw new NSGetterRuntimeError(
87149
+ `${fn.info.op} needs a dialogue id string, but got ${dialogueId === null ? "null" : typeof dialogueId}.`
87150
+ );
87151
+ if (fn.info.onFinishPointer !== void 0)
87152
+ evalPointer(fn.info.onFinishPointer, scope, ctx);
87153
+ return false;
87154
+ }
86408
87155
  case "vectorConstructor" /* vectorConstructor */: {
86409
87156
  return evalVectorConstructor(
86410
87157
  fn.info.vectorType,
@@ -95496,6 +96243,7 @@ function createAnalyzerProject(ctx) {
95496
96243
  return {
95497
96244
  project: ctx.project,
95498
96245
  projectFiles: [...ctx.projectFiles ?? []],
96246
+ dialogueGroups: [...ctx.dialogueGroups ?? []],
95499
96247
  members,
95500
96248
  classes: [...ctx.classes],
95501
96249
  enums: [...ctx.enums],
@@ -96823,6 +97571,7 @@ function compileDelegateClosureValue(code, signature) {
96823
97571
  const compiled = compileNSGetter(`return ${code};`, {
96824
97572
  project: signature.project,
96825
97573
  projectFiles: [...signature.projectFiles ?? []],
97574
+ dialogueGroups: signature.dialogueGroups ?? [],
96826
97575
  members: [...signature.members],
96827
97576
  classes: [...signature.classes],
96828
97577
  enums: [...signature.enums],
@@ -96908,6 +97657,7 @@ function compilationProjectContext(args, members = args.members) {
96908
97657
  return {
96909
97658
  project: args.project,
96910
97659
  projectFiles: args.projectFiles ?? [],
97660
+ dialogueGroups: args.dialogueGroups ?? [],
96911
97661
  members: [...members],
96912
97662
  classes: [...args.classes],
96913
97663
  enums: [...args.enums],
@@ -97558,6 +98308,7 @@ function compilationProjectForDocument(document, state) {
97558
98308
  state.compilationProject ??= createNeoScriptCompilationProject({
97559
98309
  project: document.project,
97560
98310
  projectFiles: document.projectFiles,
98311
+ dialogueGroups: document.dialogueGroups,
97561
98312
  members: document.members,
97562
98313
  classes: document.classes,
97563
98314
  enums: document.enums,
@@ -97651,6 +98402,7 @@ function compileValueInitializerDependency(document, valueId, compilationProject
97651
98402
  compileValueRowInitializerBody({
97652
98403
  project: document.project,
97653
98404
  projectFiles: document.projectFiles,
98405
+ dialogueGroups: document.dialogueGroups,
97654
98406
  members: document.members,
97655
98407
  classes: document.classes,
97656
98408
  enums: document.enums,
@@ -97669,6 +98421,7 @@ function compileMemberInitializerDependency(document, memberId, compilationProje
97669
98421
  const compileArgs = {
97670
98422
  project: document.project,
97671
98423
  projectFiles: document.projectFiles,
98424
+ dialogueGroups: document.dialogueGroups,
97672
98425
  members: document.members,
97673
98426
  classes: document.classes,
97674
98427
  enums: document.enums,
@@ -98136,7 +98889,7 @@ function isDialogueProps(value) {
98136
98889
  function isDialogue(value) {
98137
98890
  return isDialogueProps(value);
98138
98891
  }
98139
- var init_dialogue_types = __esm({
98892
+ var init_dialogue_types2 = __esm({
98140
98893
  "../src/models/dialogue/dialogue-types.ts"() {
98141
98894
  "use strict";
98142
98895
  init_core_types();
@@ -99462,7 +100215,7 @@ var init_project_document_read = __esm({
99462
100215
  init_constructors2();
99463
100216
  init_variants();
99464
100217
  init_dialogue_group_types();
99465
- init_dialogue_types();
100218
+ init_dialogue_types2();
99466
100219
  init_priority_types();
99467
100220
  init_enum();
99468
100221
  init_neoscript();
@@ -99772,7 +100525,9 @@ function collectCompilerReferencesInto(value, field, ids, names, constructedClas
99772
100525
  function isCompilerReferenceField(field) {
99773
100526
  return /(?:member|class|enum|interface|constructor|variant)(?:Type)?Ids?$/i.test(
99774
100527
  field
99775
- ) || field === "baseTypeIds" || field === "collectionValueId" || field === "fileId" || field === "primaryLinkedValueId" || field === "recordIds" || field === "valueId";
100528
+ ) || field === "baseTypeIds" || field === "collectionValueId" || field === "fileId" || // P105 §2.5. Dialogue-group calls name their group by `groupId`. The
100529
+ // IR kind is new, so the derived-edge extractor version doesn't change.
100530
+ field === "groupId" || field === "primaryLinkedValueId" || field === "recordIds" || field === "valueId";
99776
100531
  }
99777
100532
  function collectChangedContractIds(args) {
99778
100533
  const impactedIds = /* @__PURE__ */ new Set();
@@ -99802,7 +100557,26 @@ function collectChangedContractIds(args) {
99802
100557
  );
99803
100558
  const currentSchemaRecords = schemaRecordsByKind(args.currentDocument);
99804
100559
  const postSchemaRecords = schemaRecordsByKind(args.postDocument);
100560
+ const currentGroups = new DialogueGroupTree(args.currentDocument);
100561
+ const postGroups = new DialogueGroupTree(args.postDocument);
99805
100562
  for (const change of args.changes) {
100563
+ if (change.recordKind === "dialogue-group") {
100564
+ const current2 = currentGroups.byId.get(change.recordId);
100565
+ const next2 = postGroups.byId.get(change.recordId);
100566
+ if (current2 !== void 0 && next2 !== void 0 && canonicalJsonStringify(dialogueGroupLanguageContract(current2)) === canonicalJsonStringify(dialogueGroupLanguageContract(next2))) {
100567
+ continue;
100568
+ }
100569
+ currentGroups.addSubtree(change.recordId, impactedIds);
100570
+ postGroups.addSubtree(change.recordId, impactedIds);
100571
+ for (const group of [current2, next2]) {
100572
+ if (group !== void 0) {
100573
+ impactedTypeNames.add(
100574
+ generatedCSharpTypeName(group.name, "DialogueGroup")
100575
+ );
100576
+ }
100577
+ }
100578
+ continue;
100579
+ }
99806
100580
  if (change.recordKind === "class" || change.recordKind === "enum" || change.recordKind === "interface") {
99807
100581
  const kind = change.recordKind;
99808
100582
  const current2 = currentSchemaRecords[kind].get(change.recordId);
@@ -100322,7 +101096,7 @@ function withoutFields(value, ignored) {
100322
101096
  Object.entries(value).filter(([field]) => !ignored.has(field))
100323
101097
  );
100324
101098
  }
100325
- var NON_CONTRACT_MEMBER_FIELDS, NS_PROPERTY_BODY_FIELDS, NS_FUNCTION_BODY_FIELDS, NO_PLACEMENTS, classPlacementIndexes;
101099
+ var NON_CONTRACT_MEMBER_FIELDS, NS_PROPERTY_BODY_FIELDS, NS_FUNCTION_BODY_FIELDS, DialogueGroupTree, NO_PLACEMENTS, classPlacementIndexes;
100326
101100
  var init_neo_script_recompile_scope = __esm({
100327
101101
  "../src/database/neo-script-recompile-scope.ts"() {
100328
101102
  "use strict";
@@ -100330,6 +101104,8 @@ var init_neo_script_recompile_scope = __esm({
100330
101104
  init_neo_script_derived_bodies();
100331
101105
  init_canonical_json();
100332
101106
  init_lexer();
101107
+ init_generated_csharp_identifiers();
101108
+ init_dialogue_group_language();
100333
101109
  init_member_kind_enum();
100334
101110
  init_member_kinds();
100335
101111
  init_inheritance();
@@ -100363,6 +101139,31 @@ var init_neo_script_recompile_scope = __esm({
100363
101139
  "bodyMode",
100364
101140
  "uiAction"
100365
101141
  ]);
101142
+ DialogueGroupTree = class {
101143
+ byId = /* @__PURE__ */ new Map();
101144
+ children = /* @__PURE__ */ new Map();
101145
+ constructor(document) {
101146
+ for (const group of document.dialogueGroups ?? []) {
101147
+ this.byId.set(group.id, group);
101148
+ const parentId = group.parentDialogueGroupId;
101149
+ if (parentId === null || parentId === void 0) continue;
101150
+ const siblings = this.children.get(parentId) ?? [];
101151
+ siblings.push(group.id);
101152
+ this.children.set(parentId, siblings);
101153
+ }
101154
+ }
101155
+ addSubtree(id2, ids) {
101156
+ ids.add(id2);
101157
+ const queue = [id2];
101158
+ for (const groupId of queue) {
101159
+ for (const child2 of this.children.get(groupId) ?? []) {
101160
+ if (ids.has(child2)) continue;
101161
+ ids.add(child2);
101162
+ queue.push(child2);
101163
+ }
101164
+ }
101165
+ }
101166
+ };
100366
101167
  NO_PLACEMENTS = /* @__PURE__ */ new Set();
100367
101168
  classPlacementIndexes = /* @__PURE__ */ new WeakMap();
100368
101169
  }
@@ -101198,7 +101999,7 @@ var init_project_record_validation = __esm({
101198
101999
  init_packed_value_record_validation();
101199
102000
  init_enum();
101200
102001
  init_interface_types();
101201
- init_dialogue_types();
102002
+ init_dialogue_types2();
101202
102003
  init_dialogue_group_types();
101203
102004
  init_priority_types();
101204
102005
  init_files();
@@ -106009,6 +106810,7 @@ function resolveDialogueCompileContext(args) {
106009
106810
  classes: args.classes,
106010
106811
  enums: args.enums,
106011
106812
  interfaces: args.interfaces ?? [],
106813
+ dialogueGroups: args.dialogueGroups,
106012
106814
  thisClass: resolveNeoSchemaClassFromTypeInfo(thisClass, args.classes),
106013
106815
  returnTypeInfo: args.returnTypeInfo,
106014
106816
  ...valueAliases.length ? { valueAliases } : {},
@@ -106078,6 +106880,7 @@ function resolveDialogueGroupCompileContext(args) {
106078
106880
  classes: args.classes,
106079
106881
  enums: args.enums,
106080
106882
  interfaces: args.interfaces ?? [],
106883
+ dialogueGroups: args.dialogueGroups,
106081
106884
  thisClass,
106082
106885
  returnTypeInfo: args.returnTypeInfo,
106083
106886
  dialogueContext: {
@@ -106110,7 +106913,15 @@ function compileDialogueLogic(request, projectData, reuseProject) {
106110
106913
  "Invalid dialogue logic compile body: expected ICompileDialogueLogicRequest."
106111
106914
  );
106112
106915
  }
106113
- const { project, members, classes, values, enums, interfaces } = projectData;
106916
+ const {
106917
+ project,
106918
+ members,
106919
+ classes,
106920
+ values,
106921
+ enums,
106922
+ interfaces,
106923
+ dialogueGroups
106924
+ } = projectData;
106114
106925
  if (request.target === 0 /* Condition */) {
106115
106926
  const ctx2 = request.dialogueGroup ? resolveDialogueGroupCompileContext({
106116
106927
  project,
@@ -106119,6 +106930,7 @@ function compileDialogueLogic(request, projectData, reuseProject) {
106119
106930
  values,
106120
106931
  enums,
106121
106932
  interfaces,
106933
+ dialogueGroups,
106122
106934
  dialogueGroup: request.dialogueGroup,
106123
106935
  returnTypeInfo: { type: 1 /* Bool */, required: true }
106124
106936
  }) : resolveDialogueCompileContext({
@@ -106128,6 +106940,7 @@ function compileDialogueLogic(request, projectData, reuseProject) {
106128
106940
  values,
106129
106941
  enums,
106130
106942
  interfaces,
106943
+ dialogueGroups,
106131
106944
  dialogue: request.dialogue ?? {},
106132
106945
  node: request.node,
106133
106946
  returnTypeInfo: { type: 1 /* Bool */, required: true }
@@ -106162,6 +106975,7 @@ function compileDialogueLogic(request, projectData, reuseProject) {
106162
106975
  values,
106163
106976
  enums,
106164
106977
  interfaces,
106978
+ dialogueGroups,
106165
106979
  dialogue: request.dialogue ?? {},
106166
106980
  node: request.node,
106167
106981
  returnTypeInfo: sourceBacked ? request.textVariable.typeInfo : { type: 3 /* String */, required: true }
@@ -106191,6 +107005,7 @@ function compileDialogueLogic(request, projectData, reuseProject) {
106191
107005
  values,
106192
107006
  enums,
106193
107007
  interfaces,
107008
+ dialogueGroups,
106194
107009
  dialogue: request.dialogue ?? {},
106195
107010
  node: request.node,
106196
107011
  returnTypeInfo: { type: 0 /* Null */, required: true }
@@ -108377,7 +109192,7 @@ var init_general_function_call_ir_source_recompile = __esm({
108377
109192
  "use strict";
108378
109193
  init_members();
108379
109194
  init_core();
108380
- init_dialogue_types();
109195
+ init_dialogue_types2();
108381
109196
  init_logic_types();
108382
109197
  init_inheritance();
108383
109198
  init_project_content_hash();
@@ -108875,6 +109690,9 @@ function neoScriptCompilationProjectContract(document) {
108875
109690
  name: file.name,
108876
109691
  fileType: file.fileType
108877
109692
  })),
109693
+ dialogueGroups: (document.dialogueGroups ?? []).map(
109694
+ dialogueGroupLanguageContract
109695
+ ),
108878
109696
  members: document.members.map(
108879
109697
  (member) => neoScriptMemberContractProjection(
108880
109698
  member
@@ -108925,6 +109743,7 @@ var init_project_fingerprint = __esm({
108925
109743
  "use strict";
108926
109744
  init_strict_ir();
108927
109745
  init_neo_script_recompile_scope();
109746
+ init_dialogue_group_language();
108928
109747
  init_compiler_adapter();
108929
109748
  }
108930
109749
  });
@@ -113756,6 +114575,7 @@ function prepareServerOwnedValueInitializerBodies(args) {
113756
114575
  const compilationProject = cachedServerCompilationProject({
113757
114576
  project: document.project,
113758
114577
  projectFiles: document.projectFiles,
114578
+ dialogueGroups: document.dialogueGroups,
113759
114579
  members: document.members,
113760
114580
  classes: document.classes,
113761
114581
  enums: document.enums,
@@ -113781,6 +114601,7 @@ function prepareServerOwnedValueInitializerBodies(args) {
113781
114601
  compileValueRowInitializerBody({
113782
114602
  project: document.project,
113783
114603
  projectFiles: document.projectFiles,
114604
+ dialogueGroups: document.dialogueGroups,
113784
114605
  members: document.members,
113785
114606
  classes: document.classes,
113786
114607
  enums: document.enums,
@@ -113996,6 +114817,7 @@ function compileInlineDelegateConstructorArguments(args) {
113996
114817
  compiled[argumentKey] = compileDelegateClosureValue(argument2.code, {
113997
114818
  project: document.project,
113998
114819
  projectFiles: document.projectFiles,
114820
+ dialogueGroups: document.dialogueGroups,
113999
114821
  members: document.members,
114000
114822
  classes: document.classes,
114001
114823
  enums: document.enums,
@@ -114045,6 +114867,7 @@ function createDelegateValueBodyCompiler(postDocument, targetIds) {
114045
114867
  compiled.value = compileDelegateClosureValue(row.value.code, {
114046
114868
  project: document.project,
114047
114869
  projectFiles: document.projectFiles,
114870
+ dialogueGroups: document.dialogueGroups,
114048
114871
  members: document.members,
114049
114872
  classes: document.classes,
114050
114873
  enums: document.enums,
@@ -114225,6 +115048,7 @@ function prepareServerOwnedConstructorBodies(args) {
114225
115048
  ),
114226
115049
  project: document.project,
114227
115050
  projectFiles: document.projectFiles,
115051
+ dialogueGroups: document.dialogueGroups,
114228
115052
  members: document.members,
114229
115053
  classes: document.classes,
114230
115054
  enums: document.enums,
@@ -114406,6 +115230,7 @@ function compileOneAuthoredMember(args) {
114406
115230
  scriptSources: args.scriptSources,
114407
115231
  project: args.document.project,
114408
115232
  projectFiles: args.document.projectFiles,
115233
+ dialogueGroups: args.document.dialogueGroups,
114409
115234
  members: args.members,
114410
115235
  classes: args.document.classes,
114411
115236
  enums: args.document.enums,
@@ -123071,6 +123896,7 @@ function replayStoredConstructionV4(args) {
123071
123896
  const compilationProject = args.compilationProject ?? (args.compileDocumentBodies === true ? createNeoScriptCompilationProject({
123072
123897
  project: document.project,
123073
123898
  projectFiles: document.projectFiles,
123899
+ dialogueGroups: document.dialogueGroups,
123074
123900
  members: document.members,
123075
123901
  classes: document.classes,
123076
123902
  enums: document.enums,
@@ -123127,6 +123953,7 @@ function replayStoredConstructionV4(args) {
123127
123953
  compileValueRowInitializerBody({
123128
123954
  project: document.project,
123129
123955
  projectFiles: document.projectFiles,
123956
+ dialogueGroups: document.dialogueGroups,
123130
123957
  members: document.members,
123131
123958
  classes: document.classes,
123132
123959
  enums: document.enums,
@@ -123198,6 +124025,7 @@ function compilePulledUncompiledConstructorsV4(document, compilationProject, rep
123198
124025
  const project = compilationProject ?? createNeoScriptCompilationProject({
123199
124026
  project: document.project,
123200
124027
  projectFiles: document.projectFiles,
124028
+ dialogueGroups: document.dialogueGroups,
123201
124029
  members: document.members,
123202
124030
  classes: document.classes,
123203
124031
  enums: document.enums,
@@ -123207,6 +124035,7 @@ function compilePulledUncompiledConstructorsV4(document, compilationProject, rep
123207
124035
  const compileArgs = {
123208
124036
  project: document.project,
123209
124037
  projectFiles: document.projectFiles,
124038
+ dialogueGroups: document.dialogueGroups,
123210
124039
  members: document.members,
123211
124040
  classes: document.classes,
123212
124041
  enums: document.enums,
@@ -123223,6 +124052,7 @@ function compilePulledProjectDocumentForEvaluationV4(document, compilationProjec
123223
124052
  const sharedCompilationProject = compilationProject ?? createNeoScriptCompilationProject({
123224
124053
  project: document.project,
123225
124054
  projectFiles: document.projectFiles,
124055
+ dialogueGroups: document.dialogueGroups,
123226
124056
  members: document.members,
123227
124057
  classes: document.classes,
123228
124058
  enums: document.enums,
@@ -123233,6 +124063,7 @@ function compilePulledProjectDocumentForEvaluationV4(document, compilationProjec
123233
124063
  const compileArgs = {
123234
124064
  project: document.project,
123235
124065
  projectFiles: document.projectFiles,
124066
+ dialogueGroups: document.dialogueGroups,
123236
124067
  members: document.members,
123237
124068
  classes: document.classes,
123238
124069
  enums: document.enums,
@@ -129560,7 +130391,7 @@ function validateReferenceContract(context, member, target, ownerValueId) {
129560
130391
  `Dialogue member ${member.name} requires a dialogue target.`
129561
130392
  );
129562
130393
  }
129563
- if (target.genericTypeName && target.genericTypeName !== "Dialogue" && target.genericTypeName !== target.typeName) {
130394
+ if (target.genericTypeName && target.genericTypeName !== "NeoDialogue" && target.genericTypeName !== target.typeName) {
129564
130395
  throw new Error(
129565
130396
  `Reference<${target.genericTypeName}> does not accept dialogue ${target.id}.`
129566
130397
  );
@@ -129583,7 +130414,7 @@ function lookupEntryTypeName(context, member) {
129583
130414
  if (entry.kind === "class")
129584
130415
  return context.classes.get(entry.classId)?.name ?? null;
129585
130416
  if (entry.kind === "enum") return null;
129586
- if (entry.kind === "dialogueLookup") return "Dialogue";
130417
+ if (entry.kind === "dialogueLookup") return "NeoDialogueReference";
129587
130418
  return entry.kind;
129588
130419
  }
129589
130420
  function referenceTypeNameAssignable(context, actualName, expectedName) {
@@ -130105,7 +130936,7 @@ function freshConstructionReplaysDeclaredDefault(resolved, child2, defaultValue)
130105
130936
  function classMemberByName(context, classId, name) {
130106
130937
  const memberId = classMemberIdByName(context, classId, name);
130107
130938
  if (memberId !== null) return requiredMember(context, memberId);
130108
- throw new Error(
130939
+ throw new MissingStoredMemberError(
130109
130940
  `Class ${context.classes.get(classId)?.name ?? classId} has no stored member ${name}.`
130110
130941
  );
130111
130942
  }
@@ -131711,7 +132542,7 @@ function storedSchemaTypeName(context, type, environment, valueId) {
131711
132542
  case "lookup":
131712
132543
  return storedSchemaTypeName(context, type.entryType, environment);
131713
132544
  case "dialogueLookup":
131714
- return "Dialogue";
132545
+ return "NeoDialogueReference";
131715
132546
  case "delegate":
131716
132547
  return "object";
131717
132548
  case "action":
@@ -132288,7 +133119,7 @@ function referenceValue(context, member, body, dialogue) {
132288
133119
  }
132289
133120
  const symbol = context.localValues?.byValueId.get(id2)?.name ?? context.symbolsByValueId.get(id2);
132290
133121
  if (symbol !== void 0) return `Reference(${symbol})`;
132291
- const type = dialogue ? "Dialogue" : memberReferenceType(context, member);
133122
+ const type = dialogue ? "NeoDialogue" : memberReferenceType(context, member);
132292
133123
  if (!dialogue) {
132293
133124
  const key = uniqueIndexKeyForTarget(context, member, id2);
132294
133125
  if (key !== null) return `Reference<${type}>(key: ${quote3(key)})`;
@@ -132647,7 +133478,7 @@ function memberDefaultBody(member) {
132647
133478
  if (!("value" in defaultValue)) return null;
132648
133479
  return defaultValue.value;
132649
133480
  }
132650
- var INFERRED_GENERIC_CLASS_PREFIX, MEMBER_KIND_DICTIONARY2, MEMBER_KIND_LIST2, MEMBER_KIND_CLASS2, LEADING_AUTHORED_ROW_ID, INITIALIZER_KEY_PLACEHOLDER, CANONICAL_CONSTRUCTOR_INLINE_WIDTH;
133481
+ var INFERRED_GENERIC_CLASS_PREFIX, MEMBER_KIND_DICTIONARY2, MEMBER_KIND_LIST2, MEMBER_KIND_CLASS2, LEADING_AUTHORED_ROW_ID, INITIALIZER_KEY_PLACEHOLDER, MissingStoredMemberError, CANONICAL_CONSTRUCTOR_INLINE_WIDTH;
132651
133482
  var init_value_sources = __esm({
132652
133483
  "src/project-source/value-sources.ts"() {
132653
133484
  "use strict";
@@ -132712,6 +133543,8 @@ var init_value_sources = __esm({
132712
133543
  `${PENDING_ID_PREFIX}reference-key:init:\\d+`,
132713
133544
  "g"
132714
133545
  );
133546
+ MissingStoredMemberError = class extends Error {
133547
+ };
132715
133548
  CANONICAL_CONSTRUCTOR_INLINE_WIDTH = 88;
132716
133549
  }
132717
133550
  });
@@ -136537,9 +137370,11 @@ function emitDialogue(args) {
136537
137370
  content: `@id(${quote5(dialogueId)})
136538
137371
  ${args.recoveryReason ? `@incomplete(${quote5(args.recoveryReason)})
136539
137372
  ` : ""}@settings(
136540
- ${settings.map(([name, value]) => ` ${name}: ${value}`).join(",\n")}
137373
+ ${settings.map(([name, value]) => ` ${name}: ${value}`).join(
137374
+ ",\n"
137375
+ )}
136541
137376
  )
136542
- sealed class ${args.className} : Dialogue {
137377
+ sealed class ${args.className} : NeoDialogue {
136543
137378
  ${members.map((member) => indentNeoSource(member, 2)).join("\n\n")}
136544
137379
  }
136545
137380
  `,
@@ -136574,7 +137409,10 @@ function emitTrigger(context, node) {
136574
137409
  if (groupName && optionName && !context.groupChildNames.get(groupId)?.has(optionName))
136575
137410
  args.push(["group", `${groupName}.${optionName}`]);
136576
137411
  else if (groupId) {
136577
- args.push(["group", `Reference<DialogueGroup>(id: ${quote5(groupId)})`]);
137412
+ args.push([
137413
+ "group",
137414
+ `Reference<NeoDialogueGroup>(id: ${quote5(groupId)})`
137415
+ ]);
136578
137416
  if (optionId) {
136579
137417
  args.push([
136580
137418
  "priority",
@@ -137283,7 +138121,7 @@ var init_dialogue_sources = __esm({
137283
138121
  init_ui_action_source();
137284
138122
  PERSISTED_VARIABLE_PATH = /^(?:ref|linked):([^.]+)(\..+)?$/u;
137285
138123
  DIALOGUE_SYSTEM_TYPE_NAMES = [
137286
- "Dialogue",
138124
+ "NeoDialogue",
137287
138125
  "Trigger",
137288
138126
  "Text",
137289
138127
  "Actions",
@@ -138478,6 +139316,7 @@ function loadOrBuildNeoScriptProjectV1(root, document) {
138478
139316
  const project = createNeoScriptCompilationProject({
138479
139317
  project: document.project,
138480
139318
  projectFiles: document.projectFiles,
139319
+ dialogueGroups: document.dialogueGroups,
138481
139320
  members: document.members,
138482
139321
  classes: document.classes,
138483
139322
  enums: document.enums,
@@ -139410,6 +140249,25 @@ function workspaceStatusInitializerDiagnostic(workspace, status, sites, texts, a
139410
140249
  }
139411
140250
  }
139412
140251
  function computeWorkspaceStatus(workspace, options) {
140252
+ const conflictedFiles = [];
140253
+ const parseErrors = [];
140254
+ const parseWarnings = [];
140255
+ try {
140256
+ return computeStatus(
140257
+ workspace,
140258
+ options,
140259
+ conflictedFiles,
140260
+ parseErrors,
140261
+ parseWarnings
140262
+ );
140263
+ } catch (error) {
140264
+ if (error instanceof MissingStoredMemberError && parseErrors.some(isBlockingSchemaSourceError)) {
140265
+ return refusedStatus(conflictedFiles, parseErrors, parseWarnings);
140266
+ }
140267
+ throw error;
140268
+ }
140269
+ }
140270
+ function computeStatus(workspace, options, conflictedFiles, parseErrors, parseWarnings) {
139413
140271
  assertCurrentBaseline(workspace.state.records);
139414
140272
  let phaseStarted = performance.now();
139415
140273
  options.onPhase?.("Reading project schema\u2026");
@@ -139419,9 +140277,6 @@ function computeWorkspaceStatus(workspace, options) {
139419
140277
  phaseStarted = finished;
139420
140278
  if (nextLabel !== void 0) options.onPhase?.(nextLabel);
139421
140279
  };
139422
- const conflictedFiles = [];
139423
- const parseErrors = [];
139424
- const parseWarnings = [];
139425
140280
  const migrationSources = [];
139426
140281
  const projectSources = [];
139427
140282
  if (options.virtualSourceFiles === void 0) {
@@ -140630,6 +141485,7 @@ function replayAnimationDeclarationInitializersV4(records3, document, fallbackDo
140630
141485
  const compilationProject = createNeoScriptCompilationProject({
140631
141486
  project: replayDocument.project,
140632
141487
  projectFiles: replayDocument.projectFiles,
141488
+ dialogueGroups: replayDocument.dialogueGroups,
140633
141489
  members: replayDocument.members,
140634
141490
  classes: replayDocument.classes,
140635
141491
  enums: replayDocument.enums,
@@ -147042,37 +147898,37 @@ function collectionSymbols(kind, type) {
147042
147898
  const readOnly = type.readOnly === true;
147043
147899
  const canMutate = !readOnly;
147044
147900
  const symbols = [
147045
- method(
147901
+ method2(
147046
147902
  "Where",
147047
147903
  type,
147048
147904
  lambdaParameters(kind, entryType, keyType),
147049
147905
  "Filter this collection."
147050
147906
  ),
147051
- method(
147907
+ method2(
147052
147908
  "First",
147053
147909
  entryType,
147054
147910
  lambdaParameters(kind, entryType, keyType),
147055
147911
  "Return the first matching entry; throws when none exists."
147056
147912
  ),
147057
- method(
147913
+ method2(
147058
147914
  "FirstOrDefault",
147059
147915
  withNullability(entryType, true),
147060
147916
  lambdaParameters(kind, entryType, keyType),
147061
147917
  "Return the first matching entry, or null."
147062
147918
  ),
147063
- method(
147919
+ method2(
147064
147920
  "Select",
147065
147921
  { kind: "list", elementType: UNKNOWN_TYPE },
147066
147922
  lambdaParameters(kind, entryType, keyType),
147067
147923
  "Map each collection entry."
147068
147924
  ),
147069
- method(
147925
+ method2(
147070
147926
  "Contains",
147071
147927
  { kind: "primitive", name: "bool" },
147072
147928
  [parameter3("value", entryType)],
147073
147929
  "Return whether the collection contains a value."
147074
147930
  ),
147075
- method(
147931
+ method2(
147076
147932
  "Count",
147077
147933
  { kind: "primitive", name: "int" },
147078
147934
  [optionalCollectionPredicate(kind, entryType, keyType)],
@@ -147120,7 +147976,7 @@ function collectionSymbols(kind, type) {
147120
147976
  })
147121
147977
  ];
147122
147978
  symbols.push(
147123
- method(
147979
+ method2(
147124
147980
  name,
147125
147981
  returnType,
147126
147982
  parameters,
@@ -147130,7 +147986,7 @@ function collectionSymbols(kind, type) {
147130
147986
  }
147131
147987
  if (kind === "list") {
147132
147988
  symbols.push(
147133
- method(
147989
+ method2(
147134
147990
  "IndexOf",
147135
147991
  { kind: "primitive", name: "int" },
147136
147992
  [parameter3("value", entryType)],
@@ -147220,7 +148076,7 @@ function optionalCollectionPredicate(kind, entry, key) {
147220
148076
  defaultValue: { displayText: "null", value: null }
147221
148077
  };
147222
148078
  }
147223
- function method(name, returnType, parameters, documentation) {
148079
+ function method2(name, returnType, parameters, documentation) {
147224
148080
  return {
147225
148081
  id: `builtin:collection:${name}`,
147226
148082
  name,
@@ -147232,11 +148088,11 @@ function method(name, returnType, parameters, documentation) {
147232
148088
  };
147233
148089
  }
147234
148090
  function mutationMethod(name, returnType, parameters, documentation) {
147235
- return method(name, returnType, parameters, documentation);
148091
+ return method2(name, returnType, parameters, documentation);
147236
148092
  }
147237
148093
  function stringReplaceSymbol() {
147238
148094
  const stringType = { kind: "primitive", name: "string" };
147239
- return method(
148095
+ return method2(
147240
148096
  "Replace",
147241
148097
  stringType,
147242
148098
  [parameter3("search", stringType), parameter3("replacement", stringType)],
@@ -147244,7 +148100,7 @@ function stringReplaceSymbol() {
147244
148100
  );
147245
148101
  }
147246
148102
  function stringContainsSymbol() {
147247
- return method(
148103
+ return method2(
147248
148104
  "Contains",
147249
148105
  { kind: "primitive", name: "bool" },
147250
148106
  [parameter3("substring", { kind: "primitive", name: "string" })],
@@ -147367,9 +148223,9 @@ function inferLambdaParameterType(local, snapshot) {
147367
148223
  ]);
147368
148224
  for (let cursor = declarationIndex - 1; cursor >= 1; cursor--) {
147369
148225
  const open = tokens[cursor];
147370
- const method2 = tokens[cursor - 1];
148226
+ const method3 = tokens[cursor - 1];
147371
148227
  if (!open || open.kind !== "punctuation" || open.text !== "(") continue;
147372
- if (!method2 || method2.kind !== "identifier" || !lambdaMethods.has(method2.text)) {
148228
+ if (!method3 || method3.kind !== "identifier" || !lambdaMethods.has(method3.text)) {
147373
148229
  continue;
147374
148230
  }
147375
148231
  const dot = tokens[cursor - 2];
@@ -148723,7 +149579,7 @@ function projectAnnotationNamesAt(analysis, document, position) {
148723
149579
  "settings",
148724
149580
  "storage",
148725
149581
  "relations",
148726
- .../\bDialogue\b/.test(followingDeclaration[2] ?? "") ? ["incomplete"] : []
149582
+ .../\bNeoDialogue\b/.test(followingDeclaration[2] ?? "") ? ["incomplete"] : []
148727
149583
  ];
148728
149584
  }
148729
149585
  if (followingDeclaration) return ["id"];
@@ -148755,7 +149611,7 @@ function projectDeclarationAnnotationNames(declaration) {
148755
149611
  "settings",
148756
149612
  "storage",
148757
149613
  "relations",
148758
- ...declaration.baseTypes.some((type) => type.name === "Dialogue") ? ["incomplete"] : []
149614
+ ...declaration.baseTypes.some((type) => type.name === "NeoDialogue") ? ["incomplete"] : []
148759
149615
  ];
148760
149616
  }
148761
149617
  function projectMemberAnnotationNames(member) {
@@ -151126,7 +151982,7 @@ function dialogueGroupCompletions(analysis, document, position) {
151126
151982
  items.push({
151127
151983
  label: name,
151128
151984
  kind: "variable",
151129
- detail: "DialogueGroup",
151985
+ detail: "NeoDialogueGroup",
151130
151986
  insertText: name,
151131
151987
  symbolId: child2.id
151132
151988
  });
@@ -153042,10 +153898,10 @@ function readWorkspaceRecordFilesV4(workspace, dialogueGroupSymbols) {
153042
153898
  for (const absolute of listProjectSourceFilesV4(workspace.root)) {
153043
153899
  const path = relative4(workspace.root, absolute).split(sep4).join("/");
153044
153900
  const content = readFileSync11(absolute, "utf8");
153045
- if (dialogueGroupSymbols && /\bDialogueGroup\b/u.test(content) && neoProjectSourceKind(path, content) === "definition") {
153901
+ if (dialogueGroupSymbols && /\bNeoDialogueGroup\b/u.test(content) && neoProjectSourceKind(path, content) === "definition") {
153046
153902
  const source = parseNeoProjectSource(content, "definition", path);
153047
153903
  for (const declaration of source.declarations) {
153048
- if (declaration.kind !== "global" || declaration.type.name !== "DialogueGroup")
153904
+ if (declaration.kind !== "global" || declaration.type.name !== "NeoDialogueGroup")
153049
153905
  continue;
153050
153906
  const annotation2 = declaration.annotations.find(
153051
153907
  (item) => item.name === "id"
@@ -160635,11 +161491,8 @@ function dialogueGroupBaseClass(ctx, group, lookupType) {
160635
161491
  function dialogueGroupTriggerMethods(ctx, group, lookupType) {
160636
161492
  if (group.type === 0 /* Standard */) {
160637
161493
  return [
160638
- "public bool TryTrigger(out NeoDialogue dialogue) =>",
160639
- " TryTriggerStandard(out dialogue);",
160640
- "",
160641
- "public bool TryTrigger(out NeoDialogueTriggerResult result) =>",
160642
- " TryTriggerStandard(out result);"
161494
+ "public bool TryTrigger(Action? onFinish = null) =>",
161495
+ " TryTriggerStandard(onFinish);"
160643
161496
  ];
160644
161497
  }
160645
161498
  if (group.type !== 1 /* Lookup */) return [];
@@ -160649,11 +161502,8 @@ function dialogueGroupTriggerMethods(ctx, group, lookupType) {
160649
161502
  ];
160650
161503
  }
160651
161504
  return [
160652
- `public bool TryTrigger(${lookupType} value, out NeoDialogue dialogue) =>`,
160653
- " TryTriggerLookup(value, out dialogue);",
160654
- "",
160655
- `public bool TryTrigger(${lookupType} value, out NeoDialogueTriggerResult result) =>`,
160656
- " TryTriggerLookup(value, out result);"
161505
+ `public bool TryTrigger(${lookupType} value, Action? onFinish = null) =>`,
161506
+ " TryTriggerLookup(value, onFinish);"
160657
161507
  ];
160658
161508
  }
160659
161509
  function generateDialogueGroupProperty(ctx, group) {
@@ -160887,9 +161737,9 @@ function generateRelationTileGridContentClass(ctx, grid, saved) {
160887
161737
  ""
160888
161738
  ];
160889
161739
  const layerBindingExpression = (layer) => {
160890
- const method2 = `${saved ? "BindWritable" : "BindReadOnly"}${layer.kind === "tile" ? "Tile" : "Object"}Layer`;
161740
+ const method3 = `${saved ? "BindWritable" : "BindReadOnly"}${layer.kind === "tile" ? "Tile" : "Object"}Layer`;
160891
161741
  const imports = csharpStringArray(layer.importedClassIds);
160892
- return `primitive.${method2}<${layer.className}>("${escapeCSharpString(layer.layerClassId)}", ${imports})`;
161742
+ return `primitive.${method3}<${layer.className}>("${escapeCSharpString(layer.layerClassId)}", ${imports})`;
160893
161743
  };
160894
161744
  const privateConstructor = saved ? [
160895
161745
  `private ${className}(${primitiveType2} primitive)`,
@@ -161102,7 +161952,7 @@ function generateEnumClass(ctx, enumId) {
161102
161952
  ...indent([...arms, `_ => ${fallback},`]),
161103
161953
  "};"
161104
161954
  ];
161105
- const method2 = (signature, body) => [
161955
+ const method3 = (signature, body) => [
161106
161956
  signature,
161107
161957
  "{",
161108
161958
  ...indent(body),
@@ -161127,7 +161977,7 @@ function generateEnumClass(ctx, enumId) {
161127
161977
  `public static class ${optionsName}`,
161128
161978
  "{",
161129
161979
  ...indent([
161130
- ...method2(
161980
+ ...method3(
161131
161981
  `public static ${enumName} FromOptionId(string optionId)`,
161132
161982
  switchBody(
161133
161983
  "optionId",
@@ -161136,7 +161986,7 @@ function generateEnumClass(ctx, enumId) {
161136
161986
  )
161137
161987
  ),
161138
161988
  "",
161139
- ...method2(
161989
+ ...method3(
161140
161990
  `public static string OptionId(this ${enumName} value)`,
161141
161991
  switchBody(
161142
161992
  "value",
@@ -161145,7 +161995,7 @@ function generateEnumClass(ctx, enumId) {
161145
161995
  )
161146
161996
  ),
161147
161997
  "",
161148
- ...method2(
161998
+ ...method3(
161149
161999
  `public static string[] ToOptionIds(IEnumerable<${enumName}>? options)`,
161150
162000
  [
161151
162001
  "if (options is null) return Array.Empty<string>();",
@@ -161155,7 +162005,7 @@ function generateEnumClass(ctx, enumId) {
161155
162005
  ]
161156
162006
  ),
161157
162007
  "",
161158
- ...method2(
162008
+ ...method3(
161159
162009
  "public static bool IsKnown(string optionId)",
161160
162010
  switchBody(
161161
162011
  "optionId",
@@ -161164,7 +162014,7 @@ function generateEnumClass(ctx, enumId) {
161164
162014
  )
161165
162015
  ),
161166
162016
  "",
161167
- ...method2(
162017
+ ...method3(
161168
162018
  `public static string TextId(this ${enumName} value)`,
161169
162019
  switchBody(
161170
162020
  "value",
@@ -161173,7 +162023,7 @@ function generateEnumClass(ctx, enumId) {
161173
162023
  )
161174
162024
  ),
161175
162025
  "",
161176
- ...method2(
162026
+ ...method3(
161177
162027
  `public static string Text(this ${enumName} value, NeoClient? client = null)`,
161178
162028
  [
161179
162029
  ctx.singleton ? `return (client ?? ${ctx.projectClassName}.RequireInstance().Client).Localization.ResolveText(value.TextId());` : "return client is null ? value.TextId() : client.Localization.ResolveText(value.TextId());"
@@ -169100,6 +169950,28 @@ function addNeoScriptFunctionReferenceDiagnostics(args) {
169100
169950
  });
169101
169951
  return;
169102
169952
  }
169953
+ if (args.fn.type === "dialogueGroup" /* dialogueGroup */ || args.fn.type === "dialogue" /* dialogue */) {
169954
+ const info = args.fn.info;
169955
+ const pointers = [
169956
+ ["valuePointer", "valuePointer" in info ? info.valuePointer : void 0],
169957
+ [
169958
+ "dialogueIdPointer",
169959
+ "dialogueIdPointer" in info ? info.dialogueIdPointer : void 0
169960
+ ],
169961
+ ["onFinishPointer", info.onFinishPointer]
169962
+ ];
169963
+ for (const [field, pointer] of pointers) {
169964
+ if (pointer === void 0) continue;
169965
+ addPointerReferenceDiagnostics({
169966
+ diagnostics: args.diagnostics,
169967
+ pointer,
169968
+ allowDeferredFunctions: args.allowDeferredFunctions,
169969
+ context: args.context,
169970
+ path: `${args.path}.info.${field}`
169971
+ });
169972
+ }
169973
+ return;
169974
+ }
169103
169975
  if (args.fn.type === "vectorConstructor" /* vectorConstructor */) {
169104
169976
  args.fn.info.componentPointers.forEach((pointer, index) => {
169105
169977
  addPointerReferenceDiagnostics({
@@ -170018,7 +170890,7 @@ var init_dialogue_diagnostics = __esm({
170018
170890
  init_interface_types();
170019
170891
  init_interface_graph();
170020
170892
  init_neoscript();
170021
- init_dialogue_types();
170893
+ init_dialogue_types2();
170022
170894
  init_dialogue_group_types();
170023
170895
  init_logic_types();
170024
170896
  init_core();
@@ -170787,7 +171659,7 @@ var init_project_unity_export_diagnostics = __esm({
170787
171659
  "use strict";
170788
171660
  init_project_world_placement_bindings();
170789
171661
  init_dialogue_diagnostics();
170790
- init_dialogue_types();
171662
+ init_dialogue_types2();
170791
171663
  init_members();
170792
171664
  init_core_types();
170793
171665
  init_inheritance();
@@ -170809,7 +171681,7 @@ var UNITY_CODEGEN_REVISION;
170809
171681
  var init_unity_codegen_revision = __esm({
170810
171682
  "../src/models/exports/unity-codegen-revision.ts"() {
170811
171683
  "use strict";
170812
- UNITY_CODEGEN_REVISION = "45a0847addd4616acfc29f142556dcb2e0a27daae14d6aa456430228e66dbc07";
171684
+ UNITY_CODEGEN_REVISION = "e4a632a177c87244e19da71c9840b8007735773ae5f81578f58ce246ec6cb03d";
170813
171685
  }
170814
171686
  });
170815
171687
 
@@ -170819,7 +171691,7 @@ var init_project_unity_export_types = __esm({
170819
171691
  "../src/models/exports/project-unity-export-types.ts"() {
170820
171692
  "use strict";
170821
171693
  init_unity_codegen_revision();
170822
- PROJECT_UNITY_EXPORT_SCHEMA_VERSION = 38;
171694
+ PROJECT_UNITY_EXPORT_SCHEMA_VERSION = 39;
170823
171695
  }
170824
171696
  });
170825
171697
 
@@ -175872,6 +176744,7 @@ async function buildPostPushCompileSchema(workspace, status) {
175872
176744
  return {
175873
176745
  project,
175874
176746
  projectFiles: [...bucket("project-file").values()],
176747
+ dialogueGroups: [...bucket("dialogue-group").values()],
175875
176748
  members: [...bucket("member").values()],
175876
176749
  classes: [...bucket("class").values()],
175877
176750
  constructors: [...bucket("constructor").values()],
@@ -175885,6 +176758,7 @@ function createPostPushCompileContext(schema) {
175885
176758
  const project = {
175886
176759
  project: schema.project,
175887
176760
  projectFiles: schema.projectFiles,
176761
+ dialogueGroups: schema.dialogueGroups ?? [],
175888
176762
  members: schema.members,
175889
176763
  classes: schema.classes,
175890
176764
  constructors: schema.constructors,
@@ -179633,6 +180507,7 @@ function createCliNeoScriptContext(options) {
179633
180507
  const vm = {
179634
180508
  project: options.documents.project,
179635
180509
  projectFiles: [...options.documents.projectFiles ?? []],
180510
+ dialogueGroups: [...options.documents.dialogueGroups ?? []],
179636
180511
  members,
179637
180512
  classes: [...options.documents.classes],
179638
180513
  enums: [...options.documents.enums],
@@ -179659,10 +180534,25 @@ function createCliNeoScriptContext(options) {
179659
180534
  // root placement is server context, not authored schema-manifest state.
179660
180535
  roots: compilerContext.project.roots,
179661
180536
  globals: compilerContext.project.globals,
179662
- version: compilerContext.project.version
180537
+ version: compilerContext.project.version,
180538
+ dialogueGroups: cliDialogueGroupSources(options.documents)
179663
180539
  });
179664
180540
  return { ...compilerContext, project: projection.project };
179665
180541
  }
180542
+ function cliDialogueGroupSources(documents) {
180543
+ if (!documents.dialogueGroups?.length) return [];
180544
+ const members = new Map(
180545
+ documents.members.map((member) => [member.id, member])
180546
+ );
180547
+ const classes = new Map(
180548
+ documents.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
180549
+ );
180550
+ return storedDialogueGroupSources(
180551
+ documents.dialogueGroups,
180552
+ (id2) => members.get(id2),
180553
+ (id2) => classes.get(id2)
180554
+ );
180555
+ }
179666
180556
  async function validateCliNeoScript(uri, source, context) {
179667
180557
  const service = createCliNeoScriptLanguageService();
179668
180558
  const document = {
@@ -179719,7 +180609,8 @@ function createCliManifestScriptContext(manifest, scriptPath2, unit, options = {
179719
180609
  const projectedManifest = manifestWithUniqueInlineScriptKeys(manifest);
179720
180610
  const projection = projectSchemaManifest(projectedManifest, {
179721
180611
  ...options.rootMemberIds ? { rootMemberIds: options.rootMemberIds } : {},
179722
- ...options.sourceUri ? { sourceUri: options.sourceUri } : {}
180612
+ ...options.sourceUri ? { sourceUri: options.sourceUri } : {},
180613
+ ...options.dialogueGroups ? { dialogueGroups: options.dialogueGroups } : {}
179723
180614
  });
179724
180615
  const normalizedPath = options.memberId === void 0 ? normalizeWorkspacePath(scriptPath2) : inlineScriptKey(scriptPath2, options.memberId);
179725
180616
  const script = projection.scripts.get(normalizedPath);
@@ -179767,7 +180658,8 @@ function analyzeManifestScripts(manifest, options = {}) {
179767
180658
  const projectedManifest = manifestWithUniqueInlineScriptKeys(manifest);
179768
180659
  const projection = projectSchemaManifest(projectedManifest, {
179769
180660
  ...options.rootMemberIds ? { rootMemberIds: options.rootMemberIds } : {},
179770
- ...options.sourceUri ? { sourceUri: options.sourceUri } : {}
180661
+ ...options.sourceUri ? { sourceUri: options.sourceUri } : {},
180662
+ ...options.dialogueGroups ? { dialogueGroups: options.dialogueGroups } : {}
179771
180663
  });
179772
180664
  const sources2 = /* @__PURE__ */ new Map();
179773
180665
  const scriptPathByMemberId = /* @__PURE__ */ new Map();
@@ -179849,6 +180741,7 @@ var init_neoscript_language_adapter = __esm({
179849
180741
  init_service();
179850
180742
  init_strict_ir();
179851
180743
  init_neoscript_language_context_adapter();
180744
+ init_dialogue_group_language();
179852
180745
  }
179853
180746
  });
179854
180747
 
@@ -180821,7 +181714,8 @@ async function runScript(workspace, command, options, dependencies = {}) {
180821
181714
  localCheckManifest,
180822
181715
  localTarget,
180823
181716
  command,
180824
- options
181717
+ options,
181718
+ localCheckDocument === null ? [] : cliDialogueGroupSources(localCheckDocument)
180825
181719
  );
180826
181720
  return;
180827
181721
  }
@@ -180872,6 +181766,7 @@ async function runScript(workspace, command, options, dependencies = {}) {
180872
181766
  const compilerProject = {
180873
181767
  project: document.project,
180874
181768
  projectFiles: document.projectFiles,
181769
+ dialogueGroups: document.dialogueGroups,
180875
181770
  members: document.members,
180876
181771
  classes: document.classes,
180877
181772
  constructors: document.constructors,
@@ -181044,6 +181939,7 @@ async function runScript(workspace, command, options, dependencies = {}) {
181044
181939
  variants: document.variants,
181045
181940
  variantFolders: document.variantFolders,
181046
181941
  projectFiles: document.projectFiles,
181942
+ dialogueGroups: document.dialogueGroups,
181047
181943
  textureTemplates: document.textureTemplates,
181048
181944
  localizationConfig: document.localizationConfig,
181049
181945
  localizedTexts: document.localizedTexts,
@@ -181506,7 +182402,7 @@ function localMemberOwnerKeys(member) {
181506
182402
  }
181507
182403
  return [];
181508
182404
  }
181509
- async function runLocalTargetCommand(manifest, target, command, options) {
182405
+ async function runLocalTargetCommand(manifest, target, command, options, dialogueGroups) {
181510
182406
  const member = target.member;
181511
182407
  const script = member.script;
181512
182408
  if (script === null) {
@@ -181561,6 +182457,7 @@ async function runLocalTargetCommand(manifest, target, command, options) {
181561
182457
  const source = readSource(options, fallback);
181562
182458
  const context = createCliManifestScriptContext(manifest, script.path, unit, {
181563
182459
  memberId: member.id,
182460
+ dialogueGroups,
181564
182461
  ...target.receiverClassId && member.modifier !== "static" ? { receiverClassId: target.receiverClassId } : {}
181565
182462
  });
181566
182463
  const diagnostics = await validateCliNeoScript(
@@ -181622,11 +182519,11 @@ async function runLocalTargetCommand(manifest, target, command, options) {
181622
182519
  options.json ? JSON.stringify({ ...report, ...functionMetadata }, null, 2) : "Compiles cleanly."
181623
182520
  );
181624
182521
  }
181625
- function collectLocalCheckAll(manifest, options) {
182522
+ function collectLocalCheckAll(manifest, options, dialogueGroups) {
181626
182523
  const membersById = new Map(
181627
182524
  manifest.members.filter(isLocalScriptMember).map((member) => [member.id, member])
181628
182525
  );
181629
- const analyses = analyzeManifestScripts(manifest);
182526
+ const analyses = analyzeManifestScripts(manifest, { dialogueGroups });
181630
182527
  const results = analyses.map((analysis) => {
181631
182528
  const member = membersById.get(analysis.memberId);
181632
182529
  if (member === void 0) {
@@ -181664,7 +182561,11 @@ function localScriptUri(path) {
181664
182561
  return `neo-script:///${normalizeScriptPath(path).split("/").map((part) => encodeURIComponent(part)).join("/")}`;
181665
182562
  }
181666
182563
  function runCheckAll(document, manifest, options) {
181667
- const local = collectLocalCheckAll(manifest, options);
182564
+ const local = collectLocalCheckAll(
182565
+ manifest,
182566
+ options,
182567
+ cliDialogueGroupSources(document)
182568
+ );
181668
182569
  let failures = local.failures;
181669
182570
  let checked = local.checked;
181670
182571
  const results = [...local.results];
@@ -181757,7 +182658,7 @@ var init_script = __esm({
181757
182658
  init_save_overlay_resolution();
181758
182659
  init_members();
181759
182660
  init_neoscript();
181760
- init_dialogue_types();
182661
+ init_dialogue_types2();
181761
182662
  init_logic_types();
181762
182663
  init_dialogue_logic_compile_pure();
181763
182664
  init_project_migration_runner();
@@ -181965,6 +182866,7 @@ function sharedEvaluatorBase(rawDocument) {
181965
182866
  variants: document.variants,
181966
182867
  variantFolders: document.variantFolders,
181967
182868
  projectFiles: document.projectFiles,
182869
+ dialogueGroups: document.dialogueGroups,
181968
182870
  textureTemplates: document.textureTemplates,
181969
182871
  localizationConfig: document.localizationConfig,
181970
182872
  localizedTexts: document.localizedTexts,
@@ -185093,6 +185995,7 @@ async function runPendingMigrations(workspace, fetched, migrations, onlyRef) {
185093
185995
  () => compileNSVoidBody(migrationCode, {
185094
185996
  project: document.project,
185095
185997
  projectFiles: document.projectFiles,
185998
+ dialogueGroups: document.dialogueGroups,
185096
185999
  members: document.members,
185097
186000
  classes: document.classes,
185098
186001
  constructors: document.constructors,
@@ -185137,6 +186040,7 @@ async function runPendingMigrations(workspace, fetched, migrations, onlyRef) {
185137
186040
  classes: document.classes,
185138
186041
  enums: document.enums,
185139
186042
  projectFiles: document.projectFiles,
186043
+ dialogueGroups: document.dialogueGroups,
185140
186044
  localizationConfig: document.localizationConfig,
185141
186045
  localizedTexts: document.localizedTexts,
185142
186046
  ...runtime
@@ -186913,7 +187817,7 @@ var init_dialogue_lookup_candidates = __esm({
186913
187817
  var init_dialogue_record_split = __esm({
186914
187818
  "../src/models/dialogue/dialogue-record-split.ts"() {
186915
187819
  "use strict";
186916
- init_dialogue_types();
187820
+ init_dialogue_types2();
186917
187821
  }
186918
187822
  });
186919
187823
 
@@ -186923,7 +187827,7 @@ var init_dialogue_localized_text_links = __esm({
186923
187827
  "use strict";
186924
187828
  init_localized_text_create_envelope();
186925
187829
  init_localization_types();
186926
- init_dialogue_types();
187830
+ init_dialogue_types2();
186927
187831
  }
186928
187832
  });
186929
187833
 
@@ -186958,7 +187862,7 @@ var init_dialogue_triggering = __esm({
186958
187862
  var init_dialogue = __esm({
186959
187863
  "../src/models/dialogue/index.ts"() {
186960
187864
  "use strict";
186961
- init_dialogue_types();
187865
+ init_dialogue_types2();
186962
187866
  init_dialogue_source_identifiers();
186963
187867
  init_dialogue_source_names();
186964
187868
  init_dialogue_lookup_candidates();
@@ -188923,6 +189827,7 @@ function buildWorld(document, raw) {
188923
189827
  variants: document.variants,
188924
189828
  variantFolders: document.variantFolders,
188925
189829
  projectFiles: document.projectFiles,
189830
+ dialogueGroups: document.dialogueGroups,
188926
189831
  localizationConfig: document.localizationConfig,
188927
189832
  localizedTexts: document.localizedTexts,
188928
189833
  ...runtime
@@ -190519,7 +191424,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
190519
191424
  async function main() {
190520
191425
  const args = parseArgs(process.argv.slice(2));
190521
191426
  if (args.command === "--version") {
190522
- console.log("0.72.4");
191427
+ console.log("0.73.0");
190523
191428
  return;
190524
191429
  }
190525
191430
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {