@neocompose/cli 0.72.2 → 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
  });
@@ -28917,12 +29225,18 @@ function identPathSegments(expression) {
28917
29225
  if (receiver === null) return null;
28918
29226
  return [...receiver, expression.name];
28919
29227
  }
28920
- function receiverNarrowings(path, rootEntry, scope) {
29228
+ function unaffectedNarrowings(path, rootEntry, scope) {
28921
29229
  const facts = [];
28922
- for (let dot = path.indexOf("."); dot !== -1; dot = path.indexOf(".", dot + 1)) {
28923
- const prefix = path.slice(0, dot);
28924
- const type = scope.lookupNarrowedType(prefix, rootEntry);
28925
- if (type !== null) facts.push([prefix, type]);
29230
+ const prefix = `${path}.`;
29231
+ const dot = path.lastIndexOf(".");
29232
+ if (dot === -1) return facts;
29233
+ const member = path.slice(dot);
29234
+ for (const [candidate, narrowed] of scope.effectiveNarrowedPaths()) {
29235
+ if (narrowed.rootEntry !== rootEntry) continue;
29236
+ if (candidate === path || candidate.startsWith(prefix)) continue;
29237
+ if (candidate.endsWith(member) || candidate.includes(`${member}.`))
29238
+ continue;
29239
+ facts.push([candidate, narrowed.type]);
28926
29240
  }
28927
29241
  return facts;
28928
29242
  }
@@ -29246,22 +29560,22 @@ function localsWithBindings(locals, expression, whenTrue) {
29246
29560
  ...facts.flatMap((fact) => fact.bindingName ? [fact.bindingName] : [])
29247
29561
  ]);
29248
29562
  }
