forked from Shardstone/trail-into-darkness
Some encounter testing and working
This commit is contained in:
@@ -12,7 +12,7 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: c47caaa92bb94eeca3e47dd86fd010cf, type: 3}
|
m_Script: {fileID: 11500000, guid: c47caaa92bb94eeca3e47dd86fd010cf, type: 3}
|
||||||
m_Name: Dialog_Set_0
|
m_Name: Dialog_Set_0
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.EncounterDialogOptionSet
|
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.EncounterDialogOptionSet
|
||||||
id: Dialog_Set_1
|
id: Dialog_Set_0
|
||||||
library: {fileID: 11400000, guid: 11b94daa76442834198b68996afe0013, type: 2}
|
library: {fileID: 11400000, guid: 11b94daa76442834198b68996afe0013, type: 2}
|
||||||
options:
|
options:
|
||||||
- text:
|
- text:
|
||||||
|
|||||||
@@ -15,43 +15,25 @@ MonoBehaviour:
|
|||||||
id: TestEncounterTable
|
id: TestEncounterTable
|
||||||
encounters:
|
encounters:
|
||||||
- <EncounterDefinition>k__BackingField:
|
- <EncounterDefinition>k__BackingField:
|
||||||
internalId: adce0a09-6402-4c2e-b24a-db7c9c67e3e5
|
internalId: 169489f1-892d-475b-8c32-fc760da28929
|
||||||
id: test_quest_1
|
id: simple_puzzle
|
||||||
name: Test Quest Stage I
|
name: Fix a Broken Cart
|
||||||
description: An encounter like no other which leads to another encounter like
|
description: 'You encounter a broken cart. At a closer examination you chose
|
||||||
no other
|
to:'
|
||||||
|
<Kind>k__BackingField:
|
||||||
|
rid: 1352971465325281422
|
||||||
<EncounterProperties>k__BackingField:
|
<EncounterProperties>k__BackingField:
|
||||||
difficulty: 0
|
difficulty: 0
|
||||||
<EncounterVisuals>k__BackingField:
|
<EncounterVisuals>k__BackingField:
|
||||||
icon: {fileID: 21300000, guid: ea02ea44fa86ee445be0f7ca82098b75, type: 3}
|
icon: {fileID: 0}
|
||||||
encounterColor: {r: 0, g: 0, b: 0, a: 0}
|
encounterColor: {r: 0, g: 0, b: 0, a: 0}
|
||||||
encounterArt: {fileID: 21300000, guid: a9c4c7681315e25419b9381d28aa9d80, type: 3}
|
encounterArt: {fileID: 0}
|
||||||
<EncounterDialogOptionSet>k__BackingField: {fileID: 11400000, guid: 9496570aa3d05624a9b8bbbf6009c453, type: 2}
|
<EncounterDialogOptionSet>k__BackingField: {fileID: 0}
|
||||||
<Kind>k__BackingField:
|
|
||||||
rid: 1352971465325281411
|
|
||||||
- <EncounterDefinition>k__BackingField:
|
|
||||||
internalId: adce0a09-6402-4c2e-b24a-db7c9c67e3e5
|
|
||||||
id: test_quest_2
|
|
||||||
name: Test Quest Stage II
|
|
||||||
description: An encounter like no other which should be now completed
|
|
||||||
<EncounterProperties>k__BackingField:
|
|
||||||
difficulty: 0
|
|
||||||
<EncounterVisuals>k__BackingField:
|
|
||||||
icon: {fileID: 21300000, guid: ea02ea44fa86ee445be0f7ca82098b75, type: 3}
|
|
||||||
encounterColor: {r: 0, g: 0, b: 0, a: 0}
|
|
||||||
encounterArt: {fileID: 21300000, guid: 819d7a244820ad84585a1de7566bf9d0, type: 3}
|
|
||||||
<EncounterDialogOptionSet>k__BackingField: {fileID: 11400000, guid: 9496570aa3d05624a9b8bbbf6009c453, type: 2}
|
|
||||||
<Kind>k__BackingField:
|
|
||||||
rid: -2
|
|
||||||
references:
|
references:
|
||||||
version: 2
|
version: 2
|
||||||
RefIds:
|
RefIds:
|
||||||
- rid: -2
|
- rid: 1352971465325281422
|
||||||
type: {class: , ns: , asm: }
|
type: {class: PuzzleKind, ns: Jovian.EncounterSystem, asm: Jovian.EncounterSystem}
|
||||||
- rid: 1352971465325281411
|
|
||||||
type: {class: QuestKind, ns: Jovian.EncounterSystem, asm: Jovian.EncounterSystem}
|
|
||||||
data:
|
data:
|
||||||
nextEncounter:
|
puzzleId: borken_cart
|
||||||
table: {fileID: 11400000}
|
difficultyClass: 1
|
||||||
internalId: adce0a09-6402-4c2e-b24a-db7c9c67e3e5
|
|
||||||
questTitle:
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 396a5409178bf0d4b938094eefe22cca
|
guid: 0d6735c0d1617b243a1f6c8c5070028c
|
||||||
NativeFormatImporter:
|
NativeFormatImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 11400000
|
mainObjectFileID: 11400000
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: e480a30007b949679b8ca1e0e6088675, type: 3}
|
||||||
|
m_Name: TestQuestTable
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.EncounterTable
|
||||||
|
id: TestEncounterTable
|
||||||
|
encounters:
|
||||||
|
- <EncounterDefinition>k__BackingField:
|
||||||
|
internalId: adce0a09-6402-4c2e-b24a-db7c9c67e3e5
|
||||||
|
id: test_quest_1
|
||||||
|
name: Test Quest Stage I
|
||||||
|
description: An encounter like no other which leads to another encounter like
|
||||||
|
no other
|
||||||
|
<Kind>k__BackingField:
|
||||||
|
rid: 1352971465325281417
|
||||||
|
<EncounterProperties>k__BackingField:
|
||||||
|
difficulty: 0
|
||||||
|
<EncounterVisuals>k__BackingField:
|
||||||
|
icon: {fileID: 21300000, guid: ea02ea44fa86ee445be0f7ca82098b75, type: 3}
|
||||||
|
encounterColor: {r: 0, g: 0, b: 0, a: 0}
|
||||||
|
encounterArt: {fileID: 21300000, guid: a9c4c7681315e25419b9381d28aa9d80, type: 3}
|
||||||
|
<EncounterDialogOptionSet>k__BackingField: {fileID: 11400000, guid: 9496570aa3d05624a9b8bbbf6009c453, type: 2}
|
||||||
|
- <EncounterDefinition>k__BackingField:
|
||||||
|
internalId: 882ecaa9-29d9-452e-aa88-beb533f97882
|
||||||
|
id: test_quest_2
|
||||||
|
name: Test Quest Stage II
|
||||||
|
description: An encounter like no other which should be now completed
|
||||||
|
<Kind>k__BackingField:
|
||||||
|
rid: 1352971465325281421
|
||||||
|
<EncounterProperties>k__BackingField:
|
||||||
|
difficulty: 0
|
||||||
|
<EncounterVisuals>k__BackingField:
|
||||||
|
icon: {fileID: 21300000, guid: ea02ea44fa86ee445be0f7ca82098b75, type: 3}
|
||||||
|
encounterColor: {r: 0, g: 0, b: 0, a: 0}
|
||||||
|
encounterArt: {fileID: 21300000, guid: 819d7a244820ad84585a1de7566bf9d0, type: 3}
|
||||||
|
<EncounterDialogOptionSet>k__BackingField: {fileID: 11400000, guid: 9496570aa3d05624a9b8bbbf6009c453, type: 2}
|
||||||
|
references:
|
||||||
|
version: 2
|
||||||
|
RefIds:
|
||||||
|
- rid: 1352971465325281417
|
||||||
|
type: {class: QuestKind, ns: Jovian.EncounterSystem, asm: Jovian.EncounterSystem}
|
||||||
|
data:
|
||||||
|
nextEncounter:
|
||||||
|
table: {fileID: 11400000}
|
||||||
|
internalId: 882ecaa9-29d9-452e-aa88-beb533f97882
|
||||||
|
questTitle:
|
||||||
|
- rid: 1352971465325281421
|
||||||
|
type: {class: QuestKind, ns: Jovian.EncounterSystem, asm: Jovian.EncounterSystem}
|
||||||
|
data:
|
||||||
|
nextEncounter:
|
||||||
|
table: {fileID: 0}
|
||||||
|
internalId:
|
||||||
|
questTitle:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 396a5409178bf0d4b938094eefe22cca
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -14,3 +14,4 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.EncountersCollection
|
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.EncountersCollection
|
||||||
encounterTables:
|
encounterTables:
|
||||||
- {fileID: 11400000, guid: 396a5409178bf0d4b938094eefe22cca, type: 2}
|
- {fileID: 11400000, guid: 396a5409178bf0d4b938094eefe22cca, type: 2}
|
||||||
|
- {fileID: 11400000, guid: 0d6735c0d1617b243a1f6c8c5070028c, type: 2}
|
||||||
|
|||||||
@@ -16,8 +16,19 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
public EncounterTable table;
|
public EncounterTable table;
|
||||||
public int index;
|
public int index;
|
||||||
public IEncounter encounter;
|
public IEncounter encounter;
|
||||||
|
public int depth;
|
||||||
|
|
||||||
|
public bool IsTableHeader => encounter == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly Color[] DepthColors = {
|
||||||
|
new(0.35f, 0.55f, 0.85f), // depth 0 — table headers (blue)
|
||||||
|
new(0.90f, 0.90f, 0.90f), // depth 1 — encounters under table (neutral)
|
||||||
|
new(0.70f, 0.90f, 0.55f), // depth 2 — chain step 1 (green)
|
||||||
|
new(0.95f, 0.80f, 0.45f), // depth 3 — chain step 2 (amber)
|
||||||
|
new(0.85f, 0.65f, 0.90f) // depth 4+ — deeper chain (violet)
|
||||||
|
};
|
||||||
|
|
||||||
private readonly List<Record> allRecords = new();
|
private readonly List<Record> allRecords = new();
|
||||||
private string searchText = string.Empty;
|
private string searchText = string.Empty;
|
||||||
private string kindFilter = AllKinds;
|
private string kindFilter = AllKinds;
|
||||||
@@ -27,6 +38,7 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
private TreeView treeView;
|
private TreeView treeView;
|
||||||
private VisualElement detailPane;
|
private VisualElement detailPane;
|
||||||
private ToolbarMenu kindDropdown;
|
private ToolbarMenu kindDropdown;
|
||||||
|
private VisualElement statusBanner;
|
||||||
|
|
||||||
[MenuItem("Jovian/Encounters/Encounter Browser")]
|
[MenuItem("Jovian/Encounters/Encounter Browser")]
|
||||||
public static void Open() {
|
public static void Open() {
|
||||||
@@ -69,8 +81,26 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void BuildSplit() {
|
private void BuildSplit() {
|
||||||
var split = new TwoPaneSplitView(0, 280, TwoPaneSplitViewOrientation.Horizontal);
|
statusBanner = new VisualElement {
|
||||||
split.style.flexGrow = 1f;
|
style = {
|
||||||
|
paddingLeft = 10,
|
||||||
|
paddingRight = 10,
|
||||||
|
paddingTop = 8,
|
||||||
|
paddingBottom = 8,
|
||||||
|
marginBottom = 2,
|
||||||
|
flexDirection = FlexDirection.Column,
|
||||||
|
backgroundColor = new StyleColor(new Color(0.85f, 0.4f, 0.15f, 0.35f)),
|
||||||
|
display = DisplayStyle.None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
rootVisualElement.Add(statusBanner);
|
||||||
|
|
||||||
|
var split = new VisualElement {
|
||||||
|
style = {
|
||||||
|
flexDirection = FlexDirection.Row,
|
||||||
|
flexGrow = 1f
|
||||||
|
}
|
||||||
|
};
|
||||||
rootVisualElement.Add(split);
|
rootVisualElement.Add(split);
|
||||||
|
|
||||||
treeView = new TreeView {
|
treeView = new TreeView {
|
||||||
@@ -80,7 +110,10 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
selectionType = SelectionType.Single
|
selectionType = SelectionType.Single
|
||||||
};
|
};
|
||||||
treeView.selectionChanged += OnSelectionChanged;
|
treeView.selectionChanged += OnSelectionChanged;
|
||||||
treeView.style.flexGrow = 1f;
|
treeView.style.width = 280;
|
||||||
|
treeView.style.flexShrink = 0f;
|
||||||
|
treeView.style.borderRightWidth = 1;
|
||||||
|
treeView.style.borderRightColor = new StyleColor(new Color(0f, 0f, 0f, 0.4f));
|
||||||
split.Add(treeView);
|
split.Add(treeView);
|
||||||
|
|
||||||
detailPane = new ScrollView(ScrollViewMode.Vertical) {
|
detailPane = new ScrollView(ScrollViewMode.Vertical) {
|
||||||
@@ -97,7 +130,9 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
alignItems = Align.Center,
|
alignItems = Align.Center,
|
||||||
paddingLeft = 6,
|
paddingLeft = 6,
|
||||||
paddingRight = 6,
|
paddingRight = 6,
|
||||||
height = 22
|
height = 22,
|
||||||
|
flexGrow = 1f,
|
||||||
|
flexShrink = 0f
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -125,6 +160,19 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
};
|
};
|
||||||
row.Add(label);
|
row.Add(label);
|
||||||
|
|
||||||
|
var selectButton = new Button {
|
||||||
|
name = "select-button",
|
||||||
|
text = "Select",
|
||||||
|
style = {
|
||||||
|
marginLeft = 4,
|
||||||
|
marginRight = 0,
|
||||||
|
paddingLeft = 6,
|
||||||
|
paddingRight = 6,
|
||||||
|
display = DisplayStyle.None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
row.Add(selectButton);
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,9 +180,34 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
var record = treeView.GetItemDataForIndex<Record>(index);
|
var record = treeView.GetItemDataForIndex<Record>(index);
|
||||||
var label = element.Q<Label>("row-label");
|
var label = element.Q<Label>("row-label");
|
||||||
var badge = element.Q<VisualElement>("issue-badge");
|
var badge = element.Q<VisualElement>("issue-badge");
|
||||||
|
var selectButton = element.Q<Button>("select-button");
|
||||||
|
|
||||||
|
var depthIndex = Mathf.Clamp(record.depth, 0, DepthColors.Length - 1);
|
||||||
|
label.style.color = new StyleColor(DepthColors[depthIndex]);
|
||||||
|
|
||||||
|
if(record.IsTableHeader) {
|
||||||
|
label.text = record.table != null ? record.table.name : "<missing table>";
|
||||||
|
label.style.unityFontStyleAndWeight = FontStyle.Bold;
|
||||||
|
badge.style.visibility = Visibility.Hidden;
|
||||||
|
element.tooltip = $"EncounterTable asset: {record.table?.name}";
|
||||||
|
|
||||||
|
selectButton.style.display = DisplayStyle.Flex;
|
||||||
|
var table = record.table;
|
||||||
|
selectButton.clickable = new Clickable(() => {
|
||||||
|
if(table == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Selection.activeObject = table;
|
||||||
|
EditorGUIUtility.PingObject(table);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
label.style.unityFontStyleAndWeight = FontStyle.Normal;
|
||||||
|
selectButton.style.display = DisplayStyle.None;
|
||||||
|
|
||||||
var name = record.encounter?.EncounterDefinition?.name;
|
var name = record.encounter?.EncounterDefinition?.name;
|
||||||
var kind = record.encounter?.Kind?.GetType().Name ?? "—";
|
var kind = record.encounter?.EncounterDefinition?.Kind?.GetType().Name ?? "—";
|
||||||
label.text = string.IsNullOrEmpty(name)
|
label.text = string.IsNullOrEmpty(name)
|
||||||
? $"<unnamed> [{kind}]"
|
? $"<unnamed> [{kind}]"
|
||||||
: $"{name} [{kind}]";
|
: $"{name} [{kind}]";
|
||||||
@@ -180,20 +253,33 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
private void Refresh() {
|
private void Refresh() {
|
||||||
allRecords.Clear();
|
allRecords.Clear();
|
||||||
|
|
||||||
var guids = AssetDatabase.FindAssets("t:" + nameof(EncounterTable));
|
var registries = FindAssetsOfType<EncounterRegistry>().ToList();
|
||||||
foreach(var guid in guids) {
|
UpdateStatusBanner(registries);
|
||||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
|
||||||
var table = AssetDatabase.LoadAssetAtPath<EncounterTable>(path);
|
var seenTables = new HashSet<EncounterTable>();
|
||||||
if(table?.encounters == null) {
|
foreach(var registry in registries) {
|
||||||
|
if(registry?.encounterCollections == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < table.encounters.Count; i++) {
|
foreach(var collection in registry.encounterCollections) {
|
||||||
allRecords.Add(new Record {
|
if(collection?.encounterTables == null) {
|
||||||
table = table,
|
continue;
|
||||||
index = i,
|
}
|
||||||
encounter = table.encounters[i]
|
|
||||||
});
|
foreach(var table in collection.encounterTables) {
|
||||||
|
if(table?.encounters == null || !seenTables.Add(table)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var i = 0; i < table.encounters.Count; i++) {
|
||||||
|
allRecords.Add(new Record {
|
||||||
|
table = table,
|
||||||
|
index = i,
|
||||||
|
encounter = table.encounters[i]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,6 +287,72 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
ApplyFilter();
|
ApplyFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateStatusBanner(List<EncounterRegistry> registries) {
|
||||||
|
statusBanner.Clear();
|
||||||
|
|
||||||
|
if(registries.Count == 0) {
|
||||||
|
statusBanner.style.display = DisplayStyle.Flex;
|
||||||
|
statusBanner.Add(new Label("No EncounterRegistry asset found. The browser reads encounters from the registry — without one, it has nothing to show.") {
|
||||||
|
style = { marginBottom = 6, whiteSpace = WhiteSpace.Normal }
|
||||||
|
});
|
||||||
|
statusBanner.Add(new Button(CreateRegistryInteractive) {
|
||||||
|
text = "Create Registry…",
|
||||||
|
style = { alignSelf = Align.FlexStart }
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var emptyRegistries = registries.FindAll(r => r?.encounterCollections == null || r.encounterCollections.Length == 0);
|
||||||
|
if(emptyRegistries.Count == registries.Count) {
|
||||||
|
statusBanner.style.display = DisplayStyle.Flex;
|
||||||
|
statusBanner.Add(new Label("Registry found but no EncountersCollection is assigned to its 'encounterCollections' array.") {
|
||||||
|
style = { whiteSpace = WhiteSpace.Normal }
|
||||||
|
});
|
||||||
|
var pingButton = new Button(() => {
|
||||||
|
Selection.activeObject = registries[0];
|
||||||
|
EditorGUIUtility.PingObject(registries[0]);
|
||||||
|
}) {
|
||||||
|
text = "Open Registry",
|
||||||
|
style = { alignSelf = Align.FlexStart, marginTop = 6 }
|
||||||
|
};
|
||||||
|
statusBanner.Add(pingButton);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
statusBanner.style.display = DisplayStyle.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateRegistryInteractive() {
|
||||||
|
var path = EditorUtility.SaveFilePanelInProject(
|
||||||
|
"Create Encounter Registry",
|
||||||
|
"EncounterRegistry",
|
||||||
|
"asset",
|
||||||
|
"Choose where to save the new EncounterRegistry asset.");
|
||||||
|
if(string.IsNullOrEmpty(path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var registry = ScriptableObject.CreateInstance<EncounterRegistry>();
|
||||||
|
AssetDatabase.CreateAsset(registry, path);
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
|
||||||
|
Selection.activeObject = registry;
|
||||||
|
EditorGUIUtility.PingObject(registry);
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<T> FindAssetsOfType<T>() where T : UnityEngine.Object {
|
||||||
|
var guids = AssetDatabase.FindAssets("t:" + typeof(T).Name);
|
||||||
|
foreach(var guid in guids) {
|
||||||
|
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||||
|
var asset = AssetDatabase.LoadAssetAtPath<T>(path);
|
||||||
|
if(asset != null) {
|
||||||
|
yield return asset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void RebuildIssueIndex() {
|
private void RebuildIssueIndex() {
|
||||||
issuesByEncounter.Clear();
|
issuesByEncounter.Clear();
|
||||||
var issues = EncounterValidator.ValidateProject();
|
var issues = EncounterValidator.ValidateProject();
|
||||||
@@ -219,16 +371,46 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
private void ApplyFilter() {
|
private void ApplyFilter() {
|
||||||
var filtered = allRecords.Where(Matches).ToList();
|
var filtered = allRecords.Where(Matches).ToList();
|
||||||
var items = BuildTreeItems(filtered);
|
var items = BuildTreeItems(filtered);
|
||||||
if(treeView != null) {
|
if(treeView == null) {
|
||||||
treeView.SetRootItems(items);
|
return;
|
||||||
treeView.Rebuild();
|
|
||||||
treeView.ClearSelection();
|
|
||||||
treeView.ExpandAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
treeView.ClearSelection();
|
||||||
|
treeView.SetRootItems(items);
|
||||||
|
treeView.Rebuild();
|
||||||
|
// Expand after layout settles — ExpandAll immediately after Rebuild can no-op in some cases.
|
||||||
|
treeView.schedule.Execute(() => treeView.ExpandAll()).ExecuteLater(0);
|
||||||
ShowEmptyDetail();
|
ShowEmptyDetail();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<TreeViewItemData<Record>> BuildTreeItems(List<Record> records) {
|
private static List<TreeViewItemData<Record>> BuildTreeItems(List<Record> records) {
|
||||||
|
// Group by table: each table becomes a top-level row, its encounters nest under it.
|
||||||
|
var byTable = new Dictionary<EncounterTable, List<Record>>();
|
||||||
|
var tableOrder = new List<EncounterTable>();
|
||||||
|
foreach(var r in records) {
|
||||||
|
if(r.table == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(!byTable.TryGetValue(r.table, out var list)) {
|
||||||
|
list = new List<Record>();
|
||||||
|
byTable[r.table] = list;
|
||||||
|
tableOrder.Add(r.table);
|
||||||
|
}
|
||||||
|
list.Add(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = new List<TreeViewItemData<Record>>();
|
||||||
|
var uid = 0;
|
||||||
|
foreach(var table in tableOrder) {
|
||||||
|
var tableRecord = new Record { table = table, index = -1, encounter = null, depth = 0 };
|
||||||
|
var tableId = uid++;
|
||||||
|
var children = BuildEncounterNodes(byTable[table], 1, ref uid);
|
||||||
|
result.Add(new TreeViewItemData<Record>(tableId, tableRecord, children));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<TreeViewItemData<Record>> BuildEncounterNodes(List<Record> records, int depth, ref int uid) {
|
||||||
var byEncounter = new Dictionary<IEncounter, Record>();
|
var byEncounter = new Dictionary<IEncounter, Record>();
|
||||||
foreach(var r in records) {
|
foreach(var r in records) {
|
||||||
if(r.encounter != null) {
|
if(r.encounter != null) {
|
||||||
@@ -236,41 +418,81 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any encounter that is a `nextEncounter` target of another record in the filtered set
|
// Chain nesting only applies to chains contained within this table. Cross-table chains
|
||||||
// becomes a non-root (rendered as a child), not a top-level item.
|
// naturally appear flat (the target encounter lives under its own table header).
|
||||||
var nonRoot = new HashSet<IEncounter>();
|
var predecessorCount = new Dictionary<IEncounter, int>();
|
||||||
foreach(var r in records) {
|
foreach(var r in records) {
|
||||||
if(r.encounter?.Kind is not QuestKind quest) {
|
if(r.encounter?.EncounterDefinition?.Kind is not QuestKind quest) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var next = quest.nextEncounter.Resolve();
|
var next = quest.nextEncounter.Resolve();
|
||||||
if(next != null && byEncounter.ContainsKey(next)) {
|
if(next != null && byEncounter.ContainsKey(next)) {
|
||||||
nonRoot.Add(next);
|
predecessorCount.TryGetValue(next, out var count);
|
||||||
|
predecessorCount[next] = count + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = new List<TreeViewItemData<Record>>();
|
var parentOf = new Dictionary<IEncounter, IEncounter>();
|
||||||
var uid = 0;
|
|
||||||
foreach(var r in records) {
|
foreach(var r in records) {
|
||||||
if(r.encounter != null && nonRoot.Contains(r.encounter)) {
|
if(r.encounter?.EncounterDefinition?.Kind is not QuestKind quest) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var next = quest.nextEncounter.Resolve();
|
||||||
|
if(next == null || !byEncounter.ContainsKey(next)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(predecessorCount[next] != 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(ForwardReaches(next, r.encounter, byEncounter)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parentOf[next] = r.encounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodes = new List<TreeViewItemData<Record>>();
|
||||||
|
foreach(var r in records) {
|
||||||
|
if(r.encounter != null && parentOf.ContainsKey(r.encounter)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var children = BuildChainChildren(r, byEncounter, ref uid);
|
r.depth = depth;
|
||||||
result.Add(new TreeViewItemData<Record>(uid++, r, children));
|
var rootId = uid++;
|
||||||
|
var children = BuildChainChildren(r, byEncounter, parentOf, depth + 1, ref uid);
|
||||||
|
nodes.Add(new TreeViewItemData<Record>(rootId, r, children));
|
||||||
}
|
}
|
||||||
return result;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<TreeViewItemData<Record>> BuildChainChildren(Record root, Dictionary<IEncounter, Record> byEncounter, ref int uid) {
|
private static bool ForwardReaches(IEncounter start, IEncounter target, Dictionary<IEncounter, Record> byEncounter) {
|
||||||
|
var current = start;
|
||||||
|
var visited = new HashSet<IEncounter>();
|
||||||
|
while(current?.EncounterDefinition?.Kind is QuestKind quest) {
|
||||||
|
var next = quest.nextEncounter.Resolve();
|
||||||
|
if(next == null || !byEncounter.ContainsKey(next)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(next == target) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(!visited.Add(next)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<TreeViewItemData<Record>> BuildChainChildren(Record root, Dictionary<IEncounter, Record> byEncounter, Dictionary<IEncounter, IEncounter> parentOf, int depth, ref int uid) {
|
||||||
var children = new List<TreeViewItemData<Record>>();
|
var children = new List<TreeViewItemData<Record>>();
|
||||||
if(root.encounter?.Kind is not QuestKind) {
|
if(root.encounter?.EncounterDefinition?.Kind is not QuestKind) {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
var current = root.encounter;
|
var current = root.encounter;
|
||||||
var visited = new HashSet<IEncounter> { current };
|
var visited = new HashSet<IEncounter> { current };
|
||||||
while(current?.Kind is QuestKind quest) {
|
var currentDepth = depth;
|
||||||
|
while(current?.EncounterDefinition?.Kind is QuestKind quest) {
|
||||||
var next = quest.nextEncounter.Resolve();
|
var next = quest.nextEncounter.Resolve();
|
||||||
if(next == null || !visited.Add(next)) {
|
if(next == null || !visited.Add(next)) {
|
||||||
break;
|
break;
|
||||||
@@ -278,14 +500,19 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
if(!byEncounter.TryGetValue(next, out var nextRecord)) {
|
if(!byEncounter.TryGetValue(next, out var nextRecord)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if(!parentOf.TryGetValue(next, out var parent) || parent != current) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nextRecord.depth = currentDepth;
|
||||||
children.Add(new TreeViewItemData<Record>(uid++, nextRecord));
|
children.Add(new TreeViewItemData<Record>(uid++, nextRecord));
|
||||||
current = next;
|
current = next;
|
||||||
|
currentDepth++;
|
||||||
}
|
}
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Matches(Record record) {
|
private bool Matches(Record record) {
|
||||||
var kindName = record.encounter?.Kind?.GetType().Name ?? string.Empty;
|
var kindName = record.encounter?.EncounterDefinition?.Kind?.GetType().Name ?? string.Empty;
|
||||||
if(kindFilter != AllKinds && kindName != kindFilter) {
|
if(kindFilter != AllKinds && kindName != kindFilter) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -312,20 +539,40 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(record.IsTableHeader) {
|
||||||
|
ShowTableHeaderDetail(record.table);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
detailPane.Clear();
|
detailPane.Clear();
|
||||||
|
|
||||||
var serializedObject = new SerializedObject(record.table);
|
var serializedObject = new SerializedObject(record.table);
|
||||||
var encountersProp = serializedObject.FindProperty(nameof(EncounterTable.encounters));
|
var encountersProp = serializedObject.FindProperty(nameof(EncounterTable.encounters));
|
||||||
var elementProp = encountersProp.GetArrayElementAtIndex(record.index);
|
var elementProp = encountersProp.GetArrayElementAtIndex(record.index);
|
||||||
|
|
||||||
var header = new Label($"{record.table.name} → [{record.index}]") {
|
var headerRow = new VisualElement {
|
||||||
style = {
|
style = {
|
||||||
unityFontStyleAndWeight = FontStyle.Bold,
|
flexDirection = FlexDirection.Row,
|
||||||
marginBottom = 6,
|
alignItems = Align.Center,
|
||||||
color = new StyleColor(new Color(0.75f, 0.75f, 0.75f))
|
marginBottom = 6
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
detailPane.Add(header);
|
headerRow.Add(new Label($"{record.table.name} → [{record.index}]") {
|
||||||
|
style = {
|
||||||
|
unityFontStyleAndWeight = FontStyle.Bold,
|
||||||
|
flexGrow = 1f,
|
||||||
|
color = new StyleColor(new Color(0.75f, 0.75f, 0.75f))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var pingButton = new Button(() => {
|
||||||
|
Selection.activeObject = record.table;
|
||||||
|
EditorGUIUtility.PingObject(record.table);
|
||||||
|
}) {
|
||||||
|
text = "Select Table",
|
||||||
|
tooltip = "Select and ping the owning EncounterTable asset in the Project window."
|
||||||
|
};
|
||||||
|
headerRow.Add(pingButton);
|
||||||
|
detailPane.Add(headerRow);
|
||||||
|
|
||||||
elementProp.isExpanded = true;
|
elementProp.isExpanded = true;
|
||||||
var field = new PropertyField(elementProp);
|
var field = new PropertyField(elementProp);
|
||||||
@@ -336,7 +583,7 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void AddChainPreviewIfQuest(Record record) {
|
private void AddChainPreviewIfQuest(Record record) {
|
||||||
if(record.encounter?.Kind is not QuestKind questKind) {
|
if(record.encounter?.EncounterDefinition?.Kind is not QuestKind questKind) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,7 +614,7 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach(var record in allRecords) {
|
foreach(var record in allRecords) {
|
||||||
if(record.encounter?.Kind is not QuestKind kind) {
|
if(record.encounter?.EncounterDefinition?.Kind is not QuestKind kind) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,6 +626,38 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ShowTableHeaderDetail(EncounterTable table) {
|
||||||
|
detailPane.Clear();
|
||||||
|
if(table == null) {
|
||||||
|
ShowEmptyDetail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var headerRow = new VisualElement {
|
||||||
|
style = {
|
||||||
|
flexDirection = FlexDirection.Row,
|
||||||
|
alignItems = Align.Center,
|
||||||
|
marginBottom = 6
|
||||||
|
}
|
||||||
|
};
|
||||||
|
headerRow.Add(new Label(table.name) {
|
||||||
|
style = {
|
||||||
|
unityFontStyleAndWeight = FontStyle.Bold,
|
||||||
|
flexGrow = 1f
|
||||||
|
}
|
||||||
|
});
|
||||||
|
headerRow.Add(new Button(() => {
|
||||||
|
Selection.activeObject = table;
|
||||||
|
EditorGUIUtility.PingObject(table);
|
||||||
|
}) { text = "Select Table" });
|
||||||
|
detailPane.Add(headerRow);
|
||||||
|
|
||||||
|
var count = table.encounters?.Count ?? 0;
|
||||||
|
detailPane.Add(new Label($"{count} encounter(s). Expand the row to browse them, or pick one to edit.") {
|
||||||
|
style = { color = new StyleColor(Color.gray) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void ShowEmptyDetail() {
|
private void ShowEmptyDetail() {
|
||||||
if(detailPane == null) {
|
if(detailPane == null) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
public static List<ValidationIssue> ValidateProject() {
|
public static List<ValidationIssue> ValidateProject() {
|
||||||
var issues = new List<ValidationIssue>();
|
var issues = new List<ValidationIssue>();
|
||||||
|
|
||||||
|
ValidateRegistries(issues);
|
||||||
|
|
||||||
var tables = FindAssetsOfType<EncounterTable>();
|
var tables = FindAssetsOfType<EncounterTable>();
|
||||||
var idIndex = new Dictionary<string, (Encounter encounter, EncounterTable table)>();
|
var idIndex = new Dictionary<string, (Encounter encounter, EncounterTable table)>();
|
||||||
|
|
||||||
@@ -36,6 +38,42 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
return issues;
|
return issues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ValidateRegistries(List<ValidationIssue> issues) {
|
||||||
|
var registries = FindAssetsOfType<EncounterRegistry>();
|
||||||
|
if(registries.Count == 0) {
|
||||||
|
issues.Add(new ValidationIssue {
|
||||||
|
asset = null,
|
||||||
|
path = "<project>",
|
||||||
|
severity = ValidationSeverity.Error,
|
||||||
|
message = "No EncounterRegistry asset exists. Create one via Jovian → Encounter System → Encounter Registry."
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(var registry in registries) {
|
||||||
|
if(registry.encounterCollections == null || registry.encounterCollections.Length == 0) {
|
||||||
|
issues.Add(new ValidationIssue {
|
||||||
|
asset = registry,
|
||||||
|
path = "encounterCollections",
|
||||||
|
severity = ValidationSeverity.Warning,
|
||||||
|
message = "Registry has no collections assigned."
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < registry.encounterCollections.Length; i++) {
|
||||||
|
if(registry.encounterCollections[i] == null) {
|
||||||
|
issues.Add(new ValidationIssue {
|
||||||
|
asset = registry,
|
||||||
|
path = $"encounterCollections[{i}]",
|
||||||
|
severity = ValidationSeverity.Warning,
|
||||||
|
message = "Null collection slot."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static List<ValidationIssue> ValidateEncounter(EncounterTable table, int index) {
|
public static List<ValidationIssue> ValidateEncounter(EncounterTable table, int index) {
|
||||||
var issues = new List<ValidationIssue>();
|
var issues = new List<ValidationIssue>();
|
||||||
if(table?.encounters == null || index < 0 || index >= table.encounters.Count) {
|
if(table?.encounters == null || index < 0 || index >= table.encounters.Count) {
|
||||||
@@ -95,25 +133,26 @@ namespace Jovian.EncounterSystem.Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(encounter.Kind == null) {
|
if(encounter.EncounterDefinition?.Kind == null) {
|
||||||
issues.Add(new ValidationIssue {
|
issues.Add(new ValidationIssue {
|
||||||
asset = table,
|
asset = table,
|
||||||
encounter = encounter,
|
encounter = encounter,
|
||||||
path = $"{pathPrefix}.Kind",
|
path = $"{pathPrefix}.EncounterDefinition.Kind",
|
||||||
severity = ValidationSeverity.Warning,
|
severity = ValidationSeverity.Warning,
|
||||||
message = "Encounter.Kind is null — pick a kind in the inspector."
|
message = "Encounter.Kind is null — pick a kind in the inspector."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(encounter.Kind is QuestKind questKind) {
|
if(encounter.EncounterDefinition?.Kind is QuestKind questKind) {
|
||||||
ValidateEncounterLink(table, pathPrefix + ".Kind.nextEncounter", encounter, questKind.nextEncounter, issues);
|
ValidateEncounterLink(table, pathPrefix + ".EncounterDefinition.Kind.nextEncounter", encounter, questKind.nextEncounter, issues);
|
||||||
}
|
}
|
||||||
|
|
||||||
ValidateDialogEvents(table, index, encounter, issues);
|
ValidateDialogEvents(table, index, encounter, issues);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ValidateEncounterLink(EncounterTable owningTable, string path, Encounter encounter, EncounterLink link, List<ValidationIssue> issues) {
|
private static void ValidateEncounterLink(EncounterTable owningTable, string path, Encounter encounter, EncounterLink link, List<ValidationIssue> issues) {
|
||||||
if(link.table == null && string.IsNullOrEmpty(link.internalId)) {
|
// No id picked — terminal quest step / unset link. Not an error regardless of table value.
|
||||||
|
if(string.IsNullOrEmpty(link.internalId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,5 +42,34 @@ namespace Jovian.EncounterSystem {
|
|||||||
|
|
||||||
return pool[UnityEngine.Random.Range(0, pool.Count)];
|
return pool[UnityEngine.Random.Range(0, pool.Count)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
// Unity's inspector "+" duplicates the previous list element, including nested internalId
|
||||||
|
// GUIDs. Regenerate any duplicates so every encounter carries a unique internalId.
|
||||||
|
private void OnValidate() {
|
||||||
|
if(encounters == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var seen = new HashSet<string>();
|
||||||
|
var changed = false;
|
||||||
|
foreach(var encounter in encounters) {
|
||||||
|
if(encounter?.EncounterDefinition == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = encounter.EncounterDefinition.internalId;
|
||||||
|
if(string.IsNullOrEmpty(id) || !seen.Add(id)) {
|
||||||
|
encounter.EncounterDefinition.internalId = Guid.NewGuid().ToString();
|
||||||
|
seen.Add(encounter.EncounterDefinition.internalId);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(changed) {
|
||||||
|
UnityEditor.EditorUtility.SetDirty(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ namespace Jovian.EncounterSystem {
|
|||||||
EncounterProperties EncounterProperties { get; set; }
|
EncounterProperties EncounterProperties { get; set; }
|
||||||
EncounterVisuals EncounterVisuals { get; set; }
|
EncounterVisuals EncounterVisuals { get; set; }
|
||||||
EncounterDialogOptionSet EncounterDialogOptionSet { get; set; }
|
EncounterDialogOptionSet EncounterDialogOptionSet { get; set; }
|
||||||
IEncounterKind Kind { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Default concrete encounter. Extend via a new <see cref="IEncounterKind"/>, not by subclassing.</summary>
|
/// <summary>Default concrete encounter. Extend via a new <see cref="IEncounterKind"/>, not by subclassing.</summary>
|
||||||
@@ -18,9 +17,6 @@ namespace Jovian.EncounterSystem {
|
|||||||
[field: SerializeField] public EncounterProperties EncounterProperties { get; set; }
|
[field: SerializeField] public EncounterProperties EncounterProperties { get; set; }
|
||||||
[field: SerializeField] public EncounterVisuals EncounterVisuals { get; set; }
|
[field: SerializeField] public EncounterVisuals EncounterVisuals { get; set; }
|
||||||
[field: SerializeField] public EncounterDialogOptionSet EncounterDialogOptionSet { get; set; }
|
[field: SerializeField] public EncounterDialogOptionSet EncounterDialogOptionSet { get; set; }
|
||||||
|
|
||||||
[field: SerializeReference, SubclassSelector]
|
|
||||||
public IEncounterKind Kind { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
@@ -32,6 +28,7 @@ namespace Jovian.EncounterSystem {
|
|||||||
public string id;
|
public string id;
|
||||||
public string name;
|
public string name;
|
||||||
public string description;
|
public string description;
|
||||||
|
[field: SerializeReference, SubclassSelector] public IEncounterKind Kind { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace Jovian.EncounterSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void OnEncounterTriggered(IEncounter encounter) {
|
public void OnEncounterTriggered(IEncounter encounter) {
|
||||||
if(encounter?.Kind is not QuestKind questKind) {
|
if(encounter?.EncounterDefinition.Kind is not QuestKind questKind) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ namespace Jovian.EncounterSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach(var encounter in table.encounters) {
|
foreach(var encounter in table.encounters) {
|
||||||
if(encounter?.Kind is not QuestKind questKind) {
|
if(encounter?.EncounterDefinition.Kind is not QuestKind questKind) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user