29249
- function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(), inheritedLocals = /* @__PURE__ */ new Set(), flowCache = /* @__PURE__ */ new WeakMap()) {
29563
+ function collectAssignedPaths(statements, roots = /* @__PURE__ */ new Set(), inheritedLocals = /* @__PURE__ */ new Set(), flowCache = /* @__PURE__ */ new WeakMap()) {
29250
29564
  const locals = new Set(inheritedLocals);
29251
29565
  for (const statement of statements) {
29252
29566
  if (statement.kind === "assign") {
29253
29567
  const assignedPath = canonicalPath(statement.target);
29254
29568
  if (assignedPath && !locals.has(pathRoot(assignedPath))) {
29255
- roots.add(pathRoot(assignedPath));
29569
+ roots.add(assignedPath);
29256
29570
  }
29257
- collectAssignedPathRootsInExpression(
29571
+ collectAssignedPathsInExpression(
29258
29572
  statement.target,
29259
29573
  roots,
29260
29574
  locals,
29261
29575
  flowCache
29262
29576
  );
29263
29577
  if (statement.value)
29264
- collectAssignedPathRootsInExpression(
29578
+ collectAssignedPathsInExpression(
29265
29579
  statement.value,
29266
29580
  roots,
29267
29581
  locals,
@@ -29270,7 +29584,7 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29270
29584
  continue;
29271
29585
  }
29272
29586
  if (statement.kind === "varDecl") {
29273
- collectAssignedPathRootsInExpression(
29587
+ collectAssignedPathsInExpression(
29274
29588
  statement.init,
29275
29589
  roots,
29276
29590
  locals,
@@ -29284,7 +29598,7 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29284
29598
  const falseFacts = [];
29285
29599
  const fallthroughFacts = [];
29286
29600
  for (const branch of statement.branches) {
29287
- collectAssignedPathRootsInExpression(
29601
+ collectAssignedPathsInExpression(
29288
29602
  branch.cond,
29289
29603
  roots,
29290
29604
  falseLocals,
@@ -29294,7 +29608,7 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29294
29608
  ...falseFacts,
29295
29609
  ...factsWhenTrue(branch.cond, canonicalPath)
29296
29610
  ];
29297
- collectAssignedPathRoots(
29611
+ collectAssignedPaths(
29298
29612
  branch.body,
29299
29613
  roots,
29300
29614
  localsWithBindings(falseLocals, branch.cond, true),
@@ -29306,12 +29620,7 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29306
29620
  falseLocals = localsWithBindings(falseLocals, branch.cond, false);
29307
29621
  }
29308
29622
  if (statement.elseBody) {
29309
- collectAssignedPathRoots(
29310
- statement.elseBody,
29311
- roots,
29312
- falseLocals,
29313
- flowCache
29314
- );
29623
+ collectAssignedPaths(statement.elseBody, roots, falseLocals, flowCache);
29315
29624
  if (statementFlow(statement.elseBody, flowCache).has("fallthrough"))
29316
29625
  fallthroughFacts.push(falseFacts);
29317
29626
  } else {
@@ -29323,18 +29632,18 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29323
29632
  continue;
29324
29633
  }
29325
29634
  if (statement.kind === "try") {
29326
- collectAssignedPathRoots(statement.body, roots, locals, flowCache);
29635
+ collectAssignedPaths(statement.body, roots, locals, flowCache);
29327
29636
  for (const clause of statement.catches) {
29328
29637
  const catchLocals = /* @__PURE__ */ new Set([...locals, clause.name]);
29329
29638
  if (clause.filter) {
29330
- collectAssignedPathRootsInExpression(
29639
+ collectAssignedPathsInExpression(
29331
29640
  clause.filter,
29332
29641
  roots,
29333
29642
  catchLocals,
29334
29643
  flowCache
29335
29644
  );
29336
29645
  }
29337
- collectAssignedPathRoots(
29646
+ collectAssignedPaths(
29338
29647
  clause.body,
29339
29648
  roots,
29340
29649
  clause.filter ? localsWithBindings(catchLocals, clause.filter, true) : catchLocals,
@@ -29344,13 +29653,13 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29344
29653
  continue;
29345
29654
  }
29346
29655
  if (statement.kind === "while" || statement.kind === "doWhile") {
29347
- collectAssignedPathRootsInExpression(
29656
+ collectAssignedPathsInExpression(
29348
29657
  statement.condition,
29349
29658
  roots,
29350
29659
  locals,
29351
29660
  flowCache
29352
29661
  );
29353
- collectAssignedPathRoots(
29662
+ collectAssignedPaths(
29354
29663
  statement.body,
29355
29664
  roots,
29356
29665
  statement.kind === "while" ? localsWithBindings(locals, statement.condition, true) : locals,
@@ -29359,14 +29668,14 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29359
29668
  continue;
29360
29669
  }
29361
29670
  if (statement.kind === "for") {
29362
- collectAssignedPathRootsInExpression(
29671
+ collectAssignedPathsInExpression(
29363
29672
  statement.initializer.init,
29364
29673
  roots,
29365
29674
  locals,
29366
29675
  flowCache
29367
29676
  );
29368
29677
  const loopLocals = /* @__PURE__ */ new Set([...locals, statement.initializer.name]);
29369
- collectAssignedPathRootsInExpression(
29678
+ collectAssignedPathsInExpression(
29370
29679
  statement.condition,
29371
29680
  roots,
29372
29681
  loopLocals,
@@ -29377,22 +29686,17 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29377
29686
  statement.condition,
29378
29687
  true
29379
29688
  );
29380
- collectAssignedPathRoots(
29689
+ collectAssignedPaths(
29381
29690
  [statement.iterator],
29382
29691
  roots,
29383
29692
  iterationLocals,
29384
29693
  flowCache
29385
29694
  );
29386
- collectAssignedPathRoots(
29387
- statement.body,
29388
- roots,
29389
- iterationLocals,
29390
- flowCache
29391
- );
29695
+ collectAssignedPaths(statement.body, roots, iterationLocals, flowCache);
29392
29696
  continue;
29393
29697
  }
29394
29698
  if (statement.kind === "forEach") {
29395
- collectAssignedPathRootsInExpression(
29699
+ collectAssignedPathsInExpression(
29396
29700
  statement.collection,
29397
29701
  roots,
29398
29702
  locals,
@@ -29400,11 +29704,11 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29400
29704
  );
29401
29705
  const loopLocals = /* @__PURE__ */ new Set([...locals, statement.name]);
29402
29706
  if (statement.key) loopLocals.add(statement.key.name);
29403
- collectAssignedPathRoots(statement.body, roots, loopLocals, flowCache);
29707
+ collectAssignedPaths(statement.body, roots, loopLocals, flowCache);
29404
29708
  continue;
29405
29709
  }
29406
29710
  if (statement.kind === "switch") {
29407
- collectAssignedPathRootsInExpression(
29711
+ collectAssignedPathsInExpression(
29408
29712
  statement.selector,
29409
29713
  roots,
29410
29714
  locals,
@@ -29413,7 +29717,7 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29413
29717
  for (const section of statement.sections) {
29414
29718
  for (const label of section.labels) {
29415
29719
  if (label.kind === "case") {
29416
- collectAssignedPathRootsInExpression(
29720
+ collectAssignedPathsInExpression(
29417
29721
  label.expression,
29418
29722
  roots,
29419
29723
  locals,
@@ -29421,13 +29725,13 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29421
29725
  );
29422
29726
  }
29423
29727
  }
29424
- collectAssignedPathRoots(section.body, roots, locals, flowCache);
29728
+ collectAssignedPaths(section.body, roots, locals, flowCache);
29425
29729
  }
29426
29730
  continue;
29427
29731
  }
29428
29732
  if (statement.kind === "return" || statement.kind === "throw") {
29429
29733
  if (statement.expr)
29430
- collectAssignedPathRootsInExpression(
29734
+ collectAssignedPathsInExpression(
29431
29735
  statement.expr,
29432
29736
  roots,
29433
29737
  locals,
@@ -29436,7 +29740,7 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29436
29740
  continue;
29437
29741
  }
29438
29742
  if (statement.kind === "exprStmt") {
29439
- collectAssignedPathRootsInExpression(
29743
+ collectAssignedPathsInExpression(
29440
29744
  statement.expr,
29441
29745
  roots,
29442
29746
  locals,
@@ -29446,43 +29750,28 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
29446
29750
  }
29447
29751
  return roots;
29448
29752
  }
29449
- function collectAssignedPathRootsInExpression(expression, roots, locals, flowCache) {
29753
+ function collectAssignedPathsInExpression(expression, roots, locals, flowCache) {
29450
29754
  switch (expression.kind) {
29451
29755
  case "litInterp":
29452
29756
  for (const part of expression.parts) {
29453
29757
  if (part.kind === "expr") {
29454
- collectAssignedPathRootsInExpression(
29455
- part.expr,
29456
- roots,
29457
- locals,
29458
- flowCache
29459
- );
29758
+ collectAssignedPathsInExpression(part.expr, roots, locals, flowCache);
29460
29759
  }
29461
29760
  }
29462
29761
  return;
29463
29762
  case "litList":
29464
29763
  for (const element of expression.elements) {
29465
- collectAssignedPathRootsInExpression(element, roots, locals, flowCache);
29764
+ collectAssignedPathsInExpression(element, roots, locals, flowCache);
29466
29765
  }
29467
29766
  return;
29468
29767
  case "litDict":
29469
29768
  for (const entry of expression.entries) {
29470
- collectAssignedPathRootsInExpression(
29471
- entry.key,
29472
- roots,
29473
- locals,
29474
- flowCache
29475
- );
29476
- collectAssignedPathRootsInExpression(
29477
- entry.value,
29478
- roots,
29479
- locals,
29480
- flowCache
29481
- );
29769
+ collectAssignedPathsInExpression(entry.key, roots, locals, flowCache);
29770
+ collectAssignedPathsInExpression(entry.value, roots, locals, flowCache);
29482
29771
  }
29483
29772
  return;
29484
29773
  case "member":
29485
- collectAssignedPathRootsInExpression(
29774
+ collectAssignedPathsInExpression(
29486
29775
  expression.receiver,
29487
29776
  roots,
29488
29777
  locals,
@@ -29490,13 +29779,13 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
29490
29779
  );
29491
29780
  return;
29492
29781
  case "index":
29493
- collectAssignedPathRootsInExpression(
29782
+ collectAssignedPathsInExpression(
29494
29783
  expression.receiver,
29495
29784
  roots,
29496
29785
  locals,
29497
29786
  flowCache
29498
29787
  );
29499
- collectAssignedPathRootsInExpression(
29788
+ collectAssignedPathsInExpression(
29500
29789
  expression.index,
29501
29790
  roots,
29502
29791
  locals,
@@ -29504,32 +29793,22 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
29504
29793
  );
29505
29794
  return;
29506
29795
  case "call":
29507
- collectAssignedPathRootsInExpression(
29796
+ collectAssignedPathsInExpression(
29508
29797
  expression.callee,
29509
29798
  roots,
29510
29799
  locals,
29511
29800
  flowCache
29512
29801
  );
29513
29802
  for (const argument2 of expression.args) {
29514
- collectAssignedPathRootsInExpression(
29515
- argument2,
29516
- roots,
29517
- locals,
29518
- flowCache
29519
- );
29803
+ collectAssignedPathsInExpression(argument2, roots, locals, flowCache);
29520
29804
  }
29521
29805
  return;
29522
29806
  case "new":
29523
29807
  for (const argument2 of expression.args) {
29524
- collectAssignedPathRootsInExpression(
29525
- argument2,
29526
- roots,
29527
- locals,
29528
- flowCache
29529
- );
29808
+ collectAssignedPathsInExpression(argument2, roots, locals, flowCache);
29530
29809
  }
29531
29810
  for (const initializer of expression.initializer ?? []) {
29532
- collectAssignedPathRootsInExpression(
29811
+ collectAssignedPathsInExpression(
29533
29812
  initializer.value,
29534
29813
  roots,
29535
29814
  locals,
@@ -29540,15 +29819,10 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
29540
29819
  case "annotated":
29541
29820
  for (const annotation2 of expression.annotations) {
29542
29821
  for (const argument2 of annotation2.args) {
29543
- collectAssignedPathRootsInExpression(
29544
- argument2,
29545
- roots,
29546
- locals,
29547
- flowCache
29548
- );
29822
+ collectAssignedPathsInExpression(argument2, roots, locals, flowCache);
29549
29823
  }
29550
29824
  }
29551
- collectAssignedPathRootsInExpression(
29825
+ collectAssignedPathsInExpression(
29552
29826
  expression.expression,
29553
29827
  roots,
29554
29828
  locals,
@@ -29557,13 +29831,13 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
29557
29831
  return;
29558
29832
  case "binary":
29559
29833
  case "coalesce":
29560
- collectAssignedPathRootsInExpression(
29834
+ collectAssignedPathsInExpression(
29561
29835
  expression.left,
29562
29836
  roots,
29563
29837
  locals,
29564
29838
  flowCache
29565
29839
  );
29566
- collectAssignedPathRootsInExpression(
29840
+ collectAssignedPathsInExpression(
29567
29841
  expression.right,
29568
29842
  roots,
29569
29843
  locals,
@@ -29571,19 +29845,19 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
29571
29845
  );
29572
29846
  return;
29573
29847
  case "conditional":
29574
- collectAssignedPathRootsInExpression(
29848
+ collectAssignedPathsInExpression(
29575
29849
  expression.condition,
29576
29850
  roots,
29577
29851
  locals,
29578
29852
  flowCache
29579
29853
  );
29580
- collectAssignedPathRootsInExpression(
29854
+ collectAssignedPathsInExpression(
29581
29855
  expression.whenTrue,
29582
29856
  roots,
29583
29857
  locals,
29584
29858
  flowCache
29585
29859
  );
29586
- collectAssignedPathRootsInExpression(
29860
+ collectAssignedPathsInExpression(
29587
29861
  expression.whenFalse,
29588
29862
  roots,
29589
29863
  locals,
@@ -29592,7 +29866,7 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
29592
29866
  return;
29593
29867
  case "unary":
29594
29868
  case "force":
29595
- collectAssignedPathRootsInExpression(
29869
+ collectAssignedPathsInExpression(
29596
29870
  expression.operand,
29597
29871
  roots,
29598
29872
  locals,
@@ -29600,7 +29874,7 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
29600
29874
  );
29601
29875
  return;
29602
29876
  case "is":
29603
- collectAssignedPathRootsInExpression(
29877
+ collectAssignedPathsInExpression(
29604
29878
  expression.operand,
29605
29879
  roots,
29606
29880
  locals,
@@ -29608,7 +29882,7 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
29608
29882
  );
29609
29883
  return;
29610
29884
  case "lambda":
29611
- collectAssignedPathRoots(
29885
+ collectAssignedPaths(
29612
29886
  expression.body,
29613
29887
  roots,
29614
29888
  /* @__PURE__ */ new Set([
@@ -29674,6 +29948,43 @@ function enumLiteralKeyOptionId(pointer) {
29674
29948
  }
29675
29949
  return pointer.value.value[0];
29676
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
+ }
29677
29988
  function intrinsic(kind, info, type) {
29678
29989
  return {
29679
29990
  pointer: {
@@ -29880,7 +30191,7 @@ function primitiveValueKind(name) {
29880
30191
  return 11 /* Sprite */;
29881
30192
  case "AudioClipInfo":
29882
30193
  return 12 /* Audio */;
29883
- case "DialogueRef":
30194
+ case "NeoDialogueReference":
29884
30195
  return 18 /* DialogueLookup */;
29885
30196
  case "Vector2":
29886
30197
  return 14 /* Vector2 */;
@@ -29913,7 +30224,7 @@ function valueKindPrimitive(kind) {
29913
30224
  case 12 /* Audio */:
29914
30225
  return "AudioClipInfo";
29915
30226
  case 18 /* DialogueLookup */:
29916
- return "DialogueRef";
30227
+ return "NeoDialogueReference";
29917
30228
  case 14 /* Vector2 */:
29918
30229
  return "Vector2";
29919
30230
  case 15 /* Vector2Int */:
@@ -30093,7 +30404,7 @@ function resolvePrimitiveMember(type, name) {
30093
30404
  if (name === "length")
30094
30405
  return { type: { kind: "primitive", name: "float" } };
30095
30406
  }
30096
- if (type.name === "DialogueRef" && name === "id")
30407
+ if (type.name === "NeoDialogueReference" && name === "id")
30097
30408
  return { type: { kind: "primitive", name: "string" } };
30098
30409
  return null;
30099
30410
  }
@@ -30192,7 +30503,7 @@ function namedPrimitive(name) {
30192
30503
  case "decimal":
30193
30504
  case "SpriteInfo":
30194
30505
  case "AudioClipInfo":
30195
- case "DialogueRef":
30506
+ case "NeoDialogueReference":
30196
30507
  case "Vector2":
30197
30508
  case "Vector2Int":
30198
30509
  case "Vector3":
@@ -30427,7 +30738,10 @@ function resolveNeoScriptType(type, context, project) {
30427
30738
  }
30428
30739
  const named = project.typeByName.get(type.name);
30429
30740
  if (!named)
30430
- 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
+ );
30431
30745
  resolved = {
30432
30746
  kind: "named",
30433
30747
  typeId: named.id,
@@ -30493,6 +30807,7 @@ var init_strict_resolver = __esm({
30493
30807
  init_strict_compile_error();
30494
30808
  init_strict_ir();
30495
30809
  init_test_prelude();
30810
+ init_dialogue_types();
30496
30811
  init_tile_conversion();
30497
30812
  CONSTRUCTING_FUNCTION_KINDS = /* @__PURE__ */ new Set(
30498
30813
  [
@@ -30602,14 +30917,17 @@ var init_strict_resolver = __esm({
30602
30917
  return this.invalidatedRoots;
30603
30918
  }
30604
30919
  effectiveNarrowedPaths() {
30605
- const effective = this.parent ? new Map(this.parent.effectiveNarrowedPaths()) : /* @__PURE__ */ new Map();
30606
- for (const invalidated of this.invalidatedRoots) {
30607
- for (const [path, narrowed] of effective) {
30608
- if (narrowed.rootEntry === invalidated) effective.delete(path);
30920
+ const effective = new Map(this.narrowedPaths);
30921
+ const invalidated = new Set(this.invalidatedRoots);
30922
+ for (const root of this.hiddenNarrowingRoots) invalidated.add(root);
30923
+ for (let current = this.parent; current; current = current.parent) {
30924
+ for (const [path, narrowed] of current.narrowedPaths) {
30925
+ if (!effective.has(path) && !invalidated.has(narrowed.rootEntry)) {
30926
+ effective.set(path, narrowed);
30927
+ }
30609
30928
  }
30610
- }
30611
- for (const [path, narrowed] of this.narrowedPaths) {
30612
- effective.set(path, narrowed);
30929
+ for (const root of current.invalidatedRoots) invalidated.add(root);
30930
+ for (const root of current.hiddenNarrowingRoots) invalidated.add(root);
30613
30931
  }
30614
30932
  return effective;
30615
30933
  }
@@ -30635,6 +30953,9 @@ var init_strict_resolver = __esm({
30635
30953
  hideInheritedNarrowing(rootEntry) {
30636
30954
  this.hiddenNarrowingRoots.add(rootEntry);
30637
30955
  this.updatePatternType(rootEntry, rootEntry.type);
30956
+ for (const [path, narrowed] of this.narrowedPaths) {
30957
+ if (narrowed.rootEntry === rootEntry) this.narrowedPaths.delete(path);
30958
+ }
30638
30959
  }
30639
30960
  invalidate(rootEntry) {
30640
30961
  this.invalidatedRoots.add(rootEntry);
@@ -31192,24 +31513,26 @@ var init_strict_resolver = __esm({
31192
31513
  const branchExitNarrowings = [];
31193
31514
  const branchExitOwnershipScopes = [];
31194
31515
  const branches = statement.branches.map((branch) => {
31516
+ const conditionScope = new Scope(scope);
31517
+ this.applyFactsToScope(conditionScope, cumulativeFalseFacts);
31195
31518
  const condition = this.toBool(
31196
- this.resolveExpression(branch.cond, scope),
31519
+ this.resolveExpression(branch.cond, conditionScope),
31197
31520
  branch.cond.pos
31198
31521
  );
31199
31522
  const child2 = new Scope(scope);
31200
31523
  const branchFacts = [
31201
31524
  ...cumulativeFalseFacts,
31202
- ...this.conditionFacts(branch.cond, scope, true)
31525
+ ...this.conditionFacts(branch.cond, conditionScope, true)
31203
31526
  ];
31204
31527
  this.applyFactsToScope(child2, branchFacts);
31205
31528
  const instructions = this.resolveStatements(branch.body, child2);
31206
31529
  if (!instructionsTerminate(instructions)) {
31207
31530
  branchExitFacts.push(branchFacts);
31208
- branchExitNarrowings.push(new Map(child2.narrowedPaths));
31531
+ branchExitNarrowings.push(child2.effectiveNarrowedPaths());
31209
31532
  branchExitOwnershipScopes.push(child2);
31210
31533
  }
31211
31534
  cumulativeFalseFacts.push(
31212
- ...this.conditionFacts(branch.cond, scope, false)
31535
+ ...this.conditionFacts(branch.cond, conditionScope, false)
31213
31536
  );
31214
31537
  return {
31215
31538
  expression: pointerToBooleanExpression(condition.pointer),
@@ -31223,14 +31546,14 @@ var init_strict_resolver = __esm({
31223
31546
  otherwise = this.resolveStatements(statement.elseBody, elseScope);
31224
31547
  if (!instructionsTerminate(otherwise)) {
31225
31548
  branchExitFacts.push([...cumulativeFalseFacts]);
31226
- branchExitNarrowings.push(new Map(elseScope.narrowedPaths));
31549
+ branchExitNarrowings.push(elseScope.effectiveNarrowedPaths());
31227
31550
  branchExitOwnershipScopes.push(elseScope);
31228
31551
  }
31229
31552
  } else {
31230
31553
  const noBranchScope = new Scope(scope);
31231
31554
  this.applyFactsToScope(noBranchScope, cumulativeFalseFacts);
31232
31555
  branchExitFacts.push([...cumulativeFalseFacts]);
31233
- branchExitNarrowings.push(new Map(noBranchScope.narrowedPaths));
31556
+ branchExitNarrowings.push(noBranchScope.effectiveNarrowedPaths());
31234
31557
  branchExitOwnershipScopes.push(noBranchScope);
31235
31558
  }
31236
31559
  mergeBranchInvalidations(scope, branchExitOwnershipScopes);
@@ -31464,12 +31787,15 @@ var init_strict_resolver = __esm({
31464
31787
  statement.body,
31465
31788
  conditionLocals
31466
31789
  );
31467
- this.invalidateLoopEntryNarrowingsAssignedBy(
31468
- loopEntryScope,
31469
- loopScope,
31470
- [statement.iterator],
31471
- conditionLocals
31472
- );
31790
+ const bodyFlow = statementFlow(statement.body, /* @__PURE__ */ new WeakMap());
31791
+ if (bodyFlow.has("fallthrough") || bodyFlow.has("continue")) {
31792
+ this.invalidateLoopEntryNarrowingsAssignedBy(
31793
+ loopEntryScope,
31794
+ loopScope,
31795
+ [statement.iterator],
31796
+ conditionLocals
31797
+ );
31798
+ }
31473
31799
  const condition = this.toBool(
31474
31800
  this.resolveExpression(statement.condition, loopEntryScope),
31475
31801
  statement.condition.pos
@@ -31906,23 +32232,23 @@ var init_strict_resolver = __esm({
31906
32232
  resolveDebugStatement(expr, scope) {
31907
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"))
31908
32234
  return null;
31909
- const method2 = expr.callee.name;
32235
+ const method3 = expr.callee.name;
31910
32236
  const severities = {
31911
32237
  Log: "log",
31912
32238
  LogWarning: "warning",
31913
32239
  LogError: "error",
31914
32240
  Assert: "assert"
31915
32241
  };
31916
- if (!Object.hasOwn(severities, method2))
31917
- throw new CompileError(`Unknown Debug method '${method2}'.`, expr.pos);
31918
- const severity = severities[method2];
31919
- 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;
31920
32246
  if (expr.args.length !== expected)
31921
32247
  throw new CompileError(
31922
- `Debug.${method2} expects ${expected} argument(s).`,
32248
+ `Debug.${method3} expects ${expected} argument(s).`,
31923
32249
  expr.pos
31924
32250
  );
31925
- 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;
31926
32252
  if (condition && (!isPrimitive(condition.type, "bool") || isNullable(condition.type)))
31927
32253
  throw new CompileError(
31928
32254
  "Debug.Assert requires a non-null bool condition.",
@@ -32336,13 +32662,13 @@ var init_strict_resolver = __esm({
32336
32662
  if (assignedPath) {
32337
32663
  const rootEntry = scope.lookup(pathRoot(assignedPath));
32338
32664
  if (rootEntry) {
32339
- const receiverFacts = receiverNarrowings(
32665
+ const retainedFacts = unaffectedNarrowings(
32340
32666
  assignedPath,
32341
32667
  rootEntry,
32342
32668
  scope
32343
32669
  );
32344
32670
  scope.invalidate(rootEntry);
32345
- for (const [path, type] of receiverFacts) {
32671
+ for (const [path, type] of retainedFacts) {
32346
32672
  scope.narrow(path, rootEntry, type);
32347
32673
  }
32348
32674
  if (statement.op === "=" && !isNullable(value.type)) {
@@ -32559,13 +32885,13 @@ var init_strict_resolver = __esm({
32559
32885
  if (assignedPath) {
32560
32886
  const rootEntry = scope.lookup(pathRoot(assignedPath));
32561
32887
  if (rootEntry) {
32562
- const receiverFacts = receiverNarrowings(
32888
+ const retainedFacts = unaffectedNarrowings(
32563
32889
  assignedPath,
32564
32890
  rootEntry,
32565
32891
  scope
32566
32892
  );
32567
32893
  scope.invalidate(rootEntry);
32568
- for (const [path, type] of receiverFacts) {
32894
+ for (const [path, type] of retainedFacts) {
32569
32895
  scope.narrow(path, rootEntry, type);
32570
32896
  }
32571
32897
  }
@@ -32812,6 +33138,17 @@ var init_strict_resolver = __esm({
32812
33138
  }
32813
33139
  }
32814
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) {
32815
33152
  let result = this.resolveExpressionCore(expression, scope, expected);
32816
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 */) {
32817
33154
  result = {
@@ -33180,18 +33517,19 @@ var init_strict_resolver = __esm({
33180
33517
  case "coalesce": {
33181
33518
  const left = this.resolveExpression(expression.left, scope);
33182
33519
  const leftOptional = { ...left.type, nullable: true };
33520
+ const nullLeft = isNull(left.type);
33183
33521
  const right = this.resolveExpression(
33184
33522
  expression.right,
33185
33523
  scope,
33186
- leftOptional
33524
+ nullLeft ? expected : leftOptional
33187
33525
  );
33188
- if (!isNeoScriptTypeAssignable(right.type, leftOptional, this.project)) {
33526
+ if (!nullLeft && !isNeoScriptTypeAssignable(right.type, leftOptional, this.project)) {
33189
33527
  throw new CompileError(
33190
33528
  `\`??\` right operand ${this.describe(right.type)} is not assignable to ${this.describe(leftOptional)}`,
33191
33529
  expression.pos
33192
33530
  );
33193
33531
  }
33194
- const resultType = {
33532
+ const resultType = nullLeft ? right.type : {
33195
33533
  ...left.type,
33196
33534
  nullable: isNullable(left.type) && isNullable(right.type)
33197
33535
  };
@@ -33892,20 +34230,25 @@ var init_strict_resolver = __esm({
33892
34230
  return whenTrue ? factsWhenTrue(expression, pathOf) : factsWhenFalse(expression, pathOf);
33893
34231
  }
33894
34232
  /**
33895
- * A loop body is resolved once but can execute repeatedly. Any narrowing rooted
33896
- * in an outer binding that the body or iterator may write is therefore stale
33897
- * at a later iteration entry. Invalidate those roots before resolving the
33898
- * shared iteration so only the loop's own condition can narrow them again.
34233
+ * A loop body is resolved once but can execute repeatedly. Hide facts about
34234
+ * paths it may replace before resolving the shared iteration; unrelated facts
34235
+ * still hold, and the loop condition can narrow the written paths again.
33899
34236
  */
33900
34237
  invalidateLoopEntryNarrowingsAssignedBy(loopEntryScope, outerScope, statements, locals = /* @__PURE__ */ new Set()) {
33901
- for (const rootName of collectAssignedPathRoots(
34238
+ for (const assignedPath of collectAssignedPaths(
33902
34239
  statements,
33903
34240
  /* @__PURE__ */ new Set(),
33904
34241
  locals
33905
34242
  )) {
33906
- const path = this.narrowingPath(rootName, outerScope);
34243
+ const path = this.narrowingPath(assignedPath, outerScope);
33907
34244
  const outerEntry = path === null ? null : outerScope.lookup(pathRoot(path));
33908
- if (outerEntry) loopEntryScope.hideInheritedNarrowing(outerEntry);
34245
+ if (outerEntry && path !== null) {
34246
+ const retained = unaffectedNarrowings(path, outerEntry, loopEntryScope);
34247
+ loopEntryScope.hideInheritedNarrowing(outerEntry);
34248
+ for (const [retainedPath, type] of retained) {
34249
+ loopEntryScope.narrow(retainedPath, outerEntry, type);
34250
+ }
34251
+ }
33909
34252
  }
33910
34253
  }
33911
34254
  applyFactsToScope(targetScope, facts, mode = "all") {
@@ -34383,7 +34726,7 @@ var init_strict_resolver = __esm({
34383
34726
  return this.resolveStaticMemberValue(staticType, member, pos);
34384
34727
  }
34385
34728
  }
34386
- const resolvedReceiver = receiverValue ? receiverValue() : this.resolveExpression(receiverAst, scope);
34729
+ const resolvedReceiver = receiverValue ? receiverValue() : this.resolveReceiverExpression(receiverAst, scope);
34387
34730
  if (optional2 && !isNullable(resolvedReceiver.type)) {
34388
34731
  throw new CompileError(
34389
34732
  `\`?.\` requires an optional receiver; got ${this.describe(resolvedReceiver.type)}`,
@@ -34479,7 +34822,7 @@ var init_strict_resolver = __esm({
34479
34822
  }
34480
34823
  const primitiveMember = resolvePrimitiveMember(receiver.type, name);
34481
34824
  if (primitiveMember) {
34482
- if (isPrimitive(receiver.type, "DialogueRef")) {
34825
+ if (isPrimitive(receiver.type, "NeoDialogueReference")) {
34483
34826
  return {
34484
34827
  pointer: {
34485
34828
  type: "keyOf" /* KeyOf */,
@@ -34512,12 +34855,15 @@ var init_strict_resolver = __esm({
34512
34855
  pos
34513
34856
  );
34514
34857
  }
34515
- if (isPrimitive(receiver.type, "DialogueRef")) {
34858
+ if (isPrimitive(receiver.type, "NeoDialogueReference")) {
34516
34859
  throw new CompileError(
34517
34860
  `${this.describe(receiver.type)} has no member '${name}'`,
34518
34861
  pos
34519
34862
  );
34520
34863
  }
34864
+ if (receiver.dialogues !== void 0) {
34865
+ return this.resolveDialogueGroupRead(receiver, name, pos);
34866
+ }
34521
34867
  const memberReceiverType = neoScriptMemberLookupType(receiver.type);
34522
34868
  if (memberReceiverType.kind === "named") {
34523
34869
  const type = this.project.typeById.get(memberReceiverType.typeId);
@@ -34546,6 +34892,10 @@ var init_strict_resolver = __esm({
34546
34892
  if (this.userClassCode && type.id === this.rootTypeId && member.writability !== "user") {
34547
34893
  throw new CompileError("User code can only read `root.User`.", pos);
34548
34894
  }
34895
+ const dialogues = this.dialogueReceiverOf(member.type);
34896
+ if (dialogues !== void 0) {
34897
+ return { ...literal(member.type, null), dialogues, symbol: member };
34898
+ }
34549
34899
  if (member.static === true) {
34550
34900
  throw new CompileError(
34551
34901
  `Static member '${type.name}.${name}' must be accessed through the type name, not an instance.`,
@@ -34900,6 +35250,227 @@ var init_strict_resolver = __esm({
34900
35250
  );
34901
35251
  }
34902
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
+ }
34903
35474
  /**
34904
35475
  * P69 §2.7. A member read on the `Math` namespace: the two constants lower
34905
35476
  * to `float` literals, and nothing else on `Math` is readable as a value.
@@ -35105,7 +35676,9 @@ var init_strict_resolver = __esm({
35105
35676
  return () => {
35106
35677
  if (!result) {
35107
35678
  try {
35108
- result = { value: this.resolveExpression(callee.receiver, scope) };
35679
+ result = {
35680
+ value: this.resolveReceiverExpression(callee.receiver, scope)
35681
+ };
35109
35682
  } catch (error) {
35110
35683
  result = { error };
35111
35684
  }
@@ -35160,31 +35733,11 @@ var init_strict_resolver = __esm({
35160
35733
  if (vector3)
35161
35734
  return this.resolveVectorConstructor(vector3, argumentsList2, scope, pos);
35162
35735
  if (callee.name === "VisitCount" || callee.name === "HasVisited") {
35163
- if (isNeoScriptConstructionDocumentKind(this.context.kind)) {
35164
- throw new CompileError(
35165
- `${callee.name} reads runtime dialogue memory, which has no meaning in a ${this.context.kind} body.`,
35166
- pos
35167
- );
35168
- }
35169
- requireArgCount(callee.name, argumentsList2, 1, pos);
35170
- const pointer = this.resolveExpression(
35171
- requiredAt(argumentsList2, 0),
35736
+ return this.resolveDialogueMemoryRead(
35737
+ callee.name,
35738
+ argumentsList2,
35172
35739
  scope,
35173
- { kind: "primitive", name: "string" }
35174
- );
35175
- if (!isPrimitive(pointer.type, "string")) {
35176
- throw new CompileError(
35177
- `${callee.name} pointer must be a string; got ${this.describe(pointer.type)}`,
35178
- pos
35179
- );
35180
- }
35181
- return intrinsic(
35182
- callee.name === "VisitCount" ? "visitCount" /* VisitCount */ : "hasVisited" /* HasVisited */,
35183
- { pointer: pointer.pointer },
35184
- {
35185
- kind: "primitive",
35186
- name: callee.name === "VisitCount" ? "int" : "bool"
35187
- }
35740
+ pos
35188
35741
  );
35189
35742
  }
35190
35743
  const global = this.context.project.globals.find(
@@ -35289,12 +35842,37 @@ var init_strict_resolver = __esm({
35289
35842
  }
35290
35843
  const receiver = receiverValue();
35291
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
+ }
35292
35860
  if (optional2 && !isNullable(receiver.type)) {
35293
35861
  throw new CompileError(
35294
35862
  `\`?.\` requires an optional receiver; got ${this.describe(receiver.type)}`,
35295
35863
  pos
35296
35864
  );
35297
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
+ }
35298
35876
  if (callee.name === "Slice" && isPrimitive(receiver.type, "ImageRef")) {
35299
35877
  return this.resolveImageSlice(receiver, argumentsList2, scope, pos);
35300
35878
  }
@@ -37576,6 +38154,7 @@ var init_strict_resolver = __esm({
37576
38154
  }
37577
38155
  }
37578
38156
  const receiver = receiverValue();
38157
+ if (receiver.dialogues !== void 0) return null;
37579
38158
  const memberReceiverType = neoScriptMemberLookupType(receiver.type);
37580
38159
  if (memberReceiverType.kind !== "named") return null;
37581
38160
  const type = this.project.typeById.get(memberReceiverType.typeId);
@@ -42603,7 +43182,7 @@ function createEnvironment(documents, project) {
42603
43182
  if (declaration.kind === "class") {
42604
43183
  types.set(declaration.name, declaration);
42605
43184
  const dialogue = declaration.baseTypes.some(
42606
- (base) => base.name === "Dialogue"
43185
+ (base) => base.name === "NeoDialogue"
42607
43186
  );
42608
43187
  if (dialogue) {
42609
43188
  referenceTargets.set(declaration.name, {
@@ -43320,7 +43899,9 @@ function fieldsForAnnotation(name, context, environment) {
43320
43899
  }
43321
43900
  if (name === "primary") return context.kind === "flowBinding" ? [] : null;
43322
43901
  if (name === "incomplete") {
43323
- 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;
43324
43905
  }
43325
43906
  if (name === "visibility") {
43326
43907
  return context.kind === "class" ? [{ name: "visibility", type: "NeoClassVisibility" }] : null;
@@ -43364,7 +43945,7 @@ function settingsFields(context) {
43364
43945
  ];
43365
43946
  }
43366
43947
  if (context.kind === "class") {
43367
- if (context.declaration.baseTypes.some((type2) => type2.name === "Dialogue")) {
43948
+ if (context.declaration.baseTypes.some((type2) => type2.name === "NeoDialogue")) {
43368
43949
  return [
43369
43950
  { name: "name", type: "string" },
43370
43951
  { name: "description", type: "string" },
@@ -43399,7 +43980,7 @@ function settingsFields(context) {
43399
43980
  );
43400
43981
  }
43401
43982
  if (type.name === "Lookup") return lookupSettingsFields();
43402
- if (type.name === "Dialogue")
43983
+ if (type.name === "NeoDialogueReference")
43403
43984
  return settingsClassFields("NeoDialogueSettings");
43404
43985
  if (type.name === "NeoImage" || type.name === "NeoAudioClip" || type.name === "SpriteInfo" || type.name === "AudioClipInfo") {
43405
43986
  return settingsClassFields("NeoFileSettings").filter(
@@ -44074,7 +44655,7 @@ function validateExpression(expression, expected, scope, environment, uri, range
44074
44655
  if (expression.kind === "coalesce") {
44075
44656
  validateExpression(
44076
44657
  expression.left,
44077
- expected,
44658
+ expected ? { ...expected, nullable: true } : void 0,
44078
44659
  scope,
44079
44660
  environment,
44080
44661
  uri,
@@ -44085,7 +44666,7 @@ function validateExpression(expression, expected, scope, environment, uri, range
44085
44666
  const left = inferExpressionType(expression.left, scope, environment);
44086
44667
  validateExpression(
44087
44668
  expression.right,
44088
- left ?? expected,
44669
+ left && left.name !== "null" ? { ...left, nullable: true } : expected,
44089
44670
  scope,
44090
44671
  environment,
44091
44672
  uri,
@@ -44714,6 +45295,16 @@ function inferExpressionType(expression, scope, environment) {
44714
45295
  const operand = inferExpressionType(expression.operand, scope, environment);
44715
45296
  return operand ? { ...operand, nullable: false } : void 0;
44716
45297
  }
45298
+ if (expression.kind === "coalesce") {
45299
+ const left = inferExpressionType(expression.left, scope, environment);
45300
+ const right = inferExpressionType(expression.right, scope, environment);
45301
+ if (left?.name === "null") return right;
45302
+ if (!left || !right) return void 0;
45303
+ return {
45304
+ ...left,
45305
+ nullable: left.nullable === true && right.nullable === true
45306
+ };
45307
+ }
44717
45308
  if (expression.kind === "index") {
44718
45309
  const receiver = inferExpressionType(
44719
45310
  expression.receiver,
@@ -44822,7 +45413,8 @@ function subscriptKeyType(receiver) {
44822
45413
  if (receiver?.name === "List") return primitiveType("int");
44823
45414
  return void 0;
44824
45415
  }
44825
- 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;
44826
45418
  const typeArguments = expression.typeArguments ?? [];
44827
45419
  const names = expression.argumentNames ?? [];
44828
45420
  const idIndex = names.findIndex((name) => name === "id");
@@ -44914,7 +45506,7 @@ function validateReferenceExpression(expression, expected, environment, uri, ran
44914
45506
  );
44915
45507
  return;
44916
45508
  }
44917
- if (target.kind === "dialogue" && expected && expected.name !== "Dialogue") {
45509
+ if (target.kind === "dialogue" && expected && expected.name !== "NeoDialogue") {
44918
45510
  if (!referenceTypeAssignable(target.type, expected, environment)) {
44919
45511
  malformed(
44920
45512
  `Dialogue target ${path} is incompatible with expected target ${describeType(expected)}.`
@@ -44948,8 +45540,8 @@ function referenceTargetPath(expression) {
44948
45540
  return receiver === null ? null : `${receiver}.${expression.name}`;
44949
45541
  }
44950
45542
  function isDialogueReferenceType(type, environment) {
44951
- if (type.name === "Dialogue") return true;
44952
- 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());
44953
45545
  }
44954
45546
  function referenceTypeAssignable(actual, expected, environment) {
44955
45547
  if (actual.name === expected.name) {
@@ -45883,14 +46475,18 @@ function successfulBodyCache(project) {
45883
46475
  }
45884
46476
  function compileProjectSourceBodies(documents) {
45885
46477
  const graph = buildProjectGraph(documents);
45886
- const groupContexts = dialogueGroupContexts(documents, graph);
45887
- const project = {
45888
- ...graph.project,
45889
- types: [
45890
- ...graph.project.types,
45891
- ...[...groupContexts.values()].map((group) => group.contextType)
45892
- ]
45893
- };
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 };
45894
46490
  const projectIndex = createProjectIndex(project);
45895
46491
  const bodyCache = successfulBodyCache(project);
45896
46492
  const bodies = [];
@@ -46107,76 +46703,78 @@ function compileProjectSourceBodies(documents) {
46107
46703
  }
46108
46704
  return { project, bodies, contexts, diagnostics };
46109
46705
  }
46110
- function dialogueGroupContexts(documents, graph) {
46111
- const result = /* @__PURE__ */ new Map();
46112
- let index;
46113
- let membersByType;
46114
- const collectionMembersByType = () => membersByType ??= new Map(
46115
- graph.project.types.map((type) => [
46116
- type.name,
46117
- new Map(type.members.map((member) => [member.name, member]))
46118
- ])
46119
- );
46706
+ function sourceDialogueGroups2(documents, graph) {
46707
+ const declarations = [];
46708
+ const idsByName = /* @__PURE__ */ new Map();
46120
46709
  for (const [uri, document] of documents) {
46121
46710
  for (const declaration of document.declarations) {
46122
- if (declaration.kind !== "global" || !declaration.dialogueGroup) continue;
46123
- let thisType;
46124
- try {
46125
- const constructor2 = parseExpression(
46126
- declaration.dialogueGroup.constructor.text
46127
- );
46128
- if (constructor2.kind === "new") {
46129
- const kind = constructor2.args[constructor2.argumentNames?.indexOf("kind") ?? -1];
46130
- const collection = constructor2.args[constructor2.argumentNames?.indexOf("collection") ?? -1];
46131
- if (kind?.kind === "contextualEnum" && kind.name === "Lookup") {
46132
- let member;
46133
- if (collection?.kind === "member" && collection.receiver.kind === "ident") {
46134
- member = collectionMembersByType().get(collection.receiver.name)?.get(collection.name);
46135
- } else if (collection?.kind === "call" && collection.callee.kind === "ident" && collection.callee.name === "Reference") {
46136
- const id3 = collection.args[collection.argumentNames?.indexOf("id") ?? -1];
46137
- if (id3?.kind === "litString")
46138
- member = (index ??= createProjectIndex(
46139
- graph.project
46140
- )).symbolById.get(id3.value);
46141
- }
46142
- let entry;
46143
- if (member?.type.kind === "list") entry = member.type.elementType;
46144
- if (member?.type.kind === "dictionary")
46145
- entry = member.type.valueType;
46146
- if (entry?.kind === "named")
46147
- thisType = { ...entry, nullable: false };
46148
- }
46149
- }
46150
- } catch {
46151
- }
46152
- const id2 = `dialogue-context:${uri}:${declaration.name}`;
46153
- result.set(declaration, {
46154
- ...thisType ? { thisType } : {},
46155
- contextType: {
46156
- id: id2,
46157
- name: "DialogueContext",
46158
- kind: "synthetic",
46159
- members: [
46160
- {
46161
- id: `${id2}:primary`,
46162
- name: "primary",
46163
- kind: "property",
46164
- type: { kind: "primitive", name: "unknown" },
46165
- writable: false
46166
- },
46167
- {
46168
- id: `${id2}:trigger`,
46169
- name: "trigger",
46170
- kind: "property",
46171
- type: thisType ?? { kind: "primitive", name: "null" },
46172
- writable: false
46173
- }
46174
- ]
46175
- }
46176
- });
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 });
46177
46719
  }
46178
46720
  }
46179
- 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
+ };
46180
46778
  }
46181
46779
  function compileBody(args) {
46182
46780
  args.contexts.push({
@@ -46240,7 +46838,7 @@ function compileBody(args) {
46240
46838
  uri: args.uri,
46241
46839
  source: "neo-project",
46242
46840
  code: projectBodyDiagnosticCode(diagnostic.message, args.unit),
46243
- 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}`,
46244
46842
  relatedInformation: [
46245
46843
  {
46246
46844
  location: location(args.uri, args.declarationRange),
@@ -46786,7 +47384,7 @@ function projectRootType(documents, declarations) {
46786
47384
  }
46787
47385
  }
46788
47386
  }
46789
- return { id: "builtin:Root", name: "Root", kind: "synthetic", members };
47387
+ return { id: PROJECT_ROOT_TYPE_ID, name: "Root", kind: "synthetic", members };
46790
47388
  }
46791
47389
  function sourceTypeRef(type, owner, typeIds, resolvingTypeParameters = /* @__PURE__ */ new Set()) {
46792
47390
  const nullable2 = type.nullable || void 0;
@@ -46799,9 +47397,11 @@ function sourceTypeRef(type, owner, typeIds, resolvingTypeParameters = /* @__PUR
46799
47397
  };
46800
47398
  }
46801
47399
  if (type.name === "Set") {
47400
+ const element = type.typeArguments[0];
46802
47401
  return {
46803
47402
  kind: "set",
46804
- 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" },
46805
47405
  ...nullable2 ? { nullable: nullable2 } : {}
46806
47406
  };
46807
47407
  }
@@ -47003,16 +47603,15 @@ function sourceIdentity2(annotations, fallback) {
47003
47603
  function location(uri, range2) {
47004
47604
  return { uri, range: range2 };
47005
47605
  }
47006
- function capitalize(value) {
47606
+ function capitalize2(value) {
47007
47607
  return `${value[0]?.toUpperCase() ?? ""}${value.slice(1)}`;
47008
47608
  }
47009
- 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;
47010
47610
  var init_project_source_script_compiler = __esm({
47011
47611
  "../packages/neoscript-language/src/project-source-script-compiler.ts"() {
47012
47612
  "use strict";
47013
47613
  init_project_source_settlement();
47014
47614
  init_debug_info();
47015
- init_executable_parser();
47016
47615
  init_compiler();
47017
47616
  init_declared_constructors();
47018
47617
  init_language_spec();
@@ -47023,13 +47622,15 @@ var init_project_source_script_compiler = __esm({
47023
47622
  init_project_source_registry();
47024
47623
  init_source_text();
47025
47624
  init_lexer();
47625
+ init_dialogue_types();
47626
+ init_project_source_dialogue_groups();
47026
47627
  PRIMITIVE_NAME_LIST = [
47027
47628
  ...NEOSCRIPT_PRIMITIVE_TYPES,
47028
47629
  "void",
47029
47630
  "null",
47030
47631
  "SpriteInfo",
47031
47632
  "AudioClipInfo",
47032
- "DialogueRef",
47633
+ "NeoDialogueReference",
47033
47634
  "Vector2",
47034
47635
  "Vector2Int",
47035
47636
  "Vector3",
@@ -47043,6 +47644,46 @@ var init_project_source_script_compiler = __esm({
47043
47644
  User: "user"
47044
47645
  };
47045
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";
47046
47687
  }
47047
47688
  });
47048
47689
 
@@ -48035,7 +48676,7 @@ function validateClassOverrides(ref, environment, diagnostics) {
48035
48676
  }
48036
48677
  const target = candidates[candidates.length - 1];
48037
48678
  if (!target) {
48038
- 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";
48039
48680
  if (isDialogueTriggerOverride) continue;
48040
48681
  const opaqueBase = ref.declaration.baseTypes.find(
48041
48682
  (base) => BUILTIN_TYPES.has(base.name) && !environment.declarations.has(base.name)
@@ -48848,9 +49489,9 @@ var init_project_source_type_checker = __esm({
48848
49489
  "AudioTemplate",
48849
49490
  "Localization",
48850
49491
  "LocalizationStatus",
48851
- "PriorityGroup",
49492
+ "NeoPriorityGroup",
48852
49493
  "PriorityOption",
48853
- "DialogueGroup",
49494
+ "NeoDialogueGroup",
48854
49495
  "ImageRegistry",
48855
49496
  "AudioClipRegistry",
48856
49497
  "NeoImage",
@@ -49129,6 +49770,7 @@ function analyzeNeoProjectSources(inputs, parsedDocuments = /* @__PURE__ */ new
49129
49770
  }
49130
49771
  validateSymbolUniqueness(symbols, diagnostics);
49131
49772
  diagnostics.push(...validateDialogueGroupPaths({ documents, symbols }));
49773
+ diagnostics.push(...validateDialogueGroupNames({ documents, symbols }));
49132
49774
  diagnostics.push(...validateLocalValueInitializers(documents));
49133
49775
  diagnostics.push(...validateVariantDeclarations(documents));
49134
49776
  validateSystemAnnotationAuthoring(documents, diagnostics);
@@ -49632,7 +50274,7 @@ function validateTypeReferences(documents, symbols, diagnostics) {
49632
50274
  declaration.genericParameters.map((parameter4) => parameter4.name)
49633
50275
  ) : /* @__PURE__ */ new Set();
49634
50276
  for (const base of declaration.baseTypes) {
49635
- validateType(uri, base, generics, projectTypes, diagnostics);
50277
+ validateType(uri, base, generics, projectTypes, diagnostics, "base");
49636
50278
  }
49637
50279
  if (declaration.kind === "class") {
49638
50280
  for (const parameter4 of declaration.genericParameters) {
@@ -49642,7 +50284,8 @@ function validateTypeReferences(documents, symbols, diagnostics) {
49642
50284
  parameter4.constraint,
49643
50285
  generics,
49644
50286
  projectTypes,
49645
- diagnostics
50287
+ diagnostics,
50288
+ "base"
49646
50289
  );
49647
50290
  }
49648
50291
  }
@@ -49706,7 +50349,7 @@ function validateMemberTypes(uri, owner, member, genericParameters, projectTypes
49706
50349
  });
49707
50350
  }
49708
50351
  }
49709
- function validateType(uri, type, genericParameters, projectTypes, diagnostics) {
50352
+ function validateType(uri, type, genericParameters, projectTypes, diagnostics, position = "value") {
49710
50353
  if (!BUILTIN_TYPE_NAMES.has(type.name) && !genericParameters.has(type.name) && !projectTypes.has(type.name)) {
49711
50354
  diagnostics.push({
49712
50355
  uri,
@@ -49714,7 +50357,7 @@ function validateType(uri, type, genericParameters, projectTypes, diagnostics) {
49714
50357
  severity: "error",
49715
50358
  source: "neo-project",
49716
50359
  code: "unknown-project-type",
49717
- 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.`
49718
50361
  });
49719
50362
  }
49720
50363
  for (const argument2 of type.typeArguments) {
@@ -49747,6 +50390,7 @@ var BUILTIN_TYPE_NAMES, SYSTEM_RECORD_ID_PREFIX2, RFC_4122_UUID, QUARANTINED_LEG
49747
50390
  var init_project_source_analysis = __esm({
49748
50391
  "../packages/neoscript-language/src/project-source-analysis.ts"() {
49749
50392
  "use strict";
50393
+ init_dialogue_types();
49750
50394
  init_project_source_dialogue_groups();
49751
50395
  init_project_local_values();
49752
50396
  init_language_spec();
@@ -49771,9 +50415,9 @@ var init_project_source_analysis = __esm({
49771
50415
  "AudioTemplate",
49772
50416
  "Localization",
49773
50417
  "LocalizationStatus",
49774
- "PriorityGroup",
50418
+ "NeoPriorityGroup",
49775
50419
  "PriorityOption",
49776
- "DialogueGroup",
50420
+ "NeoDialogueGroup",
49777
50421
  "ImageRegistry",
49778
50422
  "AudioClipRegistry",
49779
50423
  "NeoImage",
@@ -50917,7 +51561,7 @@ var init_project_source_manifest = __esm({
50917
51561
  ]);
50918
51562
  FILE_REGISTRY_TYPES = /* @__PURE__ */ new Set(["ImageRegistry", "AudioClipRegistry"]);
50919
51563
  FILE_DECLARATION_TYPES = /* @__PURE__ */ new Set(["NeoImage", "NeoAudioClip"]);
50920
- GROUP_TYPES = /* @__PURE__ */ new Set(["PriorityGroup", "DialogueGroup"]);
51564
+ GROUP_TYPES = /* @__PURE__ */ new Set(["NeoPriorityGroup", "NeoDialogueGroup"]);
50921
51565
  MIGRATION_TYPES = /* @__PURE__ */ new Set(["Migration"]);
50922
51566
  }
50923
51567
  });
@@ -50982,7 +51626,7 @@ var init_registry = __esm({
50982
51626
  "../packages/manifest/schema-contract/registry.mjs"() {
50983
51627
  "use strict";
50984
51628
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
50985
- cliVersion: "0.72.2",
51629
+ cliVersion: "0.73.0",
50986
51630
  projectFileUploadBatchSize: 32,
50987
51631
  documentRecords: {
50988
51632
  member: {
@@ -62287,7 +62931,7 @@ var init_ui_action_source = __esm({
62287
62931
  // src/project-source/dialogue-group-symbols.ts
62288
62932
  function authoredDialogueGroupSymbols(analysis) {
62289
62933
  return new Map(
62290
- analysis?.dialogueGroups.globals.filter((global) => global.type.name === "DialogueGroup").map((global) => [
62934
+ analysis?.dialogueGroups.globals.filter((global) => global.type.name === "NeoDialogueGroup").map((global) => [
62291
62935
  global.id ?? `__pending__:dialogue-group:${encodeURIComponent(global.source.uri)}:${global.source.range.start.line}:${global.source.range.start.character}:${encodeURIComponent(global.name)}`,
62292
62936
  global.name
62293
62937
  ])
@@ -63460,7 +64104,7 @@ function memberSettings(context, member) {
63460
64104
  } else if (member.kind === "dialogueLookup") {
63461
64105
  if (member.dialogueGroupId) {
63462
64106
  settings.push(
63463
- `group: Reference<DialogueGroup>(id: ${quote(member.dialogueGroupId)})`
64107
+ `group: Reference<NeoDialogueGroup>(id: ${quote(member.dialogueGroupId)})`
63464
64108
  );
63465
64109
  }
63466
64110
  if (member.multiselect) settings.push("selection: .Multi");
@@ -63612,7 +64256,7 @@ function renderMemberType(context, member, enclosingClassId, elementSettings = f
63612
64256
  break;
63613
64257
  }
63614
64258
  case "dialogueLookup":
63615
- value = member.multiselect ? "Set<Dialogue>" : "Dialogue";
64259
+ value = member.multiselect ? "Set<NeoDialogueReference>" : "NeoDialogueReference";
63616
64260
  break;
63617
64261
  case "generic":
63618
64262
  value = genericName(context, member.genericParamId);
@@ -63709,7 +64353,7 @@ function renderType(context, type, enclosingClassId) {
63709
64353
  value = "Color";
63710
64354
  break;
63711
64355
  case "dialogueLookup":
63712
- value = "Dialogue";
64356
+ value = "NeoDialogueReference";
63713
64357
  break;
63714
64358
  case "class": {
63715
64359
  const schemaClass2 = required(context.classes, type.classId, "class");
@@ -63903,11 +64547,7 @@ function renderDefaultValue(context, member, wrapper, enclosingClassId) {
63903
64547
  ).name;
63904
64548
  }
63905
64549
  if ((member.kind === "lookup" || member.kind === "dialogueLookup") && Array.isArray(value)) {
63906
- const renderedType = renderMemberType(
63907
- context,
63908
- member,
63909
- enclosingClassId
63910
- ).replace(/\?$/u, "");
64550
+ const renderedType = referenceTargetType(context, member, enclosingClassId);
63911
64551
  const targetType = member.multiselect ? /^Set<(.+)>$/u.exec(renderedType)?.[1] ?? renderedType : renderedType;
63912
64552
  const refs = value.filter((entry) => typeof entry === "string").map((entry) => `Reference<${targetType}>(id: ${quote(entry)})`);
63913
64553
  if (refs.length === 0 && value.length === 0) return "[]";
@@ -63962,9 +64602,16 @@ function renderDefaultValue(context, member, wrapper, enclosingClassId) {
63962
64602
  function spriteFileSource(context, fileId) {
63963
64603
  return context.fileSymbols.get(fileId) ?? `Reference<NeoImage>(id: ${quote(fileId)})`;
63964
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
+ }
63965
64612
  function renderNestedValue(context, member, value, enclosingClassId) {
63966
64613
  if (typeof value === "string" && member.kind !== "string" && member.kind !== "decimal" && member.kind !== "enum") {
63967
- return `Reference<${renderMemberType(context, member, enclosingClassId).replace(/\?$/, "")}>(id: ${quote(value)})`;
64614
+ return `Reference<${referenceTargetType(context, member, enclosingClassId)}>(id: ${quote(value)})`;
63968
64615
  }
63969
64616
  return renderDefaultValue(
63970
64617
  context,
@@ -66246,7 +66893,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
66246
66893
  const storedStatic = declaration.modifiers.includes("static") && !declaration.modifiers.includes("readonly");
66247
66894
  const settings = annotation(declaration.annotations, "settings");
66248
66895
  const inherited = inheritedMember(context, commonInput.overrideOf);
66249
- 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"));
66250
66897
  const common = {
66251
66898
  ...commonInput,
66252
66899
  // A stored static initializer authors the live value binding, never an
@@ -66442,7 +67089,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
66442
67089
  assertNoElementSettings(fieldType, ownerClass, declaration, "enum");
66443
67090
  return { ...common, kind: "enum", enumId: enumId2, multiselect: true };
66444
67091
  }
66445
- if (entryType.name === "Dialogue" && multiselect) {
67092
+ if (entryType.name === "NeoDialogueReference" && multiselect) {
66446
67093
  assertNoElementSettings(fieldType, ownerClass, declaration, "dialogue");
66447
67094
  return {
66448
67095
  ...common,
@@ -66511,7 +67158,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
66511
67158
  }
66512
67159
  };
66513
67160
  }
66514
- if (name === "Dialogue") {
67161
+ if (name === "NeoDialogueReference") {
66515
67162
  return {
66516
67163
  ...common,
66517
67164
  kind: "dialogueLookup",
@@ -67118,7 +67765,8 @@ function lowerType(context, type, ownerClass) {
67118
67765
  };
67119
67766
  }
67120
67767
  }
67121
- if (type.name === "Dialogue") return { kind: "dialogueLookup", nullable: nullable2 };
67768
+ if (type.name === "NeoDialogueReference")
67769
+ return { kind: "dialogueLookup", nullable: nullable2 };
67122
67770
  if (type.name === "object") return { kind: "unknown", nullable: nullable2 };
67123
67771
  throw new Error(`Unknown Neo type ${JSON.stringify(type.name)}.`);
67124
67772
  }
@@ -67917,7 +68565,7 @@ function manifestTypeForSchemaType(context, type) {
67917
68565
  case "vector3Int":
67918
68566
  return { name: "Vector3Int", nullable: nullable2, arguments: [] };
67919
68567
  case "dialogueLookup":
67920
- return { name: "Dialogue", nullable: nullable2, arguments: [] };
68568
+ return { name: "NeoDialogueReference", nullable: nullable2, arguments: [] };
67921
68569
  case "color":
67922
68570
  return { name: "Color", nullable: nullable2, arguments: [] };
67923
68571
  case "class": {
@@ -69460,7 +70108,7 @@ function lowerSupplementalProjectRecordsV4(state, analysis, projectFileRecords)
69460
70108
  );
69461
70109
  }
69462
70110
  const priorityGlobals = analysis.dialogueGroups.globals.filter(
69463
- (global) => global.type.name === "PriorityGroup"
70111
+ (global) => global.type.name === "NeoPriorityGroup"
69464
70112
  );
69465
70113
  const priorityIds = globalIds(priorityGlobals, "priority-group");
69466
70114
  for (const global of priorityGlobals) {
@@ -69475,7 +70123,7 @@ function lowerSupplementalProjectRecordsV4(state, analysis, projectFileRecords)
69475
70123
  );
69476
70124
  }
69477
70125
  const dialogueGlobals = analysis.dialogueGroups.globals.filter(
69478
- (global) => global.type.name === "DialogueGroup"
70126
+ (global) => global.type.name === "NeoDialogueGroup"
69479
70127
  );
69480
70128
  const dialogueIds = globalIds(dialogueGlobals, "dialogue-group");
69481
70129
  const uiLogicResolver = analysisUILogicResolver(analysis);
@@ -69521,7 +70169,7 @@ function emitProjectGlobal(data, textureNames, audioNames, priorityNames) {
69521
70169
  ],
69522
70170
  [
69523
70171
  "defaultPriorityGroup",
69524
- reference(data.defaultPriorityGroupId, priorityNames, "PriorityGroup")
70172
+ reference(data.defaultPriorityGroupId, priorityNames, "NeoPriorityGroup")
69525
70173
  ]
69526
70174
  ].filter((entry) => entry[1] !== null);
69527
70175
  return `Project Project = new(${args.length === 0 ? "" : `
@@ -69547,7 +70195,7 @@ function emitPriorityGroup(data, recordId, name) {
69547
70195
  ...isObjectRecord2(data.system) ? [emitSystemAnnotation(data.system)] : []
69548
70196
  ];
69549
70197
  return `${annotations.join("\n")}
69550
- PriorityGroup ${name} = new() {
70198
+ NeoPriorityGroup ${name} = new() {
69551
70199
  ${body.join("\n\n")}
69552
70200
  }
69553
70201
  `;
@@ -69561,13 +70209,13 @@ function emitDialogueGroup(data, recordId, name, priorityNames, dialogueNames, u
69561
70209
  const priority = reference(
69562
70210
  data.priorityGroupIdOverride,
69563
70211
  priorityNames,
69564
- "PriorityGroup"
70212
+ "NeoPriorityGroup"
69565
70213
  );
69566
70214
  if (priority) args.push(["priorityGroup", priority]);
69567
70215
  const parent = reference(
69568
70216
  data.parentDialogueGroupId,
69569
70217
  dialogueNames,
69570
- "DialogueGroup"
70218
+ "NeoDialogueGroup"
69571
70219
  );
69572
70220
  if (parent) args.push(["parent", parent]);
69573
70221
  if (typeof data.collectionMemberId === "string") {
@@ -69592,7 +70240,7 @@ function emitDialogueGroup(data, recordId, name, priorityNames, dialogueNames, u
69592
70240
  ${args.map(([argument2, value]) => ` ${argument2}: ${value},`).join("\n")}
69593
70241
  )`;
69594
70242
  return `@id(${quote2(recordId)})
69595
- DialogueGroup ${name} = ${constructor2}${body.length > 0 ? ` {
70243
+ NeoDialogueGroup ${name} = ${constructor2}${body.length > 0 ? ` {
69596
70244
  ${body.map((entry) => indentNeoSource(entry, 2)).join("\n\n")}
69597
70245
  }` : ";"}
69598
70246
  `;
@@ -69636,7 +70284,7 @@ function collectDialogueGroupFunctions(data, groupId, resolver) {
69636
70284
  const existing = functions.get(functionId);
69637
70285
  if (existing.code !== code) {
69638
70286
  throw new Error(
69639
- `DialogueGroup function ${functionId} has divergent persisted uses.`
70287
+ `NeoDialogueGroup function ${functionId} has divergent persisted uses.`
69640
70288
  );
69641
70289
  }
69642
70290
  }
@@ -69653,7 +70301,7 @@ function requiredStringField(value, field, owner) {
69653
70301
  }
69654
70302
  function emitDialogueGroupFunction(fn) {
69655
70303
  if (fn.id === null) {
69656
- throw new Error(`Pulled DialogueGroup function ${fn.name} has no id.`);
70304
+ throw new Error(`Pulled NeoDialogueGroup function ${fn.name} has no id.`);
69657
70305
  }
69658
70306
  const annotation2 = `@id(${quote2(fn.id)})`;
69659
70307
  if (fn.code === null) {
@@ -69671,7 +70319,7 @@ function emitDialogueGroupUseList(uses) {
69671
70319
  ${uses.map((use) => {
69672
70320
  if (use.id === null) {
69673
70321
  throw new Error(
69674
- `Pulled DialogueGroup condition ${use.functionName} has no id.`
70322
+ `Pulled NeoDialogueGroup condition ${use.functionName} has no id.`
69675
70323
  );
69676
70324
  }
69677
70325
  return ` @id(${quote2(use.id)})
@@ -69706,7 +70354,7 @@ function lowerProjectGlobal(baseValue, global, analysis) {
69706
70354
  args.get("defaultPriorityGroup"),
69707
70355
  globalIds(
69708
70356
  analysis.dialogueGroups.globals.filter(
69709
- (entry) => entry.type.name === "PriorityGroup"
70357
+ (entry) => entry.type.name === "NeoPriorityGroup"
69710
70358
  ),
69711
70359
  "priority-group"
69712
70360
  )
@@ -69721,7 +70369,7 @@ function lowerPriorityGroup(baseValue, global) {
69721
70369
  const initializer = global.initializer.trim();
69722
70370
  const bodyMatch = /^new\s*\(\s*\)\s*\{([\s\S]*)\}$/.exec(initializer);
69723
70371
  if (!bodyMatch) {
69724
- throw new Error(`PriorityGroup ${global.name} must use new() { ... }.`);
70372
+ throw new Error(`NeoPriorityGroup ${global.name} must use new() { ... }.`);
69725
70373
  }
69726
70374
  let body = bodyMatch[1];
69727
70375
  while (body.trim().length > 0) {
@@ -69730,16 +70378,20 @@ function lowerPriorityGroup(baseValue, global) {
69730
70378
  const match = PRIORITY_OPTION_PATTERN.exec(body);
69731
70379
  if (!match) {
69732
70380
  throw new Error(
69733
- `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))}.`
69734
70382
  );
69735
70383
  }
69736
70384
  const name = match[2];
69737
70385
  const id2 = match[1] ? JSON.parse(`"${match[1]}"`) : `__pending__:priority-option:${encodeURIComponent(globalId(global, "priority-group"))}:${encodeURIComponent(name)}`;
69738
70386
  if (seenNames.has(name)) {
69739
- throw new Error(`PriorityGroup ${global.name} repeats option ${name}.`);
70387
+ throw new Error(
70388
+ `NeoPriorityGroup ${global.name} repeats option ${name}.`
70389
+ );
69740
70390
  }
69741
70391
  if (seenIds.has(id2)) {
69742
- throw new Error(`PriorityGroup ${global.name} repeats option id ${id2}.`);
70392
+ throw new Error(
70393
+ `NeoPriorityGroup ${global.name} repeats option id ${id2}.`
70394
+ );
69743
70395
  }
69744
70396
  seenNames.add(name);
69745
70397
  seenIds.add(id2);
@@ -69769,14 +70421,14 @@ function sourceDialogueGroupType(global) {
69769
70421
  const authored = parseDialogueGroupInitializer(global.initializer);
69770
70422
  return dialogueGroupType(
69771
70423
  global.name,
69772
- constructorArguments(authored.constructor, "DialogueGroup")
70424
+ constructorArguments(authored.constructor, "NeoDialogueGroup")
69773
70425
  );
69774
70426
  }
69775
70427
  function dialogueGroupType(name, args) {
69776
70428
  const kind = args.get("kind");
69777
70429
  if (kind?.kind !== "contextualEnum") {
69778
70430
  throw new Error(
69779
- `DialogueGroup ${name} requires kind: .Standard, .Lookup, or .Folder.`
70431
+ `NeoDialogueGroup ${name} requires kind: .Standard, .Lookup, or .Folder.`
69780
70432
  );
69781
70433
  }
69782
70434
  const type = kind.name === "Lookup" ? 1 /* Lookup */ : kind.name === "Folder" ? 2 /* Folder */ : kind.name === "Standard" ? 0 /* Standard */ : null;
@@ -69787,7 +70439,7 @@ function dialogueGroupType(name, args) {
69787
70439
  function dialogueGroupDisplayName(expression, symbol) {
69788
70440
  if (expression?.kind !== "litString" || expression.value.trim().length === 0)
69789
70441
  throw new Error(
69790
- `DialogueGroup ${symbol} name must be a non-empty string literal.`
70442
+ `NeoDialogueGroup ${symbol} name must be a non-empty string literal.`
69791
70443
  );
69792
70444
  return expression.value;
69793
70445
  }
@@ -69797,7 +70449,7 @@ function lowerDialogueGroup(baseValue, global, priorityIds, dialogueIds, uiLogic
69797
70449
  Reflect.deleteProperty(baseWithoutLookup, "collectionMemberId");
69798
70450
  Reflect.deleteProperty(baseWithoutLookup, "collectionValueId");
69799
70451
  const authored = parseDialogueGroupInitializer(global.initializer);
69800
- const args = constructorArguments(authored.constructor, "DialogueGroup");
70452
+ const args = constructorArguments(authored.constructor, "NeoDialogueGroup");
69801
70453
  const type = dialogueGroupType(global.name, args);
69802
70454
  const collection = args.get("collection");
69803
70455
  let collectionMemberId;
@@ -69865,7 +70517,7 @@ function lowerDialogueGroupConditions(base, global, authored, uiLogicResolver) {
69865
70517
  for (const fn of authored.functions) {
69866
70518
  if (functions.has(fn.name)) {
69867
70519
  throw new Error(
69868
- `DialogueGroup ${global.name} repeats function ${fn.name}.`
70520
+ `NeoDialogueGroup ${global.name} repeats function ${fn.name}.`
69869
70521
  );
69870
70522
  }
69871
70523
  functions.set(fn.name, fn);
@@ -69881,14 +70533,14 @@ function lowerDialogueGroupConditions(base, global, authored, uiLogicResolver) {
69881
70533
  );
69882
70534
  if (usedIds.has(id2)) {
69883
70535
  throw new Error(
69884
- `DialogueGroup ${global.name} repeats condition id ${id2}.`
70536
+ `NeoDialogueGroup ${global.name} repeats condition id ${id2}.`
69885
70537
  );
69886
70538
  }
69887
70539
  usedIds.add(id2);
69888
70540
  const fn = functions.get(use.functionName);
69889
70541
  if (!fn) {
69890
70542
  throw new Error(
69891
- `DialogueGroup ${global.name} condition ${use.functionName} has no body function.`
70543
+ `NeoDialogueGroup ${global.name} condition ${use.functionName} has no body function.`
69892
70544
  );
69893
70545
  }
69894
70546
  usedFunctions.add(fn.name);
@@ -69926,7 +70578,7 @@ function lowerDialogueGroupConditions(base, global, authored, uiLogicResolver) {
69926
70578
  for (const fn of authored.functions) {
69927
70579
  if (!usedFunctions.has(fn.name)) {
69928
70580
  throw new Error(
69929
- `DialogueGroup ${global.name} function ${fn.name} is not referenced by when.`
70581
+ `NeoDialogueGroup ${global.name} function ${fn.name} is not referenced by when.`
69930
70582
  );
69931
70583
  }
69932
70584
  }
@@ -70007,12 +70659,12 @@ function parseDialogueGroupInitializer(initializer) {
70007
70659
  }
70008
70660
  }
70009
70661
  if (closeIndex < 0) {
70010
- throw new Error("DialogueGroup initializer has an unclosed body.");
70662
+ throw new Error("NeoDialogueGroup initializer has an unclosed body.");
70011
70663
  }
70012
70664
  const close = tokens[closeIndex];
70013
70665
  const trailing = tokens.slice(closeIndex + 1);
70014
70666
  if (trailing.length > 1 || trailing[0] && trailing[0].text !== ";") {
70015
- throw new Error("Nothing may follow a DialogueGroup body.");
70667
+ throw new Error("Nothing may follow a NeoDialogueGroup body.");
70016
70668
  }
70017
70669
  let depth = 0;
70018
70670
  let whenIndex = -1;
@@ -70022,7 +70674,7 @@ function parseDialogueGroupInitializer(initializer) {
70022
70674
  else if (token.text === "}") depth -= 1;
70023
70675
  else if (depth === 0 && token.text === "when") {
70024
70676
  if (whenIndex >= 0) {
70025
- throw new Error("DialogueGroup body may declare when only once.");
70677
+ throw new Error("NeoDialogueGroup body may declare when only once.");
70026
70678
  }
70027
70679
  whenIndex = index;
70028
70680
  }
@@ -70033,7 +70685,7 @@ function parseDialogueGroupInitializer(initializer) {
70033
70685
  if (whenIndex < 0) {
70034
70686
  if (parsedFunctions.length > 0) {
70035
70687
  throw new Error(
70036
- "DialogueGroup body functions require a final when: [...] use list."
70688
+ "NeoDialogueGroup body functions require a final when: [...] use list."
70037
70689
  );
70038
70690
  }
70039
70691
  return {
@@ -70045,7 +70697,7 @@ function parseDialogueGroupInitializer(initializer) {
70045
70697
  const colon = tokens[whenIndex + 1];
70046
70698
  if (colon?.text !== ":") {
70047
70699
  throw new Error(
70048
- "DialogueGroup condition uses must be written as when: [...]."
70700
+ "NeoDialogueGroup condition uses must be written as when: [...]."
70049
70701
  );
70050
70702
  }
70051
70703
  let parenDepth = 0;
@@ -70066,10 +70718,12 @@ function parseDialogueGroupInitializer(initializer) {
70066
70718
  }
70067
70719
  }
70068
70720
  if (semicolonIndex < 0) {
70069
- throw new Error("DialogueGroup when: [...] must end with a semicolon.");
70721
+ throw new Error("NeoDialogueGroup when: [...] must end with a semicolon.");
70070
70722
  }
70071
70723
  if (tokens.slice(semicolonIndex + 1, closeIndex).length > 0) {
70072
- 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
+ );
70073
70727
  }
70074
70728
  const semicolon = tokens[semicolonIndex];
70075
70729
  return {
@@ -70091,17 +70745,17 @@ function parseDialogueGroupFunctions(source) {
70091
70745
  );
70092
70746
  if (errors.length > 0) {
70093
70747
  throw new Error(
70094
- `Invalid DialogueGroup body: ${errors.map((diagnostic) => diagnostic.message).join(" ")}`
70748
+ `Invalid NeoDialogueGroup body: ${errors.map((diagnostic) => diagnostic.message).join(" ")}`
70095
70749
  );
70096
70750
  }
70097
70751
  const declaration = parsed.declarations[0];
70098
70752
  if (declaration?.kind !== "class") {
70099
- throw new Error("DialogueGroup body could not be parsed.");
70753
+ throw new Error("NeoDialogueGroup body could not be parsed.");
70100
70754
  }
70101
70755
  return declaration.members.map((member) => {
70102
70756
  if (member.kind !== "function") {
70103
70757
  throw new Error(
70104
- "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."
70105
70759
  );
70106
70760
  }
70107
70761
  assertDialogueGroupFunctionSignature(member);
@@ -70115,19 +70769,19 @@ function parseDialogueGroupFunctions(source) {
70115
70769
  function assertDialogueGroupFunctionSignature(member) {
70116
70770
  if (member.type.name !== "bool" || member.type.nullable || member.type.typeArguments.length > 0 || member.parameters.length > 0 || member.modifiers.includes("async")) {
70117
70771
  throw new Error(
70118
- `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.`
70119
70773
  );
70120
70774
  }
70121
70775
  if (member.body === void 0 && !member.modifiers.includes("native")) {
70122
70776
  throw new Error(
70123
- `DialogueGroup function ${member.name} requires a body or the native modifier.`
70777
+ `NeoDialogueGroup function ${member.name} requires a body or the native modifier.`
70124
70778
  );
70125
70779
  }
70126
70780
  }
70127
70781
  function parseDialogueGroupUseList(expression) {
70128
70782
  const trimmed = expression.trim();
70129
70783
  if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) {
70130
- throw new Error("DialogueGroup when uses must use bracket list syntax.");
70784
+ throw new Error("NeoDialogueGroup when uses must use bracket list syntax.");
70131
70785
  }
70132
70786
  const body = trimmed.slice(1, -1);
70133
70787
  const pattern = /\s*(?:@id\(\s*("(?:[^"\\]|\\.)*")\s*\)\s*)?([A-Za-z_][A-Za-z0-9_]*)\s*(?:,|$)/gy;
@@ -70139,7 +70793,7 @@ function parseDialogueGroupUseList(expression) {
70139
70793
  if (!match) {
70140
70794
  if (body.slice(consumed).trim().length === 0) break;
70141
70795
  throw new Error(
70142
- `Invalid DialogueGroup condition-use list near ${JSON.stringify(body.slice(consumed))}.`
70796
+ `Invalid NeoDialogueGroup condition-use list near ${JSON.stringify(body.slice(consumed))}.`
70143
70797
  );
70144
70798
  }
70145
70799
  result.push({
@@ -70156,7 +70810,7 @@ function annotationId(annotations) {
70156
70810
  const parsed = JSON.parse(expression);
70157
70811
  if (typeof parsed !== "string" || parsed.length === 0) {
70158
70812
  throw new Error(
70159
- "DialogueGroup function @id must contain a non-empty string."
70813
+ "NeoDialogueGroup function @id must contain a non-empty string."
70160
70814
  );
70161
70815
  }
70162
70816
  return parsed;
@@ -70448,7 +71102,7 @@ function builtinTextVariableMember(receiver, name) {
70448
71102
  function createDialogueLoweringIndexesV4(state, analysis, options = {}) {
70449
71103
  const mainLocale = readMainLocale(state);
70450
71104
  const dialogueGroups = analysis.dialogueGroups.globals.filter(
70451
- (global) => global.type.name === "DialogueGroup"
71105
+ (global) => global.type.name === "NeoDialogueGroup"
70452
71106
  );
70453
71107
  const dialogueGroupIds = globalIds2(dialogueGroups, "dialogue-group");
70454
71108
  const lookupDialogueGroupIds = new Set(
@@ -71826,7 +72480,7 @@ function lowerDialogueGroupSettings(context, member, base) {
71826
72480
  const expression = constructorExpression(member.arguments, "group");
71827
72481
  if (expression === null) return null;
71828
72482
  const old = isObjectRecord2(base.dialogueGroupSettings) ? base.dialogueGroupSettings : {};
71829
- const referencedGroupId = referenceId3(expression, "DialogueGroup");
72483
+ const referencedGroupId = referenceId3(expression, "NeoDialogueGroup");
71830
72484
  if (referencedGroupId !== null) {
71831
72485
  if (!context.groupPaths.byId.has(referencedGroupId)) {
71832
72486
  throw dialogueSourceError(
@@ -72730,7 +73384,7 @@ var init_dialogue_lower = __esm({
72730
73384
  required: required2
72731
73385
  };
72732
73386
  }
72733
- if (type.name === "Dialogue") {
73387
+ if (type.name === "NeoDialogueReference") {
72734
73388
  return { type: 18 /* DialogueLookup */, required: required2 };
72735
73389
  }
72736
73390
  return null;
@@ -72871,7 +73525,8 @@ function projectSchemaManifest(input, options = {}) {
72871
73525
  (item, index) => enumType(item, environment, `enums[${index}]`)
72872
73526
  )
72873
73527
  ];
72874
- const rootType = createRootType(rootMemberIds, environment);
73528
+ const dialogues = neoScriptDialogueTypes(options.dialogueGroups ?? []);
73529
+ const rootType = createRootType(rootMemberIds, environment, dialogues.member);
72875
73530
  declaredTypes.push(rootType);
72876
73531
  const roots = options.roots ?? [
72877
73532
  {
@@ -72890,7 +73545,7 @@ function projectSchemaManifest(input, options = {}) {
72890
73545
  return {
72891
73546
  project: {
72892
73547
  version: options.version ?? `manifest:${nextManifestProjectionVersion++}`,
72893
- types: languageTypes,
73548
+ types: [...languageTypes, ...dialogues.types],
72894
73549
  globals: options.globals ?? [],
72895
73550
  roots,
72896
73551
  listIndexes: members.flatMap(
@@ -73025,7 +73680,7 @@ function staticDefaultWritability(classId, environment) {
73025
73680
  resolvedAllowedStorage(classId, environment)
73026
73681
  );
73027
73682
  }
73028
- function createRootType(ids, environment) {
73683
+ function createRootType(ids, environment, dialogues) {
73029
73684
  const definitions = [
73030
73685
  ["Assets", ids.assets, false, "immutable"],
73031
73686
  ["Save", ids.save, true, "save"],
@@ -73048,6 +73703,7 @@ function createRootType(ids, environment) {
73048
73703
  ...sourceLocation(member.source, environment, `root.${name}.source`)
73049
73704
  });
73050
73705
  }
73706
+ members.push(dialogues);
73051
73707
  return {
73052
73708
  id: "__root__",
73053
73709
  name: "Root",
@@ -73824,8 +74480,7 @@ function memberType(member, environment, visiting, field) {
73824
74480
  return member.multiselect === true ? { kind: "set", elementType: entryType, nullable: nullable2 } : { ...entryType, nullable: nullable2 };
73825
74481
  }
73826
74482
  if (kind === "dialogueLookup") {
73827
- const dialogue = primitive("DialogueRef", false);
73828
- 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 };
73829
74484
  }
73830
74485
  if (kind === "computed") {
73831
74486
  return manifestType2(member.returnType, environment, `${field}.returnType`);
@@ -74307,7 +74962,7 @@ function manifestPrimitive(kind) {
74307
74962
  case "vector3Int":
74308
74963
  return "Vector3Int";
74309
74964
  case "dialogueLookup":
74310
- return "DialogueRef";
74965
+ return "NeoDialogueReference";
74311
74966
  case "color":
74312
74967
  return "Color";
74313
74968
  default:
@@ -74474,6 +75129,7 @@ var init_project_schema_manifest = __esm({
74474
75129
  init_project2();
74475
75130
  init_project2();
74476
75131
  init_language_spec();
75132
+ init_dialogue_types();
74477
75133
  nextManifestProjectionVersion = 1;
74478
75134
  }
74479
75135
  });
@@ -74605,6 +75261,58 @@ var init_interface_types = __esm({
74605
75261
  }
74606
75262
  });
74607
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
+
74608
75316
  // ../src/runtime/neoscript/analyzer-types.ts
74609
75317
  function createAnalyzerSchemaIndex(context) {
74610
75318
  return projectSchemaIndexFor({
@@ -74824,8 +75532,15 @@ function createNeoScriptProjectInScope(context) {
74824
75532
  })
74825
75533
  });
74826
75534
  }
74827
- const rootType = createRootType2(context);
74828
- 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);
74829
75544
  if (context.dialogueContext) {
74830
75545
  languageTypes.push(createDialogueContextType(context));
74831
75546
  }
@@ -75353,7 +76068,7 @@ function interfaceMemberToSymbol(neoInterface, key, member, context, inherited)
75353
76068
  ...inheritedFrom ? { inheritedFrom } : {}
75354
76069
  };
75355
76070
  }
75356
- function createRootType2(context) {
76071
+ function createRootType2(context, dialogues) {
75357
76072
  const members = [];
75358
76073
  for (const [index, root] of PROJECT_ROOTS.entries()) {
75359
76074
  const name = root.key;
@@ -75378,6 +76093,7 @@ function createRootType2(context) {
75378
76093
  )
75379
76094
  });
75380
76095
  }
76096
+ members.push(dialogues);
75381
76097
  return {
75382
76098
  id: AnalyzerRootClassId,
75383
76099
  name: "Root",
@@ -75480,11 +76196,11 @@ function memberRuntimeType(record7, context, seen = /* @__PURE__ */ new Set(), g
75480
76196
  if (isMemberDialogueLookupBase(member) && isMultiSelectionMember(member)) {
75481
76197
  return {
75482
76198
  kind: "set",
75483
- elementType: primitive2("DialogueRef", true),
76199
+ elementType: primitive2("string", true),
75484
76200
  nullable: !required2
75485
76201
  };
75486
76202
  }
75487
- return primitive2("DialogueRef", required2);
76203
+ return primitive2("NeoDialogueReference", required2);
75488
76204
  case 14 /* Vector2 */:
75489
76205
  return primitive2("Vector2", required2);
75490
76206
  case 15 /* Vector2Int */:
@@ -75732,7 +76448,7 @@ function toLanguageType(type, context, genericEnvironment) {
75732
76448
  case 12 /* Audio */:
75733
76449
  return primitive2("AudioClipInfo", required2);
75734
76450
  case 18 /* DialogueLookup */:
75735
- return primitive2("DialogueRef", required2);
76451
+ return primitive2("NeoDialogueReference", required2);
75736
76452
  case 14 /* Vector2 */:
75737
76453
  return primitive2("Vector2", required2);
75738
76454
  case 15 /* Vector2Int */:
@@ -75932,7 +76648,9 @@ function projectLanguageVersion(context) {
75932
76648
  ...context.vm.projectFiles ?? [],
75933
76649
  // P43 §6. Editing a constructor's parameters changes what a `new Foo(…)`
75934
76650
  // call site resolves to, so an open editor's cached context must rebuild.
75935
- ...context.constructors ?? []
76651
+ ...context.constructors ?? [],
76652
+ // P105 §2.6. Group names, parents, and kinds shape `root.Dialogues`.
76653
+ ...context.vm.dialogueGroups ?? []
75936
76654
  ];
75937
76655
  return [
75938
76656
  `adapter:${NEOSCRIPT_COMPILER_ADAPTER_REVISION}`,
@@ -76140,8 +76858,10 @@ var init_neoscript_language_context_adapter = __esm({
76140
76858
  init_variant_member();
76141
76859
  init_project_root_members();
76142
76860
  init_project_file_registry();
76861
+ init_dialogue_types();
76862
+ init_dialogue_group_language();
76143
76863
  init_analyzer_types();
76144
- NEOSCRIPT_COMPILER_ADAPTER_REVISION = 5;
76864
+ NEOSCRIPT_COMPILER_ADAPTER_REVISION = 6;
76145
76865
  UNKNOWN_TYPE2 = {
76146
76866
  kind: "primitive",
76147
76867
  name: "unknown"
@@ -86412,6 +87132,26 @@ function evalFunction(fn, scope, ctx) {
86412
87132
  const pointer = evalPointer(fn.info.pointer, scope, ctx);
86413
87133
  return dialogueMemoryVisitCount(pointer, ctx) > 0;
86414
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
+ }
86415
87155
  case "vectorConstructor" /* vectorConstructor */: {
86416
87156
  return evalVectorConstructor(
86417
87157
  fn.info.vectorType,
@@ -95503,6 +96243,7 @@ function createAnalyzerProject(ctx) {
95503
96243
  return {
95504
96244
  project: ctx.project,
95505
96245
  projectFiles: [...ctx.projectFiles ?? []],
96246
+ dialogueGroups: [...ctx.dialogueGroups ?? []],
95506
96247
  members,
95507
96248
  classes: [...ctx.classes],
95508
96249
  enums: [...ctx.enums],
@@ -96830,6 +97571,7 @@ function compileDelegateClosureValue(code, signature) {
96830
97571
  const compiled = compileNSGetter(`return ${code};`, {
96831
97572
  project: signature.project,
96832
97573
  projectFiles: [...signature.projectFiles ?? []],
97574
+ dialogueGroups: signature.dialogueGroups ?? [],
96833
97575
  members: [...signature.members],
96834
97576
  classes: [...signature.classes],
96835
97577
  enums: [...signature.enums],
@@ -96915,6 +97657,7 @@ function compilationProjectContext(args, members = args.members) {
96915
97657
  return {
96916
97658
  project: args.project,
96917
97659
  projectFiles: args.projectFiles ?? [],
97660
+ dialogueGroups: args.dialogueGroups ?? [],
96918
97661
  members: [...members],
96919
97662
  classes: [...args.classes],
96920
97663
  enums: [...args.enums],
@@ -97565,6 +98308,7 @@ function compilationProjectForDocument(document, state) {
97565
98308
  state.compilationProject ??= createNeoScriptCompilationProject({
97566
98309
  project: document.project,
97567
98310
  projectFiles: document.projectFiles,
98311
+ dialogueGroups: document.dialogueGroups,
97568
98312
  members: document.members,
97569
98313
  classes: document.classes,
97570
98314
  enums: document.enums,
@@ -97658,6 +98402,7 @@ function compileValueInitializerDependency(document, valueId, compilationProject
97658
98402
  compileValueRowInitializerBody({
97659
98403
  project: document.project,
97660
98404
  projectFiles: document.projectFiles,
98405
+ dialogueGroups: document.dialogueGroups,
97661
98406
  members: document.members,
97662
98407
  classes: document.classes,
97663
98408
  enums: document.enums,
@@ -97676,6 +98421,7 @@ function compileMemberInitializerDependency(document, memberId, compilationProje
97676
98421
  const compileArgs = {
97677
98422
  project: document.project,
97678
98423
  projectFiles: document.projectFiles,
98424
+ dialogueGroups: document.dialogueGroups,
97679
98425
  members: document.members,
97680
98426
  classes: document.classes,
97681
98427
  enums: document.enums,
@@ -98143,7 +98889,7 @@ function isDialogueProps(value) {
98143
98889
  function isDialogue(value) {
98144
98890
  return isDialogueProps(value);
98145
98891
  }
98146
- var init_dialogue_types = __esm({
98892
+ var init_dialogue_types2 = __esm({
98147
98893
  "../src/models/dialogue/dialogue-types.ts"() {
98148
98894
  "use strict";
98149
98895
  init_core_types();
@@ -99469,7 +100215,7 @@ var init_project_document_read = __esm({
99469
100215
  init_constructors2();
99470
100216
  init_variants();
99471
100217
  init_dialogue_group_types();
99472
- init_dialogue_types();
100218
+ init_dialogue_types2();
99473
100219
  init_priority_types();
99474
100220
  init_enum();
99475
100221
  init_neoscript();
@@ -99779,7 +100525,9 @@ function collectCompilerReferencesInto(value, field, ids, names, constructedClas
99779
100525
  function isCompilerReferenceField(field) {
99780
100526
  return /(?:member|class|enum|interface|constructor|variant)(?:Type)?Ids?$/i.test(
99781
100527
  field
99782
- ) || 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";
99783
100531
  }
99784
100532
  function collectChangedContractIds(args) {
99785
100533
  const impactedIds = /* @__PURE__ */ new Set();
@@ -99809,7 +100557,26 @@ function collectChangedContractIds(args) {
99809
100557
  );
99810
100558
  const currentSchemaRecords = schemaRecordsByKind(args.currentDocument);
99811
100559
  const postSchemaRecords = schemaRecordsByKind(args.postDocument);
100560
+ const currentGroups = new DialogueGroupTree(args.currentDocument);
100561
+ const postGroups = new DialogueGroupTree(args.postDocument);
99812
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
+ }
99813
100580
  if (change.recordKind === "class" || change.recordKind === "enum" || change.recordKind === "interface") {
99814
100581
  const kind = change.recordKind;
99815
100582
  const current2 = currentSchemaRecords[kind].get(change.recordId);
@@ -100329,7 +101096,7 @@ function withoutFields(value, ignored) {
100329
101096
  Object.entries(value).filter(([field]) => !ignored.has(field))
100330
101097
  );
100331
101098
  }
100332
- 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;
100333
101100
  var init_neo_script_recompile_scope = __esm({
100334
101101
  "../src/database/neo-script-recompile-scope.ts"() {
100335
101102
  "use strict";
@@ -100337,6 +101104,8 @@ var init_neo_script_recompile_scope = __esm({
100337
101104
  init_neo_script_derived_bodies();
100338
101105
  init_canonical_json();
100339
101106
  init_lexer();
101107
+ init_generated_csharp_identifiers();
101108
+ init_dialogue_group_language();
100340
101109
  init_member_kind_enum();
100341
101110
  init_member_kinds();
100342
101111
  init_inheritance();
@@ -100370,6 +101139,31 @@ var init_neo_script_recompile_scope = __esm({
100370
101139
  "bodyMode",
100371
101140
  "uiAction"
100372
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
+ };
100373
101167
  NO_PLACEMENTS = /* @__PURE__ */ new Set();
100374
101168
  classPlacementIndexes = /* @__PURE__ */ new WeakMap();
100375
101169
  }
@@ -101205,7 +101999,7 @@ var init_project_record_validation = __esm({
101205
101999
  init_packed_value_record_validation();
101206
102000
  init_enum();
101207
102001
  init_interface_types();
101208
- init_dialogue_types();
102002
+ init_dialogue_types2();
101209
102003
  init_dialogue_group_types();
101210
102004
  init_priority_types();
101211
102005
  init_files();
@@ -106016,6 +106810,7 @@ function resolveDialogueCompileContext(args) {
106016
106810
  classes: args.classes,
106017
106811
  enums: args.enums,
106018
106812
  interfaces: args.interfaces ?? [],
106813
+ dialogueGroups: args.dialogueGroups,
106019
106814
  thisClass: resolveNeoSchemaClassFromTypeInfo(thisClass, args.classes),
106020
106815
  returnTypeInfo: args.returnTypeInfo,
106021
106816
  ...valueAliases.length ? { valueAliases } : {},
@@ -106085,6 +106880,7 @@ function resolveDialogueGroupCompileContext(args) {
106085
106880
  classes: args.classes,
106086
106881
  enums: args.enums,
106087
106882
  interfaces: args.interfaces ?? [],
106883
+ dialogueGroups: args.dialogueGroups,
106088
106884
  thisClass,
106089
106885
  returnTypeInfo: args.returnTypeInfo,
106090
106886
  dialogueContext: {
@@ -106117,7 +106913,15 @@ function compileDialogueLogic(request, projectData, reuseProject) {
106117
106913
  "Invalid dialogue logic compile body: expected ICompileDialogueLogicRequest."
106118
106914
  );
106119
106915
  }
106120
- 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;
106121
106925
  if (request.target === 0 /* Condition */) {
106122
106926
  const ctx2 = request.dialogueGroup ? resolveDialogueGroupCompileContext({
106123
106927
  project,
@@ -106126,6 +106930,7 @@ function compileDialogueLogic(request, projectData, reuseProject) {
106126
106930
  values,
106127
106931
  enums,
106128
106932
  interfaces,
106933
+ dialogueGroups,
106129
106934
  dialogueGroup: request.dialogueGroup,
106130
106935
  returnTypeInfo: { type: 1 /* Bool */, required: true }
106131
106936
  }) : resolveDialogueCompileContext({
@@ -106135,6 +106940,7 @@ function compileDialogueLogic(request, projectData, reuseProject) {
106135
106940
  values,
106136
106941
  enums,
106137
106942
  interfaces,
106943
+ dialogueGroups,
106138
106944
  dialogue: request.dialogue ?? {},
106139
106945
  node: request.node,
106140
106946
  returnTypeInfo: { type: 1 /* Bool */, required: true }
@@ -106169,6 +106975,7 @@ function compileDialogueLogic(request, projectData, reuseProject) {
106169
106975
  values,
106170
106976
  enums,
106171
106977
  interfaces,
106978
+ dialogueGroups,
106172
106979
  dialogue: request.dialogue ?? {},
106173
106980
  node: request.node,
106174
106981
  returnTypeInfo: sourceBacked ? request.textVariable.typeInfo : { type: 3 /* String */, required: true }
@@ -106198,6 +107005,7 @@ function compileDialogueLogic(request, projectData, reuseProject) {
106198
107005
  values,
106199
107006
  enums,
106200
107007
  interfaces,
107008
+ dialogueGroups,
106201
107009
  dialogue: request.dialogue ?? {},
106202
107010
  node: request.node,
106203
107011
  returnTypeInfo: { type: 0 /* Null */, required: true }
@@ -108384,7 +109192,7 @@ var init_general_function_call_ir_source_recompile = __esm({
108384
109192
  "use strict";
108385
109193
  init_members();
108386
109194
  init_core();
108387
- init_dialogue_types();
109195
+ init_dialogue_types2();
108388
109196
  init_logic_types();
108389
109197
  init_inheritance();
108390
109198
  init_project_content_hash();
@@ -108882,6 +109690,9 @@ function neoScriptCompilationProjectContract(document) {
108882
109690
  name: file.name,
108883
109691
  fileType: file.fileType
108884
109692
  })),
109693
+ dialogueGroups: (document.dialogueGroups ?? []).map(
109694
+ dialogueGroupLanguageContract
109695
+ ),
108885
109696
  members: document.members.map(
108886
109697
  (member) => neoScriptMemberContractProjection(
108887
109698
  member
@@ -108932,6 +109743,7 @@ var init_project_fingerprint = __esm({
108932
109743
  "use strict";
108933
109744
  init_strict_ir();
108934
109745
  init_neo_script_recompile_scope();
109746
+ init_dialogue_group_language();
108935
109747
  init_compiler_adapter();
108936
109748
  }
108937
109749
  });
@@ -113763,6 +114575,7 @@ function prepareServerOwnedValueInitializerBodies(args) {
113763
114575
  const compilationProject = cachedServerCompilationProject({
113764
114576
  project: document.project,
113765
114577
  projectFiles: document.projectFiles,
114578
+ dialogueGroups: document.dialogueGroups,
113766
114579
  members: document.members,
113767
114580
  classes: document.classes,
113768
114581
  enums: document.enums,
@@ -113788,6 +114601,7 @@ function prepareServerOwnedValueInitializerBodies(args) {
113788
114601
  compileValueRowInitializerBody({
113789
114602
  project: document.project,
113790
114603
  projectFiles: document.projectFiles,
114604
+ dialogueGroups: document.dialogueGroups,
113791
114605
  members: document.members,
113792
114606
  classes: document.classes,
113793
114607
  enums: document.enums,
@@ -114003,6 +114817,7 @@ function compileInlineDelegateConstructorArguments(args) {
114003
114817
  compiled[argumentKey] = compileDelegateClosureValue(argument2.code, {
114004
114818
  project: document.project,
114005
114819
  projectFiles: document.projectFiles,
114820
+ dialogueGroups: document.dialogueGroups,
114006
114821
  members: document.members,
114007
114822
  classes: document.classes,
114008
114823
  enums: document.enums,
@@ -114052,6 +114867,7 @@ function createDelegateValueBodyCompiler(postDocument, targetIds) {
114052
114867
  compiled.value = compileDelegateClosureValue(row.value.code, {
114053
114868
  project: document.project,
114054
114869
  projectFiles: document.projectFiles,
114870
+ dialogueGroups: document.dialogueGroups,
114055
114871
  members: document.members,
114056
114872
  classes: document.classes,
114057
114873
  enums: document.enums,
@@ -114232,6 +115048,7 @@ function prepareServerOwnedConstructorBodies(args) {
114232
115048
  ),
114233
115049
  project: document.project,
114234
115050
  projectFiles: document.projectFiles,
115051
+ dialogueGroups: document.dialogueGroups,
114235
115052
  members: document.members,
114236
115053
  classes: document.classes,
114237
115054
  enums: document.enums,
@@ -114413,6 +115230,7 @@ function compileOneAuthoredMember(args) {
114413
115230
  scriptSources: args.scriptSources,
114414
115231
  project: args.document.project,
114415
115232
  projectFiles: args.document.projectFiles,
115233
+ dialogueGroups: args.document.dialogueGroups,
114416
115234
  members: args.members,
114417
115235
  classes: args.document.classes,
114418
115236
  enums: args.document.enums,
@@ -123078,6 +123896,7 @@ function replayStoredConstructionV4(args) {
123078
123896
  const compilationProject = args.compilationProject ?? (args.compileDocumentBodies === true ? createNeoScriptCompilationProject({
123079
123897
  project: document.project,
123080
123898
  projectFiles: document.projectFiles,
123899
+ dialogueGroups: document.dialogueGroups,
123081
123900
  members: document.members,
123082
123901
  classes: document.classes,
123083
123902
  enums: document.enums,
@@ -123134,6 +123953,7 @@ function replayStoredConstructionV4(args) {
123134
123953
  compileValueRowInitializerBody({
123135
123954
  project: document.project,
123136
123955
  projectFiles: document.projectFiles,
123956
+ dialogueGroups: document.dialogueGroups,
123137
123957
  members: document.members,
123138
123958
  classes: document.classes,
123139
123959
  enums: document.enums,
@@ -123205,6 +124025,7 @@ function compilePulledUncompiledConstructorsV4(document, compilationProject, rep
123205
124025
  const project = compilationProject ?? createNeoScriptCompilationProject({
123206
124026
  project: document.project,
123207
124027
  projectFiles: document.projectFiles,
124028
+ dialogueGroups: document.dialogueGroups,
123208
124029
  members: document.members,
123209
124030
  classes: document.classes,
123210
124031
  enums: document.enums,
@@ -123214,6 +124035,7 @@ function compilePulledUncompiledConstructorsV4(document, compilationProject, rep
123214
124035
  const compileArgs = {
123215
124036
  project: document.project,
123216
124037
  projectFiles: document.projectFiles,
124038
+ dialogueGroups: document.dialogueGroups,
123217
124039
  members: document.members,
123218
124040
  classes: document.classes,
123219
124041
  enums: document.enums,
@@ -123230,6 +124052,7 @@ function compilePulledProjectDocumentForEvaluationV4(document, compilationProjec
123230
124052
  const sharedCompilationProject = compilationProject ?? createNeoScriptCompilationProject({
123231
124053
  project: document.project,
123232
124054
  projectFiles: document.projectFiles,
124055
+ dialogueGroups: document.dialogueGroups,
123233
124056
  members: document.members,
123234
124057
  classes: document.classes,
123235
124058
  enums: document.enums,
@@ -123240,6 +124063,7 @@ function compilePulledProjectDocumentForEvaluationV4(document, compilationProjec
123240
124063
  const compileArgs = {
123241
124064
  project: document.project,
123242
124065
  projectFiles: document.projectFiles,
124066
+ dialogueGroups: document.dialogueGroups,
123243
124067
  members: document.members,
123244
124068
  classes: document.classes,
123245
124069
  enums: document.enums,
@@ -125017,6 +125841,7 @@ function buildValueLowerContext(state, manifest, options = {}) {
125017
125841
  localizationConversionValueIds: registry.localizationConversionValueIds,
125018
125842
  loweredMemberIdByValueId: /* @__PURE__ */ new Map(),
125019
125843
  storedClassSchemaMemberIds: /* @__PURE__ */ new Map(),
125844
+ renamedSchemaKeys: /* @__PURE__ */ new Map(),
125020
125845
  ordinaryMoveFields: /* @__PURE__ */ new Map(),
125021
125846
  pendingBindingMembersByClassId: registry.pendingBindingMembersByClassId,
125022
125847
  declaredConstructors: declaredConstructorIndex,
@@ -126285,7 +127110,11 @@ function lowerRowBackedDefault(context, member, backed, baseData3, binding) {
126285
127110
  environment,
126286
127111
  binding.label
126287
127112
  );
126288
- const baseBody = backed.body;
127113
+ const baseBody = retainedStoredClassBody(
127114
+ context,
127115
+ currentClassId,
127116
+ backed.body
127117
+ );
126289
127118
  const body = {};
126290
127119
  lowerConstructorProjections(
126291
127120
  context,
@@ -126685,12 +127514,43 @@ function pendingSeedGraphRows(args) {
126685
127514
  function retainedStoredClassBody(context, storedClassId, baseBody) {
126686
127515
  const storedMemberIds = storedClassSchemaMemberIds(context, storedClassId);
126687
127516
  const body = {};
127517
+ const renames = renamedSchemaKeys(context, storedClassId);
126688
127518
  for (const [key, childId] of Object.entries(baseBody)) {
126689
127519
  if (storedMemberRemoved(context, storedMemberIds, key)) continue;
126690
- body[key] = childId;
127520
+ body[renames.get(key) ?? key] = childId;
126691
127521
  }
126692
127522
  return body;
126693
127523
  }
127524
+ function renamedSchemaKeys(context, classId) {
127525
+ const cached = context.renamedSchemaKeys.get(classId);
127526
+ if (cached !== void 0) return cached;
127527
+ const currentMembers = /* @__PURE__ */ new Map();
127528
+ for (const schemaClass2 of classInheritanceChain(context.classes, classId)) {
127529
+ for (const [key, memberId] of Object.entries(schemaClass2.schema)) {
127530
+ if (!currentMembers.has(key)) currentMembers.set(key, memberId);
127531
+ }
127532
+ }
127533
+ const renamed = schemaKeyRenamesByMemberId(
127534
+ storedClassSchemaMemberIds(context, classId),
127535
+ currentMembers
127536
+ );
127537
+ context.renamedSchemaKeys.set(classId, renamed);
127538
+ return renamed;
127539
+ }
127540
+ function schemaKeyRenamesByMemberId(before, after) {
127541
+ const currentKeys = /* @__PURE__ */ new Map();
127542
+ for (const [key, memberId] of after) {
127543
+ if (memberId !== null && !currentKeys.has(memberId))
127544
+ currentKeys.set(memberId, key);
127545
+ }
127546
+ const renamed = /* @__PURE__ */ new Map();
127547
+ for (const [key, memberId] of before) {
127548
+ const currentKey = memberId === null ? void 0 : currentKeys.get(memberId);
127549
+ if (currentKey !== void 0 && currentKey !== key)
127550
+ renamed.set(key, currentKey);
127551
+ }
127552
+ return renamed;
127553
+ }
126694
127554
  function storedMemberRemoved(context, storedMemberIds, key) {
126695
127555
  const storedMemberId = storedMemberIds.get(key);
126696
127556
  return storedMemberId !== void 0 && !context.members.has(storedMemberId);
@@ -127932,7 +128792,7 @@ function lowerValueBody(context, member, expression, base, source, environment,
127932
128792
  );
127933
128793
  }
127934
128794
  }
127935
- function authoredResetSchemaKeys(context, base, baseBody, expression, partial) {
128795
+ function authoredResetSchemaKeys(context, base, baseBody, expression, partial, classId) {
127936
128796
  if (partial) return /* @__PURE__ */ new Set();
127937
128797
  if (expression.kind !== "new") return /* @__PURE__ */ new Set();
127938
128798
  if (typeof base.id !== "string") return /* @__PURE__ */ new Set();
@@ -127940,15 +128800,17 @@ function authoredResetSchemaKeys(context, base, baseBody, expression, partial) {
127940
128800
  (expression.initializer ?? []).map((assignment) => assignment.name)
127941
128801
  );
127942
128802
  const expressions = context.materializedConstructorExpressions;
128803
+ const renames = renamedSchemaKeys(context, classId);
127943
128804
  if (Object.keys(baseBody).every(
127944
- (key) => authored.has(key) || expressions.declaresSchemaKey?.(key) === false
128805
+ (key) => authored.has(renames.get(key) ?? key) || expressions.declaresSchemaKey?.(key) === false
127945
128806
  )) {
127946
128807
  return /* @__PURE__ */ new Set();
127947
128808
  }
127948
128809
  const canonicalOverrideKeys = expressions.overrideSchemaKeys?.(base.id);
127949
128810
  if (canonicalOverrideKeys === void 0) return /* @__PURE__ */ new Set();
127950
128811
  const resets = /* @__PURE__ */ new Set();
127951
- for (const schemaKey of canonicalOverrideKeys) {
128812
+ for (const storedKey of canonicalOverrideKeys) {
128813
+ const schemaKey = renames.get(storedKey) ?? storedKey;
127952
128814
  if (!authored.has(schemaKey)) resets.add(schemaKey);
127953
128815
  }
127954
128816
  return resets;
@@ -128005,7 +128867,7 @@ function lowerClassValue(context, member, expression, base, source, outerEnviron
128005
128867
  schemaClass2,
128006
128868
  expression,
128007
128869
  base,
128008
- baseBody,
128870
+ body,
128009
128871
  body,
128010
128872
  source,
128011
128873
  environment,
@@ -128075,7 +128937,8 @@ function lowerClassValue(context, member, expression, base, source, outerEnviron
128075
128937
  base,
128076
128938
  baseBody,
128077
128939
  expression,
128078
- partial
128940
+ partial,
128941
+ currentClassId
128079
128942
  );
128080
128943
  for (const schemaKey of resetSchemaKeys) delete body[schemaKey];
128081
128944
  {
@@ -128083,10 +128946,12 @@ function lowerClassValue(context, member, expression, base, source, outerEnviron
128083
128946
  (expression.initializer ?? []).map((assignment) => assignment.name)
128084
128947
  );
128085
128948
  const storedMemberIds = storedClassSchemaMemberIds(context, currentClassId);
128086
- for (const [schemaKey, childId] of Object.entries(baseBody)) {
128949
+ const renames = renamedSchemaKeys(context, currentClassId);
128950
+ for (const [storedKey, childId] of Object.entries(baseBody)) {
128951
+ const schemaKey = renames.get(storedKey) ?? storedKey;
128087
128952
  if (typeof childId !== "string") continue;
128088
128953
  if (resetSchemaKeys.has(schemaKey)) continue;
128089
- if (storedMemberRemoved(context, storedMemberIds, schemaKey)) continue;
128954
+ if (storedMemberRemoved(context, storedMemberIds, storedKey)) continue;
128090
128955
  if (materializedConstruction === "lower" && authoredKeys.has(schemaKey)) {
128091
128956
  continue;
128092
128957
  }
@@ -128095,7 +128960,7 @@ function lowerClassValue(context, member, expression, base, source, outerEnviron
128095
128960
  childId,
128096
128961
  source.source,
128097
128962
  /* @__PURE__ */ new Set(),
128098
- memberById(context, storedMemberIds.get(schemaKey)),
128963
+ memberById(context, storedMemberIds.get(storedKey)),
128099
128964
  environment
128100
128965
  );
128101
128966
  }
@@ -128195,14 +129060,18 @@ function retainStoredValueSubgraph(context, valueId, source, visited, member, en
128195
129060
  visited.add(valueId);
128196
129061
  const state = context.state[`value:${valueId}`];
128197
129062
  if (state === void 0 || !isObjectRecord2(state.data)) return;
128198
- addReconstructed(
128199
- context,
128200
- "value",
128201
- valueId,
128202
- valueFileFields(state.data),
128203
- source,
128204
- { retained: true }
128205
- );
129063
+ const storedClassId = stringOrNull2(state.data.classId);
129064
+ const fields = valueFileFields(state.data);
129065
+ if (storedClassId !== null && isObjectRecord2(state.data.value) && renamedSchemaKeys(context, storedClassId).size > 0) {
129066
+ fields.value = retainedStoredClassBody(
129067
+ context,
129068
+ storedClassId,
129069
+ state.data.value
129070
+ );
129071
+ }
129072
+ addReconstructed(context, "value", valueId, fields, source, {
129073
+ retained: true
129074
+ });
128206
129075
  const rawOwningMember = member ?? storedRowPlacementMember(context, valueId);
128207
129076
  const owningMember = rawOwningMember === null ? null : resolveGenericSchemaMember(context, rawOwningMember, environment);
128208
129077
  if (owningMember?.kind === "string" && owningMember.localizable) {
@@ -128250,7 +129119,6 @@ function retainStoredValueSubgraph(context, valueId, source, visited, member, en
128250
129119
  for (const entry of Object.values(value)) collect(entry, childMember);
128251
129120
  };
128252
129121
  const body = state.data.value;
128253
- const storedClassId = stringOrNull2(state.data.classId);
128254
129122
  let childEnvironment = environment;
128255
129123
  if (storedClassId !== null) {
128256
129124
  if (owningMember?.kind === "class") {
@@ -128395,13 +129263,14 @@ function classProjectsEveryStoredConstructorRow(context, classId, argumentCount,
128395
129263
  if (projections2.length === 0 || projections2.length !== argumentCount) {
128396
129264
  return false;
128397
129265
  }
129266
+ const body = renamedSchemaKeys(context, classId).size === 0 ? storedBody : retainedStoredClassBody(context, classId, storedBody);
128398
129267
  return projections2.every((projection) => {
128399
129268
  const schemaKey = inheritedProjectionSchemaKey(
128400
129269
  context.classes,
128401
129270
  classId,
128402
129271
  projection.memberId
128403
129272
  );
128404
- return schemaKey !== null && typeof storedBody[schemaKey] === "string";
129273
+ return schemaKey !== null && typeof body[schemaKey] === "string";
128405
129274
  });
128406
129275
  }
128407
129276
  function requiredConstructorProjectionMap(classes, constructors, members, classId, visited) {
@@ -129522,7 +130391,7 @@ function validateReferenceContract(context, member, target, ownerValueId) {
129522
130391
  `Dialogue member ${member.name} requires a dialogue target.`
129523
130392
  );
129524
130393
  }
129525
- if (target.genericTypeName && target.genericTypeName !== "Dialogue" && target.genericTypeName !== target.typeName) {
130394
+ if (target.genericTypeName && target.genericTypeName !== "NeoDialogue" && target.genericTypeName !== target.typeName) {
129526
130395
  throw new Error(
129527
130396
  `Reference<${target.genericTypeName}> does not accept dialogue ${target.id}.`
129528
130397
  );
@@ -129545,7 +130414,7 @@ function lookupEntryTypeName(context, member) {
129545
130414
  if (entry.kind === "class")
129546
130415
  return context.classes.get(entry.classId)?.name ?? null;
129547
130416
  if (entry.kind === "enum") return null;
129548
- if (entry.kind === "dialogueLookup") return "Dialogue";
130417
+ if (entry.kind === "dialogueLookup") return "NeoDialogueReference";
129549
130418
  return entry.kind;
129550
130419
  }
129551
130420
  function referenceTypeNameAssignable(context, actualName, expectedName) {
@@ -130067,7 +130936,7 @@ function freshConstructionReplaysDeclaredDefault(resolved, child2, defaultValue)
130067
130936
  function classMemberByName(context, classId, name) {
130068
130937
  const memberId = classMemberIdByName(context, classId, name);
130069
130938
  if (memberId !== null) return requiredMember(context, memberId);
130070
- throw new Error(
130939
+ throw new MissingStoredMemberError(
130071
130940
  `Class ${context.classes.get(classId)?.name ?? classId} has no stored member ${name}.`
130072
130941
  );
130073
130942
  }
@@ -131673,7 +132542,7 @@ function storedSchemaTypeName(context, type, environment, valueId) {
131673
132542
  case "lookup":
131674
132543
  return storedSchemaTypeName(context, type.entryType, environment);
131675
132544
  case "dialogueLookup":
131676
- return "Dialogue";
132545
+ return "NeoDialogueReference";
131677
132546
  case "delegate":
131678
132547
  return "object";
131679
132548
  case "action":
@@ -132250,7 +133119,7 @@ function referenceValue(context, member, body, dialogue) {
132250
133119
  }
132251
133120
  const symbol = context.localValues?.byValueId.get(id2)?.name ?? context.symbolsByValueId.get(id2);
132252
133121
  if (symbol !== void 0) return `Reference(${symbol})`;
132253
- const type = dialogue ? "Dialogue" : memberReferenceType(context, member);
133122
+ const type = dialogue ? "NeoDialogue" : memberReferenceType(context, member);
132254
133123
  if (!dialogue) {
132255
133124
  const key = uniqueIndexKeyForTarget(context, member, id2);
132256
133125
  if (key !== null) return `Reference<${type}>(key: ${quote3(key)})`;
@@ -132609,7 +133478,7 @@ function memberDefaultBody(member) {
132609
133478
  if (!("value" in defaultValue)) return null;
132610
133479
  return defaultValue.value;
132611
133480
  }
132612
- 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;
132613
133482
  var init_value_sources = __esm({
132614
133483
  "src/project-source/value-sources.ts"() {
132615
133484
  "use strict";
@@ -132674,6 +133543,8 @@ var init_value_sources = __esm({
132674
133543
  `${PENDING_ID_PREFIX}reference-key:init:\\d+`,
132675
133544
  "g"
132676
133545
  );
133546
+ MissingStoredMemberError = class extends Error {
133547
+ };
132677
133548
  CANONICAL_CONSTRUCTOR_INLINE_WIDTH = 88;
132678
133549
  }
132679
133550
  });
@@ -136499,9 +137370,11 @@ function emitDialogue(args) {
136499
137370
  content: `@id(${quote5(dialogueId)})
136500
137371
  ${args.recoveryReason ? `@incomplete(${quote5(args.recoveryReason)})
136501
137372
  ` : ""}@settings(
136502
- ${settings.map(([name, value]) => ` ${name}: ${value}`).join(",\n")}
137373
+ ${settings.map(([name, value]) => ` ${name}: ${value}`).join(
137374
+ ",\n"
137375
+ )}
136503
137376
  )
136504
- sealed class ${args.className} : Dialogue {
137377
+ sealed class ${args.className} : NeoDialogue {
136505
137378
  ${members.map((member) => indentNeoSource(member, 2)).join("\n\n")}
136506
137379
  }
136507
137380
  `,
@@ -136536,7 +137409,10 @@ function emitTrigger(context, node) {
136536
137409
  if (groupName && optionName && !context.groupChildNames.get(groupId)?.has(optionName))
136537
137410
  args.push(["group", `${groupName}.${optionName}`]);
136538
137411
  else if (groupId) {
136539
- args.push(["group", `Reference<DialogueGroup>(id: ${quote5(groupId)})`]);
137412
+ args.push([
137413
+ "group",
137414
+ `Reference<NeoDialogueGroup>(id: ${quote5(groupId)})`
137415
+ ]);
136540
137416
  if (optionId) {
136541
137417
  args.push([
136542
137418
  "priority",
@@ -137245,7 +138121,7 @@ var init_dialogue_sources = __esm({
137245
138121
  init_ui_action_source();
137246
138122
  PERSISTED_VARIABLE_PATH = /^(?:ref|linked):([^.]+)(\..+)?$/u;
137247
138123
  DIALOGUE_SYSTEM_TYPE_NAMES = [
137248
- "Dialogue",
138124
+ "NeoDialogue",
137249
138125
  "Trigger",
137250
138126
  "Text",
137251
138127
  "Actions",
@@ -138440,6 +139316,7 @@ function loadOrBuildNeoScriptProjectV1(root, document) {
138440
139316
  const project = createNeoScriptCompilationProject({
138441
139317
  project: document.project,
138442
139318
  projectFiles: document.projectFiles,
139319
+ dialogueGroups: document.dialogueGroups,
138443
139320
  members: document.members,
138444
139321
  classes: document.classes,
138445
139322
  enums: document.enums,
@@ -138693,7 +139570,7 @@ function materializedInitializerReconciliationFailuresV4(args) {
138693
139570
  continue;
138694
139571
  }
138695
139572
  assertPulledConstructorsCompiled(replayDocument, replayContext);
138696
- currentRows ??= new Map(currentDocument.values.map((row) => [row.id, row]));
139573
+ currentRows ??= storedRowsWithRenamedKeys(currentDocument, replayDocument);
138697
139574
  currentReader ??= new EffectiveValueReader(replayDocument, currentRows);
138698
139575
  const replay = replayRows.get(reconciliation.valueId);
138699
139576
  const replayArgs = replay !== void 0 && isLiteralValueContent(replay) ? replay.constructorArgs : void 0;
@@ -138725,6 +139602,41 @@ function materializedInitializerReconciliationFailuresV4(args) {
138725
139602
  }
138726
139603
  return failures;
138727
139604
  }
139605
+ function storedRowsWithRenamedKeys(before, after) {
139606
+ const renamesByClass = /* @__PURE__ */ new Map();
139607
+ const rows = /* @__PURE__ */ new Map();
139608
+ for (const row of before.values) {
139609
+ let renamed = row;
139610
+ if (typeof row.classId === "string" && isObjectRecord2(row.value)) {
139611
+ const classId = row.classId;
139612
+ let renames = renamesByClass.get(classId);
139613
+ if (renames === void 0) {
139614
+ const entries = (document) => mergeInstanceSurfaceSchema(
139615
+ classId,
139616
+ document.classes,
139617
+ document.members
139618
+ ).map((entry) => [entry.schemaKey, entry.memberId]);
139619
+ renames = schemaKeyRenamesByMemberId(entries(before), entries(after));
139620
+ renamesByClass.set(row.classId, renames);
139621
+ }
139622
+ if (renames.size > 0) {
139623
+ const value = {};
139624
+ let collision = false;
139625
+ for (const [key, child2] of Object.entries(row.value)) {
139626
+ const target = renames.get(key) ?? key;
139627
+ if (target !== key && Object.hasOwn(row.value, target) && !renames.has(target)) {
139628
+ collision = true;
139629
+ break;
139630
+ }
139631
+ value[target] = child2;
139632
+ }
139633
+ if (!collision) renamed = { ...row, value };
139634
+ }
139635
+ }
139636
+ rows.set(row.id, renamed);
139637
+ }
139638
+ return rows;
139639
+ }
138728
139640
  function withoutSharedArguments(stored, replayed) {
138729
139641
  const storedRest = { ...stored };
138730
139642
  const replayedRest = { ...replayed };
@@ -139108,6 +140020,7 @@ var init_local_initializer_materialization = __esm({
139108
140020
  init_variant_value_graph();
139109
140021
  init_members();
139110
140022
  init_member_value_id();
140023
+ init_inheritance();
139111
140024
  init_effective_value_reader();
139112
140025
  init_virtual_instance_values();
139113
140026
  init_value_graph();
@@ -139336,6 +140249,25 @@ function workspaceStatusInitializerDiagnostic(workspace, status, sites, texts, a
139336
140249
  }
139337
140250
  }
139338
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) {
139339
140271
  assertCurrentBaseline(workspace.state.records);
139340
140272
  let phaseStarted = performance.now();
139341
140273
  options.onPhase?.("Reading project schema\u2026");
@@ -139345,9 +140277,6 @@ function computeWorkspaceStatus(workspace, options) {
139345
140277
  phaseStarted = finished;
139346
140278
  if (nextLabel !== void 0) options.onPhase?.(nextLabel);
139347
140279
  };
139348
- const conflictedFiles = [];
139349
- const parseErrors = [];
139350
- const parseWarnings = [];
139351
140280
  const migrationSources = [];
139352
140281
  const projectSources = [];
139353
140282
  if (options.virtualSourceFiles === void 0) {
@@ -140319,33 +141248,35 @@ function computeWorkspaceStatus(workspace, options) {
140319
141248
  )
140320
141249
  );
140321
141250
  }
140322
- try {
140323
- parseErrors.push(
140324
- ...materializedInitializerReconciliationFailuresV4({
140325
- workspace,
140326
- changes,
140327
- authoredValueSeeds,
140328
- reconciliations: valueLowerRegistry.initializerReconciliations,
140329
- canonicalConstructions: valueLowerRegistry.materializedConstructorExpressions,
140330
- localizedTextDependencies,
140331
- manifest,
140332
- analysis: projectAnalysisV4,
140333
- forceRecompile: options.forceRecompile,
140334
- useBuildCaches: options.useBuildCaches,
140335
- sourceTextByUri: new Map(
140336
- sourceEntries.map((entry) => [entry.relPath, entry.source])
141251
+ if (!parseErrors.some(isBlockingSchemaSourceError)) {
141252
+ try {
141253
+ parseErrors.push(
141254
+ ...materializedInitializerReconciliationFailuresV4({
141255
+ workspace,
141256
+ changes,
141257
+ authoredValueSeeds,
141258
+ reconciliations: valueLowerRegistry.initializerReconciliations,
141259
+ canonicalConstructions: valueLowerRegistry.materializedConstructorExpressions,
141260
+ localizedTextDependencies,
141261
+ manifest,
141262
+ analysis: projectAnalysisV4,
141263
+ forceRecompile: options.forceRecompile,
141264
+ useBuildCaches: options.useBuildCaches,
141265
+ sourceTextByUri: new Map(
141266
+ sourceEntries.map((entry) => [entry.relPath, entry.source])
141267
+ )
141268
+ })
141269
+ );
141270
+ } catch (error) {
141271
+ parseErrors.push(
141272
+ error instanceof SchemaSourceError ? error : new SchemaSourceError(
141273
+ error instanceof Error ? error.message : String(error),
141274
+ "<initializer-materialization>",
141275
+ 1,
141276
+ 1
140337
141277
  )
140338
- })
140339
- );
140340
- } catch (error) {
140341
- parseErrors.push(
140342
- error instanceof SchemaSourceError ? error : new SchemaSourceError(
140343
- error instanceof Error ? error.message : String(error),
140344
- "<initializer-materialization>",
140345
- 1,
140346
- 1
140347
- )
140348
- );
141278
+ );
141279
+ }
140349
141280
  }
140350
141281
  reportPhase("initializer-reconciliation", "Checking project files\u2026");
140351
141282
  for (const fileId of options.trustedPendingProjectFiles?.keys() ?? []) {
@@ -140410,7 +141341,7 @@ function computeWorkspaceStatus(workspace, options) {
140410
141341
  )) {
140411
141342
  parseErrors.push(new SchemaSourceError(message, "<project-files>", 1, 1));
140412
141343
  }
140413
- if (animationValidationInputsChanged(changes, authoredValueSeeds)) {
141344
+ if (!parseErrors.some(isBlockingSchemaSourceError) && animationValidationInputsChanged(changes, authoredValueSeeds)) {
140414
141345
  try {
140415
141346
  const animationRecords = prospectiveAnimationRecords(
140416
141347
  workspace.state.records,
@@ -140554,6 +141485,7 @@ function replayAnimationDeclarationInitializersV4(records3, document, fallbackDo
140554
141485
  const compilationProject = createNeoScriptCompilationProject({
140555
141486
  project: replayDocument.project,
140556
141487
  projectFiles: replayDocument.projectFiles,
141488
+ dialogueGroups: replayDocument.dialogueGroups,
140557
141489
  members: replayDocument.members,
140558
141490
  classes: replayDocument.classes,
140559
141491
  enums: replayDocument.enums,
@@ -146966,37 +147898,37 @@ function collectionSymbols(kind, type) {
146966
147898
  const readOnly = type.readOnly === true;
146967
147899
  const canMutate = !readOnly;
146968
147900
  const symbols = [
146969
- method(
147901
+ method2(
146970
147902
  "Where",
146971
147903
  type,
146972
147904
  lambdaParameters(kind, entryType, keyType),
146973
147905
  "Filter this collection."
146974
147906
  ),
146975
- method(
147907
+ method2(
146976
147908
  "First",
146977
147909
  entryType,
146978
147910
  lambdaParameters(kind, entryType, keyType),
146979
147911
  "Return the first matching entry; throws when none exists."
146980
147912
  ),
146981
- method(
147913
+ method2(
146982
147914
  "FirstOrDefault",
146983
147915
  withNullability(entryType, true),
146984
147916
  lambdaParameters(kind, entryType, keyType),
146985
147917
  "Return the first matching entry, or null."
146986
147918
  ),
146987
- method(
147919
+ method2(
146988
147920
  "Select",
146989
147921
  { kind: "list", elementType: UNKNOWN_TYPE },
146990
147922
  lambdaParameters(kind, entryType, keyType),
146991
147923
  "Map each collection entry."
146992
147924
  ),
146993
- method(
147925
+ method2(
146994
147926
  "Contains",
146995
147927
  { kind: "primitive", name: "bool" },
146996
147928
  [parameter3("value", entryType)],
146997
147929
  "Return whether the collection contains a value."
146998
147930
  ),
146999
- method(
147931
+ method2(
147000
147932
  "Count",
147001
147933
  { kind: "primitive", name: "int" },
147002
147934
  [optionalCollectionPredicate(kind, entryType, keyType)],
@@ -147044,7 +147976,7 @@ function collectionSymbols(kind, type) {
147044
147976
  })
147045
147977
  ];
147046
147978
  symbols.push(
147047
- method(
147979
+ method2(
147048
147980
  name,
147049
147981
  returnType,
147050
147982
  parameters,
@@ -147054,7 +147986,7 @@ function collectionSymbols(kind, type) {
147054
147986
  }
147055
147987
  if (kind === "list") {
147056
147988
  symbols.push(
147057
- method(
147989
+ method2(
147058
147990
  "IndexOf",
147059
147991
  { kind: "primitive", name: "int" },
147060
147992
  [parameter3("value", entryType)],
@@ -147144,7 +148076,7 @@ function optionalCollectionPredicate(kind, entry, key) {
147144
148076
  defaultValue: { displayText: "null", value: null }
147145
148077
  };
147146
148078
  }
147147
- function method(name, returnType, parameters, documentation) {
148079
+ function method2(name, returnType, parameters, documentation) {
147148
148080
  return {
147149
148081
  id: `builtin:collection:${name}`,
147150
148082
  name,
@@ -147156,11 +148088,11 @@ function method(name, returnType, parameters, documentation) {
147156
148088
  };
147157
148089
  }
147158
148090
  function mutationMethod(name, returnType, parameters, documentation) {
147159
- return method(name, returnType, parameters, documentation);
148091
+ return method2(name, returnType, parameters, documentation);
147160
148092
  }
147161
148093
  function stringReplaceSymbol() {
147162
148094
  const stringType = { kind: "primitive", name: "string" };
147163
- return method(
148095
+ return method2(
147164
148096
  "Replace",
147165
148097
  stringType,
147166
148098
  [parameter3("search", stringType), parameter3("replacement", stringType)],
@@ -147168,7 +148100,7 @@ function stringReplaceSymbol() {
147168
148100
  );
147169
148101
  }
147170
148102
  function stringContainsSymbol() {
147171
- return method(
148103
+ return method2(
147172
148104
  "Contains",
147173
148105
  { kind: "primitive", name: "bool" },
147174
148106
  [parameter3("substring", { kind: "primitive", name: "string" })],
@@ -147291,9 +148223,9 @@ function inferLambdaParameterType(local, snapshot) {
147291
148223
  ]);
147292
148224
  for (let cursor = declarationIndex - 1; cursor >= 1; cursor--) {
147293
148225
  const open = tokens[cursor];
147294
- const method2 = tokens[cursor - 1];
148226
+ const method3 = tokens[cursor - 1];
147295
148227
  if (!open || open.kind !== "punctuation" || open.text !== "(") continue;
147296
- if (!method2 || method2.kind !== "identifier" || !lambdaMethods.has(method2.text)) {
148228
+ if (!method3 || method3.kind !== "identifier" || !lambdaMethods.has(method3.text)) {
147297
148229
  continue;
147298
148230
  }
147299
148231
  const dot = tokens[cursor - 2];
@@ -148647,7 +149579,7 @@ function projectAnnotationNamesAt(analysis, document, position) {
148647
149579
  "settings",
148648
149580
  "storage",
148649
149581
  "relations",
148650
- .../\bDialogue\b/.test(followingDeclaration[2] ?? "") ? ["incomplete"] : []
149582
+ .../\bNeoDialogue\b/.test(followingDeclaration[2] ?? "") ? ["incomplete"] : []
148651
149583
  ];
148652
149584
  }
148653
149585
  if (followingDeclaration) return ["id"];
@@ -148679,7 +149611,7 @@ function projectDeclarationAnnotationNames(declaration) {
148679
149611
  "settings",
148680
149612
  "storage",
148681
149613
  "relations",
148682
- ...declaration.baseTypes.some((type) => type.name === "Dialogue") ? ["incomplete"] : []
149614
+ ...declaration.baseTypes.some((type) => type.name === "NeoDialogue") ? ["incomplete"] : []
148683
149615
  ];
148684
149616
  }
148685
149617
  function projectMemberAnnotationNames(member) {
@@ -151050,7 +151982,7 @@ function dialogueGroupCompletions(analysis, document, position) {
151050
151982
  items.push({
151051
151983
  label: name,
151052
151984
  kind: "variable",
151053
- detail: "DialogueGroup",
151985
+ detail: "NeoDialogueGroup",
151054
151986
  insertText: name,
151055
151987
  symbolId: child2.id
151056
151988
  });
@@ -152966,10 +153898,10 @@ function readWorkspaceRecordFilesV4(workspace, dialogueGroupSymbols) {
152966
153898
  for (const absolute of listProjectSourceFilesV4(workspace.root)) {
152967
153899
  const path = relative4(workspace.root, absolute).split(sep4).join("/");
152968
153900
  const content = readFileSync11(absolute, "utf8");
152969
- if (dialogueGroupSymbols && /\bDialogueGroup\b/u.test(content) && neoProjectSourceKind(path, content) === "definition") {
153901
+ if (dialogueGroupSymbols && /\bNeoDialogueGroup\b/u.test(content) && neoProjectSourceKind(path, content) === "definition") {
152970
153902
  const source = parseNeoProjectSource(content, "definition", path);
152971
153903
  for (const declaration of source.declarations) {
152972
- if (declaration.kind !== "global" || declaration.type.name !== "DialogueGroup")
153904
+ if (declaration.kind !== "global" || declaration.type.name !== "NeoDialogueGroup")
152973
153905
  continue;
152974
153906
  const annotation2 = declaration.annotations.find(
152975
153907
  (item) => item.name === "id"
@@ -160559,11 +161491,8 @@ function dialogueGroupBaseClass(ctx, group, lookupType) {
160559
161491
  function dialogueGroupTriggerMethods(ctx, group, lookupType) {
160560
161492
  if (group.type === 0 /* Standard */) {
160561
161493
  return [
160562
- "public bool TryTrigger(out NeoDialogue dialogue) =>",
160563
- " TryTriggerStandard(out dialogue);",
160564
- "",
160565
- "public bool TryTrigger(out NeoDialogueTriggerResult result) =>",
160566
- " TryTriggerStandard(out result);"
161494
+ "public bool TryTrigger(Action? onFinish = null) =>",
161495
+ " TryTriggerStandard(onFinish);"
160567
161496
  ];
160568
161497
  }
160569
161498
  if (group.type !== 1 /* Lookup */) return [];
@@ -160573,11 +161502,8 @@ function dialogueGroupTriggerMethods(ctx, group, lookupType) {
160573
161502
  ];
160574
161503
  }
160575
161504
  return [
160576
- `public bool TryTrigger(${lookupType} value, out NeoDialogue dialogue) =>`,
160577
- " TryTriggerLookup(value, out dialogue);",
160578
- "",
160579
- `public bool TryTrigger(${lookupType} value, out NeoDialogueTriggerResult result) =>`,
160580
- " TryTriggerLookup(value, out result);"
161505
+ `public bool TryTrigger(${lookupType} value, Action? onFinish = null) =>`,
161506
+ " TryTriggerLookup(value, onFinish);"
160581
161507
  ];
160582
161508
  }
160583
161509
  function generateDialogueGroupProperty(ctx, group) {
@@ -160811,9 +161737,9 @@ function generateRelationTileGridContentClass(ctx, grid, saved) {
160811
161737
  ""
160812
161738
  ];
160813
161739
  const layerBindingExpression = (layer) => {
160814
- const method2 = `${saved ? "BindWritable" : "BindReadOnly"}${layer.kind === "tile" ? "Tile" : "Object"}Layer`;
161740
+ const method3 = `${saved ? "BindWritable" : "BindReadOnly"}${layer.kind === "tile" ? "Tile" : "Object"}Layer`;
160815
161741
  const imports = csharpStringArray(layer.importedClassIds);
160816
- return `primitive.${method2}<${layer.className}>("${escapeCSharpString(layer.layerClassId)}", ${imports})`;
161742
+ return `primitive.${method3}<${layer.className}>("${escapeCSharpString(layer.layerClassId)}", ${imports})`;
160817
161743
  };
160818
161744
  const privateConstructor = saved ? [
160819
161745
  `private ${className}(${primitiveType2} primitive)`,
@@ -161026,7 +161952,7 @@ function generateEnumClass(ctx, enumId) {
161026
161952
  ...indent([...arms, `_ => ${fallback},`]),
161027
161953
  "};"
161028
161954
  ];
161029
- const method2 = (signature, body) => [
161955
+ const method3 = (signature, body) => [
161030
161956
  signature,
161031
161957
  "{",
161032
161958
  ...indent(body),
@@ -161051,7 +161977,7 @@ function generateEnumClass(ctx, enumId) {
161051
161977
  `public static class ${optionsName}`,
161052
161978
  "{",
161053
161979
  ...indent([
161054
- ...method2(
161980
+ ...method3(
161055
161981
  `public static ${enumName} FromOptionId(string optionId)`,
161056
161982
  switchBody(
161057
161983
  "optionId",
@@ -161060,7 +161986,7 @@ function generateEnumClass(ctx, enumId) {
161060
161986
  )
161061
161987
  ),
161062
161988
  "",
161063
- ...method2(
161989
+ ...method3(
161064
161990
  `public static string OptionId(this ${enumName} value)`,
161065
161991
  switchBody(
161066
161992
  "value",
@@ -161069,7 +161995,7 @@ function generateEnumClass(ctx, enumId) {
161069
161995
  )
161070
161996
  ),
161071
161997
  "",
161072
- ...method2(
161998
+ ...method3(
161073
161999
  `public static string[] ToOptionIds(IEnumerable<${enumName}>? options)`,
161074
162000
  [
161075
162001
  "if (options is null) return Array.Empty<string>();",
@@ -161079,7 +162005,7 @@ function generateEnumClass(ctx, enumId) {
161079
162005
  ]
161080
162006
  ),
161081
162007
  "",
161082
- ...method2(
162008
+ ...method3(
161083
162009
  "public static bool IsKnown(string optionId)",
161084
162010
  switchBody(
161085
162011
  "optionId",
@@ -161088,7 +162014,7 @@ function generateEnumClass(ctx, enumId) {
161088
162014
  )
161089
162015
  ),
161090
162016
  "",
161091
- ...method2(
162017
+ ...method3(
161092
162018
  `public static string TextId(this ${enumName} value)`,
161093
162019
  switchBody(
161094
162020
  "value",
@@ -161097,7 +162023,7 @@ function generateEnumClass(ctx, enumId) {
161097
162023
  )
161098
162024
  ),
161099
162025
  "",
161100
- ...method2(
162026
+ ...method3(
161101
162027
  `public static string Text(this ${enumName} value, NeoClient? client = null)`,
161102
162028
  [
161103
162029
  ctx.singleton ? `return (client ?? ${ctx.projectClassName}.RequireInstance().Client).Localization.ResolveText(value.TextId());` : "return client is null ? value.TextId() : client.Localization.ResolveText(value.TextId());"
@@ -169024,6 +169950,28 @@ function addNeoScriptFunctionReferenceDiagnostics(args) {
169024
169950
  });
169025
169951
  return;
169026
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
+ }
169027
169975
  if (args.fn.type === "vectorConstructor" /* vectorConstructor */) {
169028
169976
  args.fn.info.componentPointers.forEach((pointer, index) => {
169029
169977
  addPointerReferenceDiagnostics({
@@ -169942,7 +170890,7 @@ var init_dialogue_diagnostics = __esm({
169942
170890
  init_interface_types();
169943
170891
  init_interface_graph();
169944
170892
  init_neoscript();
169945
- init_dialogue_types();
170893
+ init_dialogue_types2();
169946
170894
  init_dialogue_group_types();
169947
170895
  init_logic_types();
169948
170896
  init_core();
@@ -170711,7 +171659,7 @@ var init_project_unity_export_diagnostics = __esm({
170711
171659
  "use strict";
170712
171660
  init_project_world_placement_bindings();
170713
171661
  init_dialogue_diagnostics();
170714
- init_dialogue_types();
171662
+ init_dialogue_types2();
170715
171663
  init_members();
170716
171664
  init_core_types();
170717
171665
  init_inheritance();
@@ -170733,7 +171681,7 @@ var UNITY_CODEGEN_REVISION;
170733
171681
  var init_unity_codegen_revision = __esm({
170734
171682
  "../src/models/exports/unity-codegen-revision.ts"() {
170735
171683
  "use strict";
170736
- UNITY_CODEGEN_REVISION = "45a0847addd4616acfc29f142556dcb2e0a27daae14d6aa456430228e66dbc07";
171684
+ UNITY_CODEGEN_REVISION = "e4a632a177c87244e19da71c9840b8007735773ae5f81578f58ce246ec6cb03d";
170737
171685
  }
170738
171686
  });
170739
171687
 
@@ -170743,7 +171691,7 @@ var init_project_unity_export_types = __esm({
170743
171691
  "../src/models/exports/project-unity-export-types.ts"() {
170744
171692
  "use strict";
170745
171693
  init_unity_codegen_revision();
170746
- PROJECT_UNITY_EXPORT_SCHEMA_VERSION = 38;
171694
+ PROJECT_UNITY_EXPORT_SCHEMA_VERSION = 39;
170747
171695
  }
170748
171696
  });
170749
171697
 
@@ -175796,6 +176744,7 @@ async function buildPostPushCompileSchema(workspace, status) {
175796
176744
  return {
175797
176745
  project,
175798
176746
  projectFiles: [...bucket("project-file").values()],
176747
+ dialogueGroups: [...bucket("dialogue-group").values()],
175799
176748
  members: [...bucket("member").values()],
175800
176749
  classes: [...bucket("class").values()],
175801
176750
  constructors: [...bucket("constructor").values()],
@@ -175809,6 +176758,7 @@ function createPostPushCompileContext(schema) {
175809
176758
  const project = {
175810
176759
  project: schema.project,
175811
176760
  projectFiles: schema.projectFiles,
176761
+ dialogueGroups: schema.dialogueGroups ?? [],
175812
176762
  members: schema.members,
175813
176763
  classes: schema.classes,
175814
176764
  constructors: schema.constructors,
@@ -179557,6 +180507,7 @@ function createCliNeoScriptContext(options) {
179557
180507
  const vm = {
179558
180508
  project: options.documents.project,
179559
180509
  projectFiles: [...options.documents.projectFiles ?? []],
180510
+ dialogueGroups: [...options.documents.dialogueGroups ?? []],
179560
180511
  members,
179561
180512
  classes: [...options.documents.classes],
179562
180513
  enums: [...options.documents.enums],
@@ -179583,10 +180534,25 @@ function createCliNeoScriptContext(options) {
179583
180534
  // root placement is server context, not authored schema-manifest state.
179584
180535
  roots: compilerContext.project.roots,
179585
180536
  globals: compilerContext.project.globals,
179586
- version: compilerContext.project.version
180537
+ version: compilerContext.project.version,
180538
+ dialogueGroups: cliDialogueGroupSources(options.documents)
179587
180539
  });
179588
180540
  return { ...compilerContext, project: projection.project };
179589
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
+ }
179590
180556
  async function validateCliNeoScript(uri, source, context) {
179591
180557
  const service = createCliNeoScriptLanguageService();
179592
180558
  const document = {
@@ -179643,7 +180609,8 @@ function createCliManifestScriptContext(manifest, scriptPath2, unit, options = {
179643
180609
  const projectedManifest = manifestWithUniqueInlineScriptKeys(manifest);
179644
180610
  const projection = projectSchemaManifest(projectedManifest, {
179645
180611
  ...options.rootMemberIds ? { rootMemberIds: options.rootMemberIds } : {},
179646
- ...options.sourceUri ? { sourceUri: options.sourceUri } : {}
180612
+ ...options.sourceUri ? { sourceUri: options.sourceUri } : {},
180613
+ ...options.dialogueGroups ? { dialogueGroups: options.dialogueGroups } : {}
179647
180614
  });
179648
180615
  const normalizedPath = options.memberId === void 0 ? normalizeWorkspacePath(scriptPath2) : inlineScriptKey(scriptPath2, options.memberId);
179649
180616
  const script = projection.scripts.get(normalizedPath);
@@ -179691,7 +180658,8 @@ function analyzeManifestScripts(manifest, options = {}) {
179691
180658
  const projectedManifest = manifestWithUniqueInlineScriptKeys(manifest);
179692
180659
  const projection = projectSchemaManifest(projectedManifest, {
179693
180660
  ...options.rootMemberIds ? { rootMemberIds: options.rootMemberIds } : {},
179694
- ...options.sourceUri ? { sourceUri: options.sourceUri } : {}
180661
+ ...options.sourceUri ? { sourceUri: options.sourceUri } : {},
180662
+ ...options.dialogueGroups ? { dialogueGroups: options.dialogueGroups } : {}
179695
180663
  });
179696
180664
  const sources2 = /* @__PURE__ */ new Map();
179697
180665
  const scriptPathByMemberId = /* @__PURE__ */ new Map();
@@ -179773,6 +180741,7 @@ var init_neoscript_language_adapter = __esm({
179773
180741
  init_service();
179774
180742
  init_strict_ir();
179775
180743
  init_neoscript_language_context_adapter();
180744
+ init_dialogue_group_language();
179776
180745
  }
179777
180746
  });
179778
180747
 
@@ -180745,7 +181714,8 @@ async function runScript(workspace, command, options, dependencies = {}) {
180745
181714
  localCheckManifest,
180746
181715
  localTarget,
180747
181716
  command,
180748
- options
181717
+ options,
181718
+ localCheckDocument === null ? [] : cliDialogueGroupSources(localCheckDocument)
180749
181719
  );
180750
181720
  return;
180751
181721
  }
@@ -180796,6 +181766,7 @@ async function runScript(workspace, command, options, dependencies = {}) {
180796
181766
  const compilerProject = {
180797
181767
  project: document.project,
180798
181768
  projectFiles: document.projectFiles,
181769
+ dialogueGroups: document.dialogueGroups,
180799
181770
  members: document.members,
180800
181771
  classes: document.classes,
180801
181772
  constructors: document.constructors,
@@ -180968,6 +181939,7 @@ async function runScript(workspace, command, options, dependencies = {}) {
180968
181939
  variants: document.variants,
180969
181940
  variantFolders: document.variantFolders,
180970
181941
  projectFiles: document.projectFiles,
181942
+ dialogueGroups: document.dialogueGroups,
180971
181943
  textureTemplates: document.textureTemplates,
180972
181944
  localizationConfig: document.localizationConfig,
180973
181945
  localizedTexts: document.localizedTexts,
@@ -181430,7 +182402,7 @@ function localMemberOwnerKeys(member) {
181430
182402
  }
181431
182403
  return [];
181432
182404
  }
181433
- async function runLocalTargetCommand(manifest, target, command, options) {
182405
+ async function runLocalTargetCommand(manifest, target, command, options, dialogueGroups) {
181434
182406
  const member = target.member;
181435
182407
  const script = member.script;
181436
182408
  if (script === null) {
@@ -181485,6 +182457,7 @@ async function runLocalTargetCommand(manifest, target, command, options) {
181485
182457
  const source = readSource(options, fallback);
181486
182458
  const context = createCliManifestScriptContext(manifest, script.path, unit, {
181487
182459
  memberId: member.id,
182460
+ dialogueGroups,
181488
182461
  ...target.receiverClassId && member.modifier !== "static" ? { receiverClassId: target.receiverClassId } : {}
181489
182462
  });
181490
182463
  const diagnostics = await validateCliNeoScript(
@@ -181546,11 +182519,11 @@ async function runLocalTargetCommand(manifest, target, command, options) {
181546
182519
  options.json ? JSON.stringify({ ...report, ...functionMetadata }, null, 2) : "Compiles cleanly."
181547
182520
  );
181548
182521
  }
181549
- function collectLocalCheckAll(manifest, options) {
182522
+ function collectLocalCheckAll(manifest, options, dialogueGroups) {
181550
182523
  const membersById = new Map(
181551
182524
  manifest.members.filter(isLocalScriptMember).map((member) => [member.id, member])
181552
182525
  );
181553
- const analyses = analyzeManifestScripts(manifest);
182526
+ const analyses = analyzeManifestScripts(manifest, { dialogueGroups });
181554
182527
  const results = analyses.map((analysis) => {
181555
182528
  const member = membersById.get(analysis.memberId);
181556
182529
  if (member === void 0) {
@@ -181588,7 +182561,11 @@ function localScriptUri(path) {
181588
182561
  return `neo-script:///${normalizeScriptPath(path).split("/").map((part) => encodeURIComponent(part)).join("/")}`;
181589
182562
  }
181590
182563
  function runCheckAll(document, manifest, options) {
181591
- const local = collectLocalCheckAll(manifest, options);
182564
+ const local = collectLocalCheckAll(
182565
+ manifest,
182566
+ options,
182567
+ cliDialogueGroupSources(document)
182568
+ );
181592
182569
  let failures = local.failures;
181593
182570
  let checked = local.checked;
181594
182571
  const results = [...local.results];
@@ -181681,7 +182658,7 @@ var init_script = __esm({
181681
182658
  init_save_overlay_resolution();
181682
182659
  init_members();
181683
182660
  init_neoscript();
181684
- init_dialogue_types();
182661
+ init_dialogue_types2();
181685
182662
  init_logic_types();
181686
182663
  init_dialogue_logic_compile_pure();
181687
182664
  init_project_migration_runner();
@@ -181889,6 +182866,7 @@ function sharedEvaluatorBase(rawDocument) {
181889
182866
  variants: document.variants,
181890
182867
  variantFolders: document.variantFolders,
181891
182868
  projectFiles: document.projectFiles,
182869
+ dialogueGroups: document.dialogueGroups,
181892
182870
  textureTemplates: document.textureTemplates,
181893
182871
  localizationConfig: document.localizationConfig,
181894
182872
  localizedTexts: document.localizedTexts,
@@ -185017,6 +185995,7 @@ async function runPendingMigrations(workspace, fetched, migrations, onlyRef) {
185017
185995
  () => compileNSVoidBody(migrationCode, {
185018
185996
  project: document.project,
185019
185997
  projectFiles: document.projectFiles,
185998
+ dialogueGroups: document.dialogueGroups,
185020
185999
  members: document.members,
185021
186000
  classes: document.classes,
185022
186001
  constructors: document.constructors,
@@ -185061,6 +186040,7 @@ async function runPendingMigrations(workspace, fetched, migrations, onlyRef) {
185061
186040
  classes: document.classes,
185062
186041
  enums: document.enums,
185063
186042
  projectFiles: document.projectFiles,
186043
+ dialogueGroups: document.dialogueGroups,
185064
186044
  localizationConfig: document.localizationConfig,
185065
186045
  localizedTexts: document.localizedTexts,
185066
186046
  ...runtime
@@ -186837,7 +187817,7 @@ var init_dialogue_lookup_candidates = __esm({
186837
187817
  var init_dialogue_record_split = __esm({
186838
187818
  "../src/models/dialogue/dialogue-record-split.ts"() {
186839
187819
  "use strict";
186840
- init_dialogue_types();
187820
+ init_dialogue_types2();
186841
187821
  }
186842
187822
  });
186843
187823
 
@@ -186847,7 +187827,7 @@ var init_dialogue_localized_text_links = __esm({
186847
187827
  "use strict";
186848
187828
  init_localized_text_create_envelope();
186849
187829
  init_localization_types();
186850
- init_dialogue_types();
187830
+ init_dialogue_types2();
186851
187831
  }
186852
187832
  });
186853
187833
 
@@ -186882,7 +187862,7 @@ var init_dialogue_triggering = __esm({
186882
187862
  var init_dialogue = __esm({
186883
187863
  "../src/models/dialogue/index.ts"() {
186884
187864
  "use strict";
186885
- init_dialogue_types();
187865
+ init_dialogue_types2();
186886
187866
  init_dialogue_source_identifiers();
186887
187867
  init_dialogue_source_names();
186888
187868
  init_dialogue_lookup_candidates();
@@ -188847,6 +189827,7 @@ function buildWorld(document, raw) {
188847
189827
  variants: document.variants,
188848
189828
  variantFolders: document.variantFolders,
188849
189829
  projectFiles: document.projectFiles,
189830
+ dialogueGroups: document.dialogueGroups,
188850
189831
  localizationConfig: document.localizationConfig,
188851
189832
  localizedTexts: document.localizedTexts,
188852
189833
  ...runtime
@@ -190443,7 +191424,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
190443
191424
  async function main() {
190444
191425
  const args = parseArgs(process.argv.slice(2));
190445
191426
  if (args.command === "--version") {
190446
- console.log("0.72.2");
191427
+ console.log("0.73.0");
190447
191428
  return;
190448
191429
  }
190449
191430
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {