Compare commits

17 Commits

Author SHA1 Message Date
Sebastian Bularca
09fe607aab should trigger encounters now 2026-05-06 11:29:50 +02:00
Sebastian Bularca
356e07939a removed tag system 2026-05-04 21:55:18 +02:00
Sebastian Bularca
0ab806d281 ignore 2026-04-27 10:08:10 +02:00
Sebastian Bularca
ac32a6887c ignore 2026-04-27 10:08:00 +02:00
Sebastian Bularca
c1a3231559 leftovers 2026-04-27 00:11:12 +02:00
Sebastian Bularca
ea6c28bfba Added part of the encounter triggering system 2026-04-27 00:01:15 +02:00
Sebastian Bularca
f117ddb914 added tag system support 2026-04-21 00:42:58 +02:00
Sebastian Bularca
dbe799dd73 semantic changes 2026-04-21 00:13:52 +02:00
Sebastian Bularca
2445781f33 performance optimizations 2026-04-20 08:07:24 +02:00
Sebastian Bularca
f055250ca6 Some encounter testing and working 2026-04-19 18:34:22 +02:00
Sebastian Bularca
8861bdc5eb added encounter system 2026-04-19 12:46:44 +02:00
Sebastian Bularca
c1b5d0e9e0 Adedd some testing zones 2026-04-18 11:58:07 +02:00
Sebastian Bularca
90b66f26fd dadded package sync 2026-04-12 19:22:35 +02:00
Sebastian Bularca
34f99434b9 finished readme 2026-04-12 19:19:04 +02:00
Sebastian Bularca
0e00e798fd Added a custom calendar system 2026-04-12 19:14:37 +02:00
Sebastian Bularca
3428f168f9 some cosmetic changes 2026-04-12 17:19:38 +02:00
Sebastian Bularca
993929bede settings stuff 2026-04-12 17:00:25 +02:00
160 changed files with 22137 additions and 116 deletions

View File

@@ -23,7 +23,10 @@
"Bash(find D:/repos/trail-into-darkness/Assets -name *.asmdef)",
"Bash(grep -E \"\\\\.\\(prefab|unity\\)$\")",
"Bash(python3:*)",
"WebSearch"
"WebSearch",
"Bash(mkdir -p \"D:/repos/trail-into-darkness/Packages/com.jovian.worldtime/Runtime\")",
"Bash(mkdir -p \"D:/repos/trail-into-darkness/Packages/com.jovian.worldtime/Editor\")",
"Bash(mkdir -p \"D:/repos/trail-into-darkness/Packages/com.jovian.worldtime/Samples~\")"
]
}
}

1
.gitignore vendored
View File

@@ -98,3 +98,4 @@ InitTestScene*.unity*
# Auto-generated scenes by play mode tests
/[Aa]ssets/[Ii]nit[Tt]est[Ss]cene*.unity*
.idea/
Packages/com.jovian.tag-system

View File

@@ -15,7 +15,7 @@ MonoBehaviour:
m_DefaultGroup: d7f58d36cc4da874fa45d38c0070c2c2
m_currentHash:
serializedVersion: 2
Hash: 00000000000000000000000000000000
Hash: 41c3275372ee23ae1595642e0bc286bf
m_OptimizeCatalogSize: 0
m_BuildRemoteCatalog: 0
m_CatalogRequestsTimeout: 0

View File

@@ -115,6 +115,16 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7a17d50d1abe3764695c6cd9598487ca
m_Address: EncounterRegistry
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7b5e9961dadecea4bba3be6de61909f3
m_Address: CalendarSettings
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7e443a969de292045b2224c779d96139
m_Address: Assets/Art/UI/menu_bar_left.png
m_ReadOnly: 0
@@ -231,6 +241,16 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f7becfd0b70554e46b4e04fa25a75341
m_Address: JovianTagsSettings
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: fdfc8d602281a0b45bbd7c08cb41f727
m_Address: EncounterPrefabs
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: fe393ace9b354375a9cb14cdbbc28be4
m_Address: Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader
m_ReadOnly: 0

View File

@@ -1,3 +1,5 @@
using Jovian.Calendar;
using Jovian.EncounterSystem;
using Jovian.PopupSystem;
using Jovian.PopupSystem.UI;
using Jovian.SaveSystem;
@@ -25,7 +27,8 @@ namespace Nox.Game {
private readonly PlayModeSettings bootstrapSettings;
private readonly GameDataState gameDataState;
private readonly ISaveSystem saveSystem;
private PartyDefinition partyDefinition;
private readonly PartyDefinition partyDefinition;
private readonly AdventureSettings adventureSettings;
private AdventureData adventureData;
private AdventureModePrefabs scenePrefabs;
private ICameraController cameraController;
@@ -37,11 +40,13 @@ namespace Nox.Game {
private AdventureView adventureView;
private ZoneSystem zoneSystem;
private GuiReferences guiReferences;
private AdventureSettings adventureSettings;
private TimeHandler timeHandler;
private PartyInventoryHandler partyInventoryHandler;
private PartyGuiView partyGuiView;
private IPopupSystem popupSystem;
private EncounterRegistry encounterRegistry;
private EncounterHandler encounterHandler;
private EncounterPrefabs encounterPrefabs;
public AdventurePlayMode(
PlatformSettings platformSettings,
@@ -102,7 +107,9 @@ namespace Nox.Game {
Debug.LogWarning("AdventurePlayMode started from the Adventure Scene. Loading the last Autosave");
}
encounterRegistry ??= Addressables.LoadAssetAsync<EncounterRegistry>("EncounterRegistry").WaitForCompletion();
scenePrefabs ??= Addressables.LoadAssetAsync<AdventureModePrefabs>("AdventureMapPrefabs").WaitForCompletion();
encounterPrefabs = Addressables.LoadAssetAsync<EncounterPrefabs>("EncounterPrefabs").WaitForCompletion();
mapRef ??= Object.FindFirstObjectByType<MapReference>();
partyRef ??= Object.FindFirstObjectByType<PartyReference>();
if(partyRef && gameDataState.savedPartyPosition.HasValue) {
@@ -125,14 +132,24 @@ namespace Nox.Game {
partyInventoryHandler ??= new PartyInventoryHandler(adventureData, adventureSettings);
partyInventoryHandler.Initialize();
timeHandler ??= new TimeHandler(adventureSettings, adventureData);
zoneSystem ??= new ZoneSystem(mapRef.zonesObjectHolder);
var calendarSettings = Addressables.LoadAssetAsync<CalendarSettings>("CalendarSettings").WaitForCompletion();
var worldClock = new WorldClock(calendarSettings);
timeHandler ??= new TimeHandler(adventureSettings, adventureData, worldClock);
partyMovementHandler ??= new PartyMovementHandler(partyRef, cameraController, mapLocationsReference, platformSettings.inputSettings, zoneSystem, adventureData, adventureSettings);
zoneSystem ??= new ZoneSystem(mapRef.zonesObjectHolder);
encounterHandler = new EncounterHandler(zoneSystem, encounterRegistry, encounterPrefabs);
partyMovementHandler ??= new PartyMovementHandler(
partyRef,
cameraController,
mapLocationsReference,
platformSettings.inputSettings,
encounterHandler,
adventureData,
adventureSettings);
partyMovementHandler.Initialize();
guiReferences ??= Object.FindFirstObjectByType<GuiReferences>();
adventureView ??= new AdventureView(gameDataState, guiReferences, inputActions, adventureData, adventureSettings);
adventureView ??= new AdventureView(gameDataState, guiReferences, inputActions, adventureData, adventureSettings, worldClock);
adventureView.Initialize();
if(partyGuiView == null && guiReferences.partyMemberSlotPrefab != null) {
@@ -161,6 +178,7 @@ namespace Nox.Game {
timeHandler.Tick();
partyInventoryHandler.Tick();
partyMovementHandler.Tick();
encounterHandler.Tick();
adventureView.Tick();
partyGuiView?.Tick();
popupSystem?.Tick(Time.deltaTime);
@@ -188,10 +206,14 @@ namespace Nox.Game {
inputActions.UI.PauseMenu.Disable();
}
public void Dispose() {
cameraController?.Dispose();
partyMovementHandler?.Dispose();
partyGuiView?.Dispose();
popupSystem?.Dispose();
cameraController?.Dispose();
partyMovementHandler?.Dispose();
encounterHandler?.Dispose();
encounterRegistry = null;
Resources.UnloadUnusedAssets();
}
}

View File

@@ -1,3 +1,4 @@
using System;
using UnityEngine;
namespace Nox.Game {

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d6216fd41db9494aaa6c127d9d790b93
timeCreated: 1776506857

View File

@@ -0,0 +1,9 @@
using TMPro;
using UnityEngine;
namespace Nox.Game {
public class AnswerPrefab : MonoBehaviour {
public TextMeshProUGUI number;
public TextMeshProUGUI dialogText;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0c14350aeeed44a28d98d22c6ef048dc
timeCreated: 1777235448

View File

@@ -0,0 +1,95 @@
using Jovian.EncounterSystem;
using Jovian.ZoneSystem;
using UnityEngine;
namespace Nox.Game {
public class EncounterHandler {
private readonly ZoneSystem zoneSystem;
private readonly EncounterRegistry encounterRegistry;
private readonly EncounterView encounterView;
private string previousZoneId;
public EncounterHandler(ZoneSystem zoneSystem, EncounterRegistry encounterRegistry, EncounterPrefabs encounterPrefabs) {
this.zoneSystem = zoneSystem;
this.encounterRegistry = encounterRegistry;
encounterView = new EncounterView(encounterPrefabs);
}
public bool AskForRandomEncounter(ZoneContext zoneContext, string encounterTableId, out IEncounter encounter) {
return ResolveEncounter(zoneContext, encounterTableId, out encounter);
}
public bool AskForRandomEncounterOfType(ZoneContext zoneContext, string encounterTableId, out IEncounter encounter, IEncounterKind encounterKind) {
return ResolveEncounter(zoneContext, encounterTableId, out encounter, encounterKind);
}
public bool AskForEncounter(string encounterId, out IEncounter encounter) {
return encounterRegistry.GetEncounters().TryGetValue(encounterId, out encounter);
}
private bool ResolveEncounter(ZoneContext zoneContext, string encounterTableId, out IEncounter encounter, IEncounterKind encounterKind = null) {
encounter = null;
if(zoneContext.isSafe) {
return false;
}
var randomChance = Random.Range(0f, 1f);
var shouldTrigger = randomChance <= zoneContext.finalEncounterChance;
if(!shouldTrigger) {
return false;
}
if(encounterKind == null) {
encounter = encounterRegistry.GetRandomEncounter(encounterTableId);
return encounter != null;
}
encounter = encounterRegistry.GetRandomEncounter(encounterTableId, encounterKind);
return encounter != null;
}
private void VerifyZones(Vector3 position) {
var zoneContext = zoneSystem.QueryZone(position);
if(string.IsNullOrEmpty(zoneContext.resolvedZoneId)) {
return;
}
var currentZoneId = zoneContext.resolvedZoneId;
if(currentZoneId != previousZoneId) {
if(!string.IsNullOrEmpty(currentZoneId)) {
Debug.Log($"Entered zone: {currentZoneId} (encounter: {zoneContext.encounterTableId}, safe: {zoneContext.isSafe})");
if(ResolveEncounter(zoneContext, zoneContext.encounterTableId, out var encounter)) {
TriggerEncounter(encounter);
}
}
else if(!string.IsNullOrEmpty(previousZoneId)) {
Debug.Log($"Left zone: {previousZoneId}");
}
previousZoneId = currentZoneId;
}
}
private void TriggerEncounter(IEncounter encounter) {
switch(encounter.EncounterDefinition.Kind) {
case CombatKind:
return;
default:
encounterView?.SetCurrentEncounter(encounter);
encounterView?.Show();
break;
}
}
public void CheckForEncounters(Vector3 position) {
VerifyZones(position);
}
public void Tick() { }
public void Dispose() {
// nothing here
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 523274f9158f453dbfac02601a77c3f7
timeCreated: 1776506833

View File

@@ -0,0 +1,25 @@
using Jovian.EncounterSystem;
using System;
namespace Nox.Game {
[Serializable]
public class CombatKind : IEncounterKind { }
[Serializable]
public class SocialKind : IEncounterKind { }
[Serializable]
public class PuzzleKind : IEncounterKind { }
[Serializable]
public class ExplorationKind : IEncounterKind { }
[Serializable]
public class TutorialKind : IEncounterKind { }
[Serializable]
public class HazardKind : IEncounterKind { }
[Serializable]
public class OtherKind : IEncounterKind { }
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: abf01048c404a0240ad538b65a15f5fb

View File

@@ -0,0 +1,18 @@
using Jovian.EncounterSystem;
using System;
using UnityEngine;
namespace Nox.Game {
[CreateAssetMenu(fileName = "EncounterPrefabs", menuName = "Nox/EncounterPrefabs")]
public class EncounterPrefabs : ScriptableObject {
public EncounterSet[] encounterSets;
public AnswerPrefab answerPrefab;
}
[Serializable]
public class EncounterSet {
[field: SerializeReference, SubclassSelector]
public IEncounterKind encounterKind;
public EncounterReference encounterReference;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7fc36c84acd04836b1280aba57a64e24
timeCreated: 1777229589

View File

@@ -0,0 +1,43 @@
using Jovian.EncounterSystem;
using Nox.Game.UI;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Nox.Game {
public class EncounterView : IMenuView{
private readonly EncounterPrefabs encounterPrefabs;
private readonly IEncounterKind encounterKind;
private IEncounter currentEncounter;
private Dictionary<IEncounterKind, EncounterReference> encounterKindToPrefab = new ();
private IEncounterKind currentActiveKind;
public EncounterView(EncounterPrefabs encounterPrefabs) {
this.encounterPrefabs = encounterPrefabs;
}
public void SetCurrentEncounter(IEncounter encounter) {
currentEncounter = encounter;
if(!encounterKindToPrefab.TryGetValue(encounter.EncounterDefinition.Kind, out var encounterReference)) {
encounterReference = Object.Instantiate(encounterPrefabs.encounterSets.FirstOrDefault(e => e.encounterKind == encounterKind)?.encounterReference);
encounterKindToPrefab.Add(encounter.EncounterDefinition.Kind, encounterReference);
}
}
public void Initialize() { }
public void Show() {
currentActiveKind = currentEncounter.EncounterDefinition.Kind;
PopulateEncounterReference();
encounterKindToPrefab[currentActiveKind].gameObject.SetActive(true);
}
private void PopulateEncounterReference() {
}
public void Hide() {
encounterKindToPrefab[currentActiveKind].gameObject.SetActive(false);
}
public void Tick() { }
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b69490c9f1d8471a84b4594d1b1be117
timeCreated: 1776590016

View File

@@ -0,0 +1,30 @@
using Jovian.EncounterSystem;
using System;
namespace Nox.Game {
[Serializable]
public class CurrencyRewardKind : IRewardKind {
public string currencyId;
public int amount;
}
[Serializable]
public class ItemRewardKind : IRewardKind {
public string itemId;
public int quantity;
}
[Serializable]
public class ExperienceRewardKind : IRewardKind {
public int amount;
}
[Serializable]
public class UnlockableRewardKind : IRewardKind {
public string unlockableId;
}
[Serializable]
public class OtherRewardKind : IRewardKind {
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7895041af87249e4c8458a07b0bc6b2c

View File

@@ -1,4 +1,3 @@
using Jovian.ZoneSystem;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
@@ -9,17 +8,15 @@ namespace Nox.Game {
private readonly ICameraController cameraController;
private readonly InputSystem_Actions inputActions;
private readonly MapLocationsReference mapLocationsReference;
private readonly ZoneSystem zoneSystem;
private readonly EncounterHandler encounterHandler;
private readonly AdventureSettings adventureSettings;
private readonly float maxDistance = 100f;
private readonly AdventureData adventureData;
private AdventureData adventureData;
private bool partyCanMove;
private Vector3 targetPosition;
private bool shouldHover;
private MapLocation currentSelectedPoi;
private string previousZoneId;
private bool hasClicked;
private bool skipNextClick;
@@ -31,16 +28,15 @@ namespace Nox.Game {
ICameraController cameraController,
MapLocationsReference mapLocationsReference,
Input.InputSettings inputSettings,
ZoneSystem zoneSystem,
EncounterHandler encounterHandler,
AdventureData adventureData,
AdventureSettings adventureSettings) {
this.partyReference = partyReference;
this.cameraController = cameraController;
this.mapLocationsReference = mapLocationsReference;
this.zoneSystem = zoneSystem;
this.encounterHandler = encounterHandler;
this.adventureData = adventureData;
this.adventureSettings = adventureSettings;
inputActions = inputSettings.inputActions;
}
@@ -77,10 +73,14 @@ namespace Nox.Game {
if(!clickHit.collider.gameObject.transform.parent.TryGetComponent(out MapReference mapReference)) {
return;
}
//if(mapReference.ValidateMoveLocation(hitInfoPoint)) {
if(ValidateMoveLocation(clickHit)) {
targetPosition = clickHit.point;
partyCanMove = true;
//}
}
}
private bool ValidateMoveLocation(object hitInfoPoint) {
return true;
}
public void Tick() {
@@ -109,9 +109,13 @@ namespace Nox.Game {
VerifyPointsOfInterest();
partyCanMove = false;
}
adventureData.isPartyMoving = true;
partyReference.transform.position = Vector3.MoveTowards(new Vector3(partyReference.transform.position.x, 0, partyReference.transform.position.z), targetPosition, Time.deltaTime * adventureSettings.partyBaseSpeed);
VerifyZones(partyReference.transform.position);
partyReference.transform.position = Vector3.MoveTowards(
new Vector3(partyReference.transform.position.x, 0,
partyReference.transform.position.z), targetPosition,
Time.deltaTime * adventureSettings.partyBaseSpeed);
encounterHandler?.CheckForEncounters(partyReference.transform.position);
}
private void HandleHover() {
@@ -128,20 +132,6 @@ namespace Nox.Game {
currentSelectedPoi = null;
}
}
private void VerifyZones(Vector3 position) {
var zoneContext = zoneSystem.QueryZone(position);
var currentZoneId = zoneContext.resolvedZoneId;
if(currentZoneId != previousZoneId) {
if(!string.IsNullOrEmpty(currentZoneId)) {
Debug.Log($"Entered zone: {currentZoneId} (encounter: {zoneContext.encounterTableId}, safe: {zoneContext.isSafe})");
}
else if(!string.IsNullOrEmpty(previousZoneId)) {
Debug.Log($"Left zone: {previousZoneId}");
}
previousZoneId = currentZoneId;
}
}
private void VerifyPointsOfInterest() {
foreach(var location in mapLocationsReference.mapLocations) {
@@ -156,5 +146,4 @@ namespace Nox.Game {
inputActions.Player.ClickOnMap.performed -= OnClickOnMap;
}
}
}

View File

@@ -1,3 +1,4 @@
using Jovian.Calendar;
using UnityEngine;
namespace Nox.Game {
@@ -13,6 +14,7 @@ namespace Nox.Game {
public class TimeHandler {
private readonly AdventureSettings adventureSettings;
private readonly AdventureData adventureData;
private readonly WorldClock worldClock;
private float localTime;
@@ -23,34 +25,44 @@ namespace Nox.Game {
(0.25f, DayPhase.Morning),
(0.50f, DayPhase.Afternoon),
(0.75f, DayPhase.Dusk),
(0.90f, DayPhase.Night),
(0.90f, DayPhase.Night)
};
public TimeHandler(AdventureSettings adventureSettings, AdventureData adventureData) {
public TimeHandler(AdventureSettings adventureSettings, AdventureData adventureData, WorldClock worldClock) {
this.adventureSettings = adventureSettings;
this.adventureData = adventureData;
this.worldClock = worldClock;
localTime = adventureData.currentTime * adventureSettings.dayLength;
}
public void Tick() {
if (!adventureData.isPartyMoving) return;
if(!adventureData.isPartyMoving) {
return;
}
localTime += Time.deltaTime;
if (localTime >= adventureSettings.dayLength) {
if(localTime >= adventureSettings.dayLength) {
localTime -= adventureSettings.dayLength;
adventureData.currentDay++;
}
adventureData.currentTime = localTime / adventureSettings.dayLength;
adventureData.currentDayPhase = GetPhase(adventureData.currentTime);
var normalized = localTime / adventureSettings.dayLength;
worldClock.Tick(normalized);
adventureData.currentTime = normalized;
adventureData.currentDayPhase = GetPhase(normalized);
}
private static DayPhase GetPhase(float t) {
var phase = DayPhase.Midnight;
foreach (var (start, p) in PhaseThresholds) {
if (t >= start) phase = p;
else break;
foreach(var (start, p) in PhaseThresholds) {
if(t >= start) {
phase = p;
}
else {
break;
}
}
return phase;
}

View File

@@ -1,3 +1,4 @@
using Jovian.Calendar;
using Nox.Core;
namespace Nox.Game.UI {
@@ -7,20 +8,22 @@ namespace Nox.Game.UI {
private readonly InputSystem_Actions inputActions;
private readonly AdventureData adventureData;
private readonly AdventureSettings adventureSettings;
private DayPhase dayPhase = DayPhase.Midnight;
private readonly WorldClock worldClock;
private int currentDay;
private int previousTime;
public AdventureView(
GameDataState gameDataState,
public AdventureView(GameDataState gameDataState,
GuiReferences guiReferences,
InputSystem_Actions inputActions,
AdventureData adventureData,
AdventureSettings adventureSettings) {
AdventureSettings adventureSettings,
WorldClock worldClock) {
this.gameDataState = gameDataState;
this.guiReferences = guiReferences;
this.inputActions = inputActions;
this.adventureData = adventureData;
this.adventureSettings = adventureSettings;
this.worldClock = worldClock;
}
private void InvokePauseMenu() {
gameDataState.ChangePlayMode(PlayMode.PauseMenu);
@@ -28,7 +31,8 @@ namespace Nox.Game.UI {
public void Initialize() {
guiReferences.pauseMenuButton.onClick.AddListener(InvokePauseMenu);
guiReferences.dayText.text = $"Day {adventureData.currentDay}, {adventureData.currentDayPhase.ToString()}";
guiReferences.dayText.text = $"{worldClock.FullStringNamed()}";
previousTime = -1;
guiReferences.suppliesBar.fillAmount = (float)adventureData.suppliesAvailable / adventureSettings.maxSupplies;
guiReferences.suppliesText.text = $"{adventureData.suppliesAvailable}/{adventureSettings.maxSupplies}";
}
@@ -40,14 +44,14 @@ namespace Nox.Game.UI {
throw new System.NotImplementedException();
}
public void Tick() {
if(dayPhase != adventureData.currentDayPhase) {
dayPhase = adventureData.currentDayPhase;
guiReferences.dayText.text = $"Day {adventureData.currentDay}, {adventureData.currentDayPhase.ToString()}";
var time = worldClock.Now.minute;
if (time != previousTime) {
previousTime = time;
}
guiReferences.dayText.text = $"{worldClock.FullStringNamed()}";
if(currentDay != adventureData.currentDay) {
currentDay = adventureData.currentDay;
guiReferences.dayText.text = $"Day {adventureData.currentDay}, {adventureData.currentDayPhase.ToString()}";
guiReferences.suppliesBar.fillAmount = (float)adventureData.suppliesAvailable / adventureSettings.maxSupplies;
guiReferences.suppliesText.text = $"{adventureData.suppliesAvailable}/{adventureSettings.maxSupplies}";
}

View File

@@ -62,10 +62,13 @@ namespace Nox.Game.UI {
: 0;
// Activate slots for current members, deactivate the rest
for(int i = 0; i < PoolSize; i++) {
for(var i = 0; i < PoolSize; i++) {
var slot = slotPool[i];
if(i < memberCount) {
if(i < memberCount && trackedParty?.members != null) {
var member = trackedParty.members[i];
if(member == null) {
continue;
}
slot.gameObject.SetActive(true);
// Portrait
@@ -84,10 +87,9 @@ namespace Nox.Game.UI {
activeCount = memberCount;
// Initialize popup triggers
if(popupSystem != null) {
popupSystem.InitializeTriggersInChildren(portraitsContainer, (trigger, view) => {
popupSystem?.InitializeTriggersInChildren(portraitsContainer, (trigger, view) => {
var slot = trigger.GetComponentInParent<PartyMemberSlot>();
if(slot == null) {
if(!slot) {
return;
}
var slotIndex = System.Array.IndexOf(slotPool, slot);
@@ -98,7 +100,6 @@ namespace Nox.Game.UI {
view.SetContent(builder => BuildCharacterPopup(builder, member));
});
}
}
private void BuildCharacterPopup(PopupContentBuilder builder, CharacterDefinition member) {
// Header

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 83509b822db37ec4e863ff7a2b4c01ae
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
%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: 7fc36c84acd04836b1280aba57a64e24, type: 3}
m_Name: EncounterPrefabs
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.EncounterPrefabs
encounterSets:
- encounterKind:
rid: 1352971649185742937
encounterReference: {fileID: 3705563528526877357, guid: 62525e62adc83b84abde85d78828de2b, type: 3}
answerPrefab: {fileID: -3146704326252051464, guid: cbecff27dee2cf7448a05a89ecb018b4, type: 3}
references:
version: 2
RefIds:
- rid: 1352971649185742937
type: {class: ExplorationKind, ns: Nox.Game, asm: Assembly-CSharp}
data:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fdfc8d602281a0b45bbd7c08cb41f727
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
%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: 0dfee180882d49c9a3d4474f389d4905, type: 3}
m_Name: EncounterRegistry
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.EncounterRegistry
encounterCollections:
- {fileID: 11400000, guid: b3c3371ae34b4e34ea57a013b5125022, type: 2}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7a17d50d1abe3764695c6cd9598487ca
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 453cbe825e21cba41b61175034c2b5d1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 65c1422c9083d1b4d9721cf275cfe7f3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
%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: 142d6e5b0f6a6cb41beddeae92b56fee, type: 3}
m_Name: DialogLineLibrary
m_EditorClassIdentifier: Jovian.EncounterSystem::Jovian.EncounterSystem.DialogLineLibrary
lines:
- id: test_you_die
text: Click me and see what happens. MIght all your dreams com true?
- id: click_to_continue
text: This is a test like that should you click it, it will continue and record
quest progress
- id: right_choice
text: You have chose right, padwan, here is 4 RON!

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 11b94daa76442834198b68996afe0013
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
%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: c47caaa92bb94eeca3e47dd86fd010cf, type: 3}
m_Name: Dialog_Set_0
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.EncounterDialogOptionSet
id: Dialog_Set_0
library: {fileID: 11400000, guid: 11b94daa76442834198b68996afe0013, type: 2}
options:
- text:
id: click_to_continue
inlineText:
events:
- rid: 1352971465325281416
references:
version: 2
RefIds:
- rid: 1352971465325281416
type: {class: LogEvent, ns: Jovian.EncounterSystem, asm: Jovian.EncounterSystem}
data:
message: An thus, you continue...

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7bc554ae0760bbb4796a1b3acef22cb3
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
%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: c47caaa92bb94eeca3e47dd86fd010cf, type: 3}
m_Name: Dialog_Set_1
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.EncounterDialogOptionSet
id: Dialog_Set_1
library: {fileID: 11400000, guid: 11b94daa76442834198b68996afe0013, type: 2}
options:
- text:
id: test_you_die
inlineText:
events:
- rid: 1352971465325281414
- text:
id: right_choice
inlineText:
events:
- rid: 1352971465325281412
references:
version: 2
RefIds:
- rid: 1352971465325281412
type: {class: GiveRewardEvent, ns: Jovian.EncounterSystem, asm: Jovian.EncounterSystem}
data:
reward: {fileID: 11400000, guid: 2c02212ce09c5a246a8fe11a5253bfd4, type: 2}
- rid: 1352971465325281414
type: {class: LogEvent, ns: Jovian.EncounterSystem, asm: Jovian.EncounterSystem}
data:
message: You died! HAhahAhaha!

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9496570aa3d05624a9b8bbbf6009c453
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,39 @@
%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: TestEncounterTable
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.EncounterTable
id: TestEncounterTable
encounters:
- <EncounterDefinition>k__BackingField:
internalId: 169489f1-892d-475b-8c32-fc760da28929
id: simple_puzzle
name: Fix a Broken Cart
description: 'You encounter a broken cart. At a closer examination you chose
to:'
<Kind>k__BackingField:
rid: 1352971521842741341
<EncounterProperties>k__BackingField:
difficulty: 0
<EncounterVisuals>k__BackingField:
icon: {fileID: 0}
encounterColor: {r: 0, g: 0, b: 0, a: 0}
encounterArt: {fileID: 0}
<EncounterDialogOptionSet>k__BackingField: {fileID: 0}
references:
version: 2
RefIds:
- rid: 1352971521842741341
type: {class: PuzzleKind, ns: Nox.Game, asm: Assembly-CSharp}
data:
puzzleId: cart
difficultyClass: 0

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0d6735c0d1617b243a1f6c8c5070028c
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 396a5409178bf0d4b938094eefe22cca
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 57820b3b9a698e24393172741670d8fe
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
%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: ce47d4bfb319877429589295ac214255, type: 3}
m_Name: Reward
m_EditorClassIdentifier: Jovian.EncounterSystem::Jovian.EncounterSystem.Reward
id: gold
displayName: All Ze Money
kind:
rid: 1352971521842741336
references:
version: 2
RefIds:
- rid: 1352971521842741336
type: {class: CurrencyRewardKind, ns: Nox.Game, asm: Assembly-CSharp}
data:
currencyId: gold
amount: 100

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2c02212ce09c5a246a8fe11a5253bfd4
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
%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: 96ab08e2592347f68b8ad2e6e8d45187, type: 3}
m_Name: TestEncountersCollection
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.EncountersCollection
encounterTables:
- {fileID: 11400000, guid: 396a5409178bf0d4b938094eefe22cca, type: 2}
- {fileID: 11400000, guid: 0d6735c0d1617b243a1f6c8c5070028c, type: 2}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b3c3371ae34b4e34ea57a013b5125022
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -12,6 +12,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 1d2424482c4843c0b7a33a9cc67411b2, type: 3}
m_Name: AdventureSettings
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.AdventureSettings
startingDate: 2026-04-12
startingTime: 08:00:00
dayLength: 20
maxSupplies: 20
partyBaseSpeed: 0.3

View File

@@ -0,0 +1,29 @@
%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: e3a6df85a820d0a4db469ae8a20ea773, type: 3}
m_Name: CalendarSettings
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.CalendarSettings
secondsPerFullDay: 60
hoursPerDay: 24
minutesPerHour: 60
daysPerMonth: 5a0000005a0000005a0000005a000000
monthNames:
- Ashveil
- Thornmere
- Duskhollow
- 'Frosthollow '
daysPerWeek: 7
startYear: 4232
startMonth: 1
startDay: 1
startHour: 8
startMinute: 0

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7b5e9961dadecea4bba3be6de61909f3
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
%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: 32e658688044a8f469e0c311f9c4facb, type: 3}
m_Name: JovianTagsSettings
m_EditorClassIdentifier: Jovian.TagSystem::Jovian.TagSystem.JovianTagsSettings
gameTags: []

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f7becfd0b70554e46b4e04fa25a75341
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
%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: 8497d766078e5764a9c7c0dd5d671561, type: 3}
m_Name: Codrii_Vasluiului
m_EditorClassIdentifier: Jovian.ZoneSystem::Jovian.ZoneSystem.ZoneData
zoneId: forest_1
zoneName: Codrii Vasluiului
role: 0
priority: 5
debugColor: {r: 0, g: 0.7563188, b: 1, a: 0.25}
encounterTableId: Forest_Easy
baseDifficultyTier: 2
baseEncounterChance: 0.35
encounterChanceMultiplier: 1
difficultyTierBonus: 0
isSafeZone: 0
overrideEncounterTableId:
overrideEncounterChance: 1
overrideDifficultyTier: 4
shape: 2
circleRadius: 2
polygon:
- {x: 12.236091, y: 1.6645191}
- {x: 6.1699877, y: 1.8335454}
- {x: 4.4582586, y: 13.148059}
- {x: -6.042471, y: 13.081609}
- {x: -4.9572964, y: 7.6616793}
- {x: -4.7374926, y: 2.7339745}
- {x: -5.4721823, y: -0.8101535}
- {x: -8.5348425, y: -7.156863}
- {x: -5.730815, y: -7.9851418}
- {x: -1.2216358, y: -9.166967}
- {x: 4.660077, y: -10.403753}
- {x: 9.102275, y: -8.908843}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4eefe490fd756c947b300b6f3d697df4
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
%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: 8497d766078e5764a9c7c0dd5d671561, type: 3}
m_Name: RedMystEast_1
m_EditorClassIdentifier: Jovian.ZoneSystem::Jovian.ZoneSystem.ZoneData
zoneId: redmysteast_1
zoneName: RedMystEast_1
role: 2
priority: 1
debugColor: {r: 1, g: 0, b: 0.70456123, a: 0.28235295}
encounterTableId:
baseDifficultyTier: 1
baseEncounterChance: 0.2
encounterChanceMultiplier: 1
difficultyTierBonus: 0
isSafeZone: 0
overrideEncounterTableId: Mys_Generic
overrideEncounterChance: 0.5
overrideDifficultyTier: 2
shape: 2
circleRadius: 2
polygon:
- {x: 13.724243, y: -0.19157219}
- {x: 7.0784187, y: -2.0174198}
- {x: 1.8911858, y: -2.108677}
- {x: -0.8943138, y: -1.4471855}
- {x: -2.439663, y: -0.7384167}
- {x: -4.3616867, y: 0.1630249}
- {x: -4.843336, y: -1.959795}
- {x: -4.2144585, y: -3.5807629}
- {x: -1.4249802, y: -3.6347256}
- {x: 2.9196434, y: -3.987339}
- {x: 7.422428, y: -4.7113047}
- {x: 13.624405, y: -4.2200985}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b8ae323df4686334d91ad4d9b22f4159
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
%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: 8497d766078e5764a9c7c0dd5d671561, type: 3}
m_Name: South_Road
m_EditorClassIdentifier: Jovian.ZoneSystem::Jovian.ZoneSystem.ZoneData
zoneId: adventure_generic_!
zoneName: South Road
role: 0
priority: 10
debugColor: {r: 0, g: 0.7563188, b: 1, a: 0.25}
encounterTableId: Adventure_Random_Easy
baseDifficultyTier: 1
baseEncounterChance: 1
encounterChanceMultiplier: 1
difficultyTierBonus: 0
isSafeZone: 0
overrideEncounterTableId:
overrideEncounterChance: 1
overrideDifficultyTier: 4
shape: 2
circleRadius: 2
polygon:
- {x: 0.384861, y: 24.29522}
- {x: -15.640621, y: 34.511837}
- {x: -30.113129, y: 27.246357}
- {x: -31.496538, y: 21.42181}
- {x: -27.24808, y: 14.641392}
- {x: -20.353535, y: 8.758091}
- {x: -17.977764, y: 1.1894388}
- {x: -16.602146, y: -6.5378437}
- {x: -4.461025, y: -6.983674}
- {x: 0.00000003577464, y: -3}
- {x: 5.9418945, y: 1.2338381}
- {x: 5.1053047, y: 12.924463}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 263de6ccb4b79c340883df4a1d555220
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
%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: 8497d766078e5764a9c7c0dd5d671561, type: 3}
m_Name: Thievs_Corener
m_EditorClassIdentifier: Jovian.ZoneSystem::Jovian.ZoneSystem.ZoneData
zoneId: thieves_corner
zoneName: Thievs Corener
role: 1
priority: 1
debugColor: {r: 0.18546152, g: 1, b: 0, a: 0.25}
encounterTableId:
baseDifficultyTier: 1
baseEncounterChance: 0.2
encounterChanceMultiplier: 1.3
difficultyTierBonus: 2
isSafeZone: 0
overrideEncounterTableId:
overrideEncounterChance: 1
overrideDifficultyTier: 4
shape: 0
circleRadius: 2
polygon:
- {x: -1.2897816, y: -1.2319221}
- {x: -3.3127394, y: 4.1323624}
- {x: 3.03339, y: 5.764496}
- {x: 4.5610886, y: -0.49201393}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 499c88e149852754ab0a9a5d551f7eea
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -12,9 +12,9 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: e38e313f3665d464b82b22699b2a4634, type: 3}
m_Name: PopupSettings
m_EditorClassIdentifier: Jovian.PopupSystem::Jovian.PopupSystem.PopupSettings
popupDelay: 0.4
popupDelay: 0.2
fadeDuration: 0.2
defaultAnchorSide: 3
defaultAnchorSide: 2
screenEdgePadding: 10
maxPopupWidth: 400
sortingOrder: 100

View File

@@ -0,0 +1,359 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1774939147060596866
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1760747944163223242}
- component: {fileID: 3503963276009221598}
- component: {fileID: 572009535857796838}
m_Layer: 5
m_Name: nr
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1760747944163223242
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1774939147060596866}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5249586234698548752}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 33.7117, y: -11.996}
m_SizeDelta: {x: 21.0224, y: 24.1}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &3503963276009221598
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1774939147060596866}
m_CullTransparentMesh: 1
--- !u!114 &572009535857796838
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1774939147060596866}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: 1.
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_sharedMaterial: {fileID: 9074173216178389243, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4278783248
m_fontColor: {r: 0.0627451, g: 0.050980397, b: 0.03529412, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 12
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 2.6
m_fontSizeMax: 12
m_fontStyle: 0
m_HorizontalAlignment: 4
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 2.668274, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &5906514193138747816
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5249586234698548752}
- component: {fileID: 6966740546070481897}
- component: {fileID: 1953891385698885950}
- component: {fileID: -3146704326252051464}
m_Layer: 5
m_Name: Answers
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5249586234698548752
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5906514193138747816}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1760747944163223242}
- {fileID: 7428637175488290741}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 192.33157, y: -11.602112}
m_SizeDelta: {x: 384.6631, y: 24.0463}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6966740546070481897
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5906514193138747816}
m_CullTransparentMesh: 1
--- !u!114 &1953891385698885950
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5906514193138747816}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.LayoutElement
m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: -1
m_PreferredHeight: -1
m_FlexibleWidth: -1
m_FlexibleHeight: -1
m_LayoutPriority: 1
--- !u!114 &-3146704326252051464
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5906514193138747816}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0c14350aeeed44a28d98d22c6ef048dc, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.AnswerPrefab
number: {fileID: 572009535857796838}
dialogText: {fileID: 3412282869295099737}
--- !u!1 &6684607543305325759
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7428637175488290741}
- component: {fileID: 8466763491809017645}
- component: {fileID: 3412282869295099737}
m_Layer: 5
m_Name: Text
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7428637175488290741
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6684607543305325759}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5249586234698548752}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 214.33, y: -12.023}
m_SizeDelta: {x: 340.22, y: 24.046}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8466763491809017645
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6684607543305325759}
m_CullTransparentMesh: 1
--- !u!114 &3412282869295099737
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6684607543305325759}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Charge The Line Charge The Line Charge The Line Charge The Line Charge
The Line Charge The Line Charge The Line Charge The Line Charge The Line Charge
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_sharedMaterial: {fileID: 9074173216178389243, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4278783248
m_fontColor: {r: 0.0627451, g: 0.050980397, b: 0.03529412, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 8.9
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 2.6
m_fontSizeMax: 12
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 7.1723022, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: cbecff27dee2cf7448a05a89ecb018b4
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,697 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3617559978782513519
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8477970123459414041}
- component: {fileID: 3077754775864774321}
- component: {fileID: 3649549507639781181}
m_Layer: 5
m_Name: Mask
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8477970123459414041
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3617559978782513519}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7039252932434566139}
m_Father: {fileID: 7107336662030716891}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &3077754775864774321
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3617559978782513519}
m_CullTransparentMesh: 1
--- !u!114 &3649549507639781181
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3617559978782513519}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 0}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &3853719035858582054
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4900680696536290555}
- component: {fileID: 502023626210869990}
- component: {fileID: 6074527782412359595}
m_Layer: 5
m_Name: Text
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4900680696536290555
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3853719035858582054}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7039252932434566139}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.48286262}
m_AnchorMax: {x: 0.6627312, y: 1}
m_AnchoredPosition: {x: 0.9819946, y: -38.289}
m_SizeDelta: {x: 1.62, y: -42.331}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &502023626210869990
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3853719035858582054}
m_CullTransparentMesh: 1
--- !u!114 &6074527782412359595
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3853719035858582054}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: A group of Gargoyles has blocked the road. They are chanting abd blah
bla
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_sharedMaterial: {fileID: 9074173216178389243, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4279507489
m_fontColor: {r: 0.12941177, g: 0.10196079, b: 0.078431375, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 13.1
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 7.8
m_fontSizeMax: 13.1
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 256
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 26.800018, y: 6.367523, z: 6.807068, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &4043707640276751891
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 565728455484042611}
- component: {fileID: 2681516528620939688}
- component: {fileID: 1883240519542694916}
m_Layer: 5
m_Name: Art
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &565728455484042611
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4043707640276751891}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7039252932434566139}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.6627312, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: -14.5, y: 0.000015258789}
m_SizeDelta: {x: -32.578293, y: -65.75531}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2681516528620939688
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4043707640276751891}
m_CullTransparentMesh: 1
--- !u!114 &1883240519542694916
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4043707640276751891}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 6cb6255ee69dbf04abe2eac591388adf, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &4690676139639527418
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5610124364099563801}
- component: {fileID: 3458576624150439327}
- component: {fileID: 1362417063745413028}
m_Layer: 5
m_Name: Title
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5610124364099563801
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4690676139639527418}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7039252932434566139}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.8264123}
m_AnchorMax: {x: 0.6627312, y: 1}
m_AnchoredPosition: {x: -0.80999756, y: -15.64299}
m_SizeDelta: {x: 1.62, y: -33.7364}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &3458576624150439327
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4690676139639527418}
m_CullTransparentMesh: 1
--- !u!114 &1362417063745413028
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4690676139639527418}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Encounter Title
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_sharedMaterial: {fileID: 9074173216178389243, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4279507489
m_fontColor: {r: 0.12941177, g: 0.10196079, b: 0.078431375, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 26.9
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 6.97
m_fontSizeMax: 45.4
m_fontStyle: 1
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 21.254028, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &4791155219053449426
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4897385661531424469}
- component: {fileID: 7326620177005582428}
- component: {fileID: 7295291249677778017}
m_Layer: 5
m_Name: AnswersContainer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4897385661531424469
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4791155219053449426}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7039252932434566139}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0.6627312, y: 0.43427482}
m_AnchoredPosition: {x: 0.9819946, y: 13.1859}
m_SizeDelta: {x: 1.62, y: -26.6202}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7326620177005582428
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4791155219053449426}
m_CullTransparentMesh: 1
--- !u!114 &7295291249677778017
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4791155219053449426}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.VerticalLayoutGroup
m_Padding:
m_Left: 0
m_Right: 0
m_Top: 0
m_Bottom: 0
m_ChildAlignment: 0
m_Spacing: 1
m_ChildForceExpandWidth: 1
m_ChildForceExpandHeight: 0
m_ChildControlWidth: 1
m_ChildControlHeight: 0
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!1 &6989683072839887398
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7107336662030716891}
- component: {fileID: 5489237150592293923}
- component: {fileID: 5723139269595044}
- component: {fileID: 1343977848673373576}
- component: {fileID: 3705563528526877357}
m_Layer: 5
m_Name: EncounterReference
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7107336662030716891
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6989683072839887398}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0, y: 0, z: 0}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8477970123459414041}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!223 &5489237150592293923
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6989683072839887398}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 0
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_VertexColorAlwaysGammaSpace: 1
m_AdditionalShaderChannelsFlag: 25
m_UpdateRectTransformForStandalone: 0
m_SortingLayerID: 0
m_SortingOrder: 100
m_TargetDisplay: 0
--- !u!114 &5723139269595044
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6989683072839887398}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.CanvasScaler
m_UiScaleMode: 0
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 800, y: 600}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 3
m_FallbackScreenDPI: 96
m_DefaultSpriteDPI: 96
m_DynamicPixelsPerUnit: 1
m_PresetInfoIsWorld: 0
--- !u!114 &1343977848673373576
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6989683072839887398}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.GraphicRaycaster
m_IgnoreReversedGraphics: 1
m_BlockingObjects: 0
m_BlockingMask:
serializedVersion: 2
m_Bits: 4294967295
--- !u!114 &3705563528526877357
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6989683072839887398}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0173ea7fbf1e45b1932694938ecd3058, type: 3}
m_Name:
m_EditorClassIdentifier: Jovian.EncounterSystem::Jovian.EncounterSystem.EncounterReference
encounterName: {fileID: 1362417063745413028}
encounterDescription: {fileID: 6074527782412359595}
encounterArt: {fileID: 1883240519542694916}
encounterOptionsContainer: {fileID: 4897385661531424469}
--- !u!1 &8084146734087207726
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7039252932434566139}
- component: {fileID: 7810011449154573601}
- component: {fileID: 4925850881383289972}
m_Layer: 5
m_Name: Background
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7039252932434566139
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8084146734087207726}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 565728455484042611}
- {fileID: 5610124364099563801}
- {fileID: 4900680696536290555}
- {fileID: 4897385661531424469}
m_Father: {fileID: 8477970123459414041}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: -510.3443, y: -262.6666}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7810011449154573601
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8084146734087207726}
m_CullTransparentMesh: 1
--- !u!114 &4925850881383289972
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8084146734087207726}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 0.7882353}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 52125a3c3df558448a5af5a04dbf8d2d, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 62525e62adc83b84abde85d78828de2b
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -374,6 +374,141 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &899987077
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 899987078}
- component: {fileID: 899987079}
m_Layer: 0
m_Name: RedMystEast_1
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &899987078
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 899987077}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 7.289, y: 0, z: 3.48}
m_LocalScale: {x: 0.2, y: 0.2, z: 0.2}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2065324670}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &899987079
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 899987077}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 95af4f7ff0649854598833eabd84f131, type: 3}
m_Name:
m_EditorClassIdentifier: Jovian.ZoneSystem::Jovian.ZoneSystem.ZoneInstance
data: {fileID: 11400000, guid: b8ae323df4686334d91ad4d9b22f4159, type: 2}
--- !u!1 &1037239273
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1037239274}
- component: {fileID: 1037239275}
m_Layer: 0
m_Name: Codrii Vasluiului
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1037239274
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1037239273}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 2.46, y: 0, z: 0.06}
m_LocalScale: {x: 0.2, y: 0.2, z: 0.2}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2065324670}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1037239275
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1037239273}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 95af4f7ff0649854598833eabd84f131, type: 3}
m_Name:
m_EditorClassIdentifier: Jovian.ZoneSystem::Jovian.ZoneSystem.ZoneInstance
data: {fileID: 11400000, guid: 4eefe490fd756c947b300b6f3d697df4, type: 2}
--- !u!1 &1056456186
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1056456187}
- component: {fileID: 1056456188}
m_Layer: 0
m_Name: Thievs Corener
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1056456187
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1056456186}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 3.31, y: 0, z: 6.1}
m_LocalScale: {x: 0.2, y: 0.2, z: 0.2}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2065324670}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1056456188
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1056456186}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 95af4f7ff0649854598833eabd84f131, type: 3}
m_Name:
m_EditorClassIdentifier: Jovian.ZoneSystem::Jovian.ZoneSystem.ZoneInstance
data: {fileID: 11400000, guid: 499c88e149852754ab0a9a5d551f7eea, type: 2}
--- !u!1 &1342894008
GameObject:
m_ObjectHideFlags: 0
@@ -420,6 +555,51 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1853369441
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1853369442}
- component: {fileID: 1853369443}
m_Layer: 0
m_Name: South Road
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1853369442
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1853369441}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 6.95, y: 0, z: 1.7}
m_LocalScale: {x: 0.2, y: 0.2, z: 0.2}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2065324670}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1853369443
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1853369441}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 95af4f7ff0649854598833eabd84f131, type: 3}
m_Name:
m_EditorClassIdentifier: Jovian.ZoneSystem::Jovian.ZoneSystem.ZoneInstance
data: {fileID: 11400000, guid: 263de6ccb4b79c340883df4a1d555220, type: 2}
--- !u!1001 &2065324669
PrefabInstance:
m_ObjectHideFlags: 0
@@ -512,9 +692,26 @@ PrefabInstance:
m_RemovedGameObjects:
- {fileID: 7700777388891455207, guid: e152c7d154fb4da419d61245d532e8ca, type: 3}
- {fileID: 6524685290382203959, guid: e152c7d154fb4da419d61245d532e8ca, type: 3}
m_AddedGameObjects: []
m_AddedGameObjects:
- targetCorrespondingSourceObject: {fileID: 926535160506351424, guid: e152c7d154fb4da419d61245d532e8ca, type: 3}
insertIndex: -1
addedObject: {fileID: 899987078}
- targetCorrespondingSourceObject: {fileID: 926535160506351424, guid: e152c7d154fb4da419d61245d532e8ca, type: 3}
insertIndex: -1
addedObject: {fileID: 1853369442}
- targetCorrespondingSourceObject: {fileID: 926535160506351424, guid: e152c7d154fb4da419d61245d532e8ca, type: 3}
insertIndex: -1
addedObject: {fileID: 1037239274}
- targetCorrespondingSourceObject: {fileID: 926535160506351424, guid: e152c7d154fb4da419d61245d532e8ca, type: 3}
insertIndex: -1
addedObject: {fileID: 1056456187}
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: e152c7d154fb4da419d61245d532e8ca, type: 3}
--- !u!4 &2065324670 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 926535160506351424, guid: e152c7d154fb4da419d61245d532e8ca, type: 3}
m_PrefabInstance: {fileID: 2065324669}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &2263217030056493631
PrefabInstance:
m_ObjectHideFlags: 0
@@ -680,6 +877,50 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5547799966266031405, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_fontSize
value: 32.83
objectReference: {fileID: 0}
- target: {fileID: 5547799966266031405, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_fontSizeMax
value: 32.83
objectReference: {fileID: 0}
- target: {fileID: 5547799966266031405, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_fontSizeMin
value: 4.7
objectReference: {fileID: 0}
- target: {fileID: 5547799966266031405, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_enableAutoSizing
value: 1
objectReference: {fileID: 0}
- target: {fileID: 5547799966266031405, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_HorizontalAlignment
value: 2
objectReference: {fileID: 0}
- target: {fileID: 7031164879444458698, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_AnchorMin.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7031164879444458698, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_AnchorMin.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 7031164879444458698, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_SizeDelta.x
value: -45.73
objectReference: {fileID: 0}
- target: {fileID: 7031164879444458698, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_SizeDelta.y
value: 60.911
objectReference: {fileID: 0}
- target: {fileID: 7031164879444458698, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_AnchoredPosition.x
value: -24.620117
objectReference: {fileID: 0}
- target: {fileID: 7031164879444458698, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_AnchoredPosition.y
value: 2.125
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
@@ -707,7 +948,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 660494562578339291, guid: 3a1b48d52adea3347acf44510bdb6fc3, type: 3}
propertyPath: m_LocalPosition.x
value: -5.33
value: 36.49
objectReference: {fileID: 0}
- target: {fileID: 660494562578339291, guid: 3a1b48d52adea3347acf44510bdb6fc3, type: 3}
propertyPath: m_LocalPosition.y
@@ -715,7 +956,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 660494562578339291, guid: 3a1b48d52adea3347acf44510bdb6fc3, type: 3}
propertyPath: m_LocalPosition.z
value: 5.13
value: 2.61
objectReference: {fileID: 0}
- target: {fileID: 660494562578339291, guid: 3a1b48d52adea3347acf44510bdb6fc3, type: 3}
propertyPath: m_LocalRotation.w

View File

@@ -1286,6 +1286,21 @@ MonoBehaviour:
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 667489615
- m_FirstAdjustmentRecord:
m_GlyphIndex: 70
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.26367188
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 70
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 72
m_GlyphValueRecord:
@@ -1346,6 +1361,681 @@ MonoBehaviour:
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 667489615
- m_FirstAdjustmentRecord:
m_GlyphIndex: 81
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.3515625
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 92
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 81
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.3515625
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 190
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 81
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.3515625
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 192
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 82
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.3515625
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 90
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 82
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.1425781
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 91
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 82
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.6152344
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 92
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 82
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.6152344
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 190
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 82
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.6152344
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 192
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0986328
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 68
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.92285156
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 70
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0546875
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 71
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 72
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 82
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.8457031
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 84
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.52734375
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0986328
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 161
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0986328
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 162
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0986328
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 163
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0986328
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 164
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0986328
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 165
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0986328
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 166
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0986328
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 167
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 168
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 169
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 170
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 171
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 172
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 177
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 179
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 180
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 181
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 182
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 183
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 185
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0986328
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 194
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0986328
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 196
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0986328
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 198
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 200
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 206
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 212
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 216
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 271
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.0986328
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 329
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 333
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.6699219
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 341
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 2105283919
- m_FirstAdjustmentRecord:
m_GlyphIndex: 90
m_GlyphValueRecord:

View File

@@ -657,6 +657,51 @@ MonoBehaviour:
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 0
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -4.745117
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 15
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 0
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -4.745117
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 17
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 0
- m_FirstAdjustmentRecord:
m_GlyphIndex: 85
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 3.1914062
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 2020
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 0
- m_FirstAdjustmentRecord:
m_GlyphIndex: 90
m_GlyphValueRecord:

View File

@@ -109,3 +109,20 @@ Assets/Code/
- Factory pattern for character/party creation
- Action delegates for UI event communication (e.g., `menuGameStateData.startGameRequests += handler`)
- Mixed async patterns: both `async Task` and `IEnumerator` coroutines for async operations
## Planning Docs Convention
Non-trivial features are planned in `docs/plans/` as paired markdown files: a design doc and an implementation doc, both prefixed with the date. Examples: `2026-04-05-ingame-logging-design.md` + `2026-04-05-ingame-logging-implementation.md`, `2026-04-06-popup-system-design.md` + `2026-04-06-popup-system-implementation.md`. When starting a new feature, look here first for existing context, and follow the same pair-of-docs pattern for new work.
## In-House Jovian Packages
Several packages under `Packages/` are first-party code maintained alongside the game, not third-party dependencies. Before adding new capabilities, check whether one of these already provides what you need:
- `Jovian.SaveSystem` — JSON persistence, used by `GamePersistenceController`
- `Jovian.Calendar` — custom in-game calendar system
- `Jovian.InGameLogging` — runtime logging surface
- `Jovian.EncounterSystem` — data-driven encounter authoring, `IEncounterKind` polymorphic payloads, `EncounterLink` cross-table refs, `QuestProgress` gated progression + `QuestLog`. Designer browser at `Jovian → Encounters → Encounter Browser`.
- `Jovian.PopupSystem` — popup/dialog UI
- `Jovian.ZoneSystem` — zone/region management
- `Jovian.Logger` — developer logging
- `Jovian.InspectorTools` / `JovianUtilities` — editor and general utilities

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 361fc968822691543a13717f28a81b18
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
{
"name": "Jovian.Calendar.Editor",
"rootNamespace": "Jovian.Calendar.Editor",
"references": [
"Jovian.Calendar"
],
"includePlatforms": ["Editor"],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f267cb10ab07ff54584ed67eb6e56e65
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
MIT License
Copyright (c) 2026 uzihead
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: aa2cf3e5447578e44abea28c081c281d
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,151 @@
# Jovian Calendar
A configurable in-game calendar and world clock system for Unity. Supports custom day lengths, hours, minutes, months with variable lengths, named months, week tracking, and a serializable date-time struct. No external dependencies.
## Requirements
- Unity 2022.3 or later
- No additional package dependencies
## Quick Start
### 1. Create a CalendarSettings asset
In the Unity Editor, go to **Assets > Create > Jovian > Calendar > Calendar Settings**.
Configure:
- **Seconds Per Full Day**: How many real-time seconds equal one full in-game day (the 0-1 cycle)
- **Hours Per Day**: In-world hours per day (e.g. 24)
- **Minutes Per Hour**: In-world minutes per hour (e.g. 60)
- **Days Per Month**: Array defining the length of each month. Array length = months per year
- **Month Names**: Display names for each month (must match Days Per Month length)
- **Days Per Week**: Optional week length (0 to disable)
- **Start Date**: Starting year, month, day, hour, minute for the clock
### 2. Create and tick a WorldClock
```csharp
using Jovian.Calendar;
// Create the clock from settings
var clock = new WorldClock(calendarSettings);
// Each frame, feed it a 0-1 normalized day progress
clock.Tick(normalizedDayTime);
// Query the current date and time
WorldDateTime now = clock.Now;
Debug.Log($"Year {now.year}, {clock.GetMonthName()} {now.DisplayDay}, {now.TimeString}");
```
### 3. Display the date
```csharp
// Individual fields
int year = clock.Now.year;
int month = clock.Now.DisplayMonth; // 1-indexed
int day = clock.Now.DisplayDay; // 1-indexed
string time = clock.Now.TimeString; // "HH:MM"
// Full display string
string full = clock.FullStringNamed();
// e.g. "14:30, 5th day of Frostmoon, year 3"
```
## CalendarSettings
ScriptableObject defining calendar rules. Create via **Assets > Create > Jovian > Calendar > Calendar Settings**.
| Field | Type | Description |
|---|---|---|
| `secondsPerFullDay` | float | Real-time seconds for one full 0-1 day cycle |
| `hoursPerDay` | int | In-world hours per day |
| `minutesPerHour` | int | In-world minutes per hour |
| `daysPerMonth` | int[] | Days in each month. Array length = months per year |
| `monthNames` | string[] | Display name per month. Must match daysPerMonth length |
| `daysPerWeek` | int | Days per week (0 to disable week tracking) |
| `startYear` | int | Starting year |
| `startMonth` | int | Starting month (0-indexed) |
| `startDay` | int | Starting day (0-indexed) |
| `startHour` | int | Starting hour |
| `startMinute` | int | Starting minute |
**Computed properties:**
- `MonthsPerYear` -- derived from daysPerMonth array length
- `TotalDaysInYear` -- sum of all daysPerMonth entries
- `MinutesPerDay` -- hoursPerDay * minutesPerHour
## WorldClock
The core clock class. Feed it a normalized 0-1 day progress each tick. It accumulates world-minutes internally, handling day wrap-around and fractional minute accumulation across frames.
```csharp
var clock = new WorldClock(settings);
// Tick with normalized time (0 = midnight, 0.5 = noon, 1 = next midnight)
clock.Tick(normalizedTime);
// Manual time skip (sleep, rest, cutscene)
clock.AdvanceMinutes(480); // skip 8 hours
// Queries
WorldDateTime now = clock.Now;
long elapsed = clock.TotalElapsedMinutes;
float normalized = clock.NormalizedTimeOfDay; // 0-1 for lighting/skybox
int weekday = clock.DayOfWeek; // 0-indexed, -1 if disabled
string monthName = clock.GetMonthName();
string display = clock.FullStringNamed();
```
## WorldDateTime
A serializable struct representing a point in calendar time. Implements `IEquatable<WorldDateTime>` and `IComparable<WorldDateTime>` for collections and sorting.
```csharp
WorldDateTime dt = clock.Now;
// 0-indexed fields
dt.year; dt.month; dt.day; dt.hour; dt.minute;
// 1-indexed display properties
dt.DisplayDay; // day + 1
dt.DisplayMonth; // month + 1
// Formatting
dt.TimeString; // "14:30"
dt.DateString; // "5/3/1"
dt.FullString; // "5/3/1 14:30"
// Comparison
if(dateA < dateB) { ... }
if(dateA == dateB) { ... }
var sorted = dates.OrderBy(d => d);
```
## Integration Example
```csharp
// In your game state initialization:
var calendarSettings = Addressables.LoadAssetAsync<CalendarSettings>("CalendarSettings").WaitForCompletion();
var worldClock = new WorldClock(calendarSettings);
// In your time handler's Tick():
float normalizedTime = localTime / dayLength;
worldClock.Tick(normalizedTime);
// Update UI:
dayText.text = $"Day {worldClock.Now.DisplayDay}, {worldClock.GetMonthName()}";
// Use NormalizedTimeOfDay for visual effects:
float t = worldClock.NormalizedTimeOfDay;
skyboxMaterial.SetFloat("_Blend", t);
directionalLight.intensity = sunCurve.Evaluate(t);
```
## API Reference
| Type | Description |
|---|---|
| `CalendarSettings` | ScriptableObject defining calendar rules (day length, months, weeks, start date) |
| `WorldClock` | Core clock class. Tick with normalized time, query WorldDateTime |
| `WorldDateTime` | Serializable struct for date-time values. IEquatable, IComparable, operator overloads |

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3b2f99c9462058d47ae5f4d667d063d4
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5171b66295e446142a89186f5d91bb16
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,98 @@
using System;
using UnityEngine;
namespace Jovian.Calendar {
/// <summary>
/// ScriptableObject defining the rules of an in-game calendar: day length, hours, minutes,
/// month structure, month names, week length, and starting date. Create via
/// Assets > Create > Jovian > Calendar > Calendar Settings.
/// </summary>
[CreateAssetMenu(fileName = "CalendarSettings", menuName = "Jovian/Calendar/Calendar Settings")]
public class CalendarSettings : ScriptableObject {
/// <summary>How many real-time seconds one full 0 to 1 float cycle represents.</summary>
public float secondsPerFullDay;
/// <summary>How many in-world hours per day (e.g. 24, or 16 for a shorter day).</summary>
public int hoursPerDay;
/// <summary>How many in-world minutes per hour (e.g. 60).</summary>
public int minutesPerHour;
/// <summary>
/// Days in each month, in order. Length of this array defines months per year.
/// E.g. { 30, 28, 31 } = 3 months with different lengths.
/// </summary>
public int[] daysPerMonth;
/// <summary>
/// Custom month names. Must match daysPerMonth.Length.
/// </summary>
public string[] monthNames;
/// <summary>Optional: days per week for week-tracking. 0 to disable.</summary>
public int daysPerWeek;
// --- Starting date ---
public int startYear;
public int startMonth; // 0-indexed
public int startDay; // 0-indexed
public int startHour;
public int startMinute;
/// <summary>Number of months in a year, derived from daysPerMonth array length.</summary>
public int MonthsPerYear => daysPerMonth?.Length ?? 0;
/// <summary>Total days in one full year.</summary>
public int TotalDaysInYear {
get {
var total = 0;
if(daysPerMonth == null) {
return 0;
}
foreach(var t in daysPerMonth) {
total += t;
}
return total;
}
}
/// <summary>Total in-world minutes in a single day.</summary>
public int MinutesPerDay => hoursPerDay * minutesPerHour;
/// <summary>Validates all calendar parameters. Throws ArgumentException on invalid configuration.</summary>
public void Validate() {
if(secondsPerFullDay <= 0f) {
throw new ArgumentException("SecondsPerFullDay must be > 0");
}
if(hoursPerDay <= 0) {
throw new ArgumentException("HoursPerDay must be > 0");
}
if(minutesPerHour <= 0) {
throw new ArgumentException("MinutesPerHour must be > 0");
}
if(daysPerMonth == null || daysPerMonth.Length == 0) {
throw new ArgumentException("DaysPerMonth must have at least one entry");
}
if(monthNames == null || monthNames.Length != daysPerMonth.Length) {
throw new ArgumentException("MonthNames length must match DaysPerMonth length");
}
for(var i = 0; i < daysPerMonth.Length; i++) {
if(daysPerMonth[i] <= 0) {
throw new ArgumentException($"DaysPerMonth[{i}] must be > 0");
}
}
if(startMonth < 0 || startMonth >= daysPerMonth.Length) {
throw new ArgumentException("StartMonth out of range");
}
if(startDay < 0 || startDay >= daysPerMonth[startMonth]) {
throw new ArgumentException("StartDay out of range for StartMonth");
}
if(startHour < 0 || startHour >= hoursPerDay) {
throw new ArgumentException("StartHour out of range");
}
if(startMinute < 0 || startMinute >= minutesPerHour) {
throw new ArgumentException("StartMinute out of range");
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e3a6df85a820d0a4db469ae8a20ea773

View File

@@ -0,0 +1,14 @@
{
"name": "Jovian.Calendar",
"rootNamespace": "Jovian.Calendar",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 237923931c0f9cf4ea0d30f11d58dda7
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,214 @@
namespace Jovian.Calendar {
/// <summary>
/// Core calendar clock. Feed it a 0-1 normalized day float each tick.
/// Internally accumulates world-minutes and rolls them into the calendar.
/// </summary>
public class WorldClock {
/// <summary>The calendar configuration driving this clock.</summary>
public CalendarSettings Settings { get; }
/// <summary>The current world date and time.</summary>
public WorldDateTime Now { get; private set; }
/// <summary>
/// Total in-world minutes elapsed since the start date.
/// This is the single source of truth. WorldDateTime is derived from it.
/// </summary>
public long TotalElapsedMinutes { get; private set; }
/// <summary>The normalized time (0-1) from the last tick.</summary>
public float LastNormalizedTime { get; private set; }
private float prevNormalized;
private bool initialized;
private float fractionalMinutes;
private readonly long startOffsetMinutes;
/// <summary>
/// Creates a new world clock from the given calendar settings.
/// Validates settings and initializes to the configured start date.
/// </summary>
public WorldClock(CalendarSettings settings) {
settings.Validate();
Settings = settings;
startOffsetMinutes = ComputeMinuteOffset(
settings, settings.startYear, settings.startMonth,
settings.startDay, settings.startHour, settings.startMinute
);
TotalElapsedMinutes = 0;
prevNormalized = -1f;
initialized = false;
Now = MakeDateTime(startOffsetMinutes);
}
/// <summary>
/// Call every frame with the current normalized day progress (0..1).
/// The clock detects the delta since last tick and advances time accordingly.
/// Handles wrap-around (1 to 0 = new day crossing).
/// </summary>
public void Tick(float normalizedTime) {
normalizedTime = Clamp01(normalizedTime);
LastNormalizedTime = normalizedTime;
if(!initialized) {
prevNormalized = normalizedTime;
initialized = true;
return;
}
var delta = normalizedTime - prevNormalized;
if(delta < 0f) {
delta += 1f;
}
if(delta < 1e-7f) {
prevNormalized = normalizedTime;
return;
}
var minutesAdvanced = delta * Settings.MinutesPerDay;
fractionalMinutes += minutesAdvanced;
var wholeMinutes = (int)fractionalMinutes;
if(wholeMinutes > 0) {
fractionalMinutes -= wholeMinutes;
TotalElapsedMinutes += wholeMinutes;
Now = MakeDateTime(startOffsetMinutes + TotalElapsedMinutes);
}
prevNormalized = normalizedTime;
}
/// <summary>
/// Manually advance the clock by a number of in-world minutes.
/// Useful for sleep/rest skips, cutscenes, etc.
/// </summary>
public void AdvanceMinutes(int minutes) {
if(minutes <= 0) {
return;
}
TotalElapsedMinutes += minutes;
Now = MakeDateTime(startOffsetMinutes + TotalElapsedMinutes);
var dayFraction = (float)((Now.hour * Settings.minutesPerHour) + Now.minute) / Settings.MinutesPerDay;
prevNormalized = dayFraction;
}
/// <summary>
/// Converts a total-minutes-from-epoch value into a WorldDateTime.
/// </summary>
private WorldDateTime MakeDateTime(long totalMinutes) {
if(totalMinutes < 0) {
totalMinutes = 0;
}
var minutesPerDay = Settings.MinutesPerDay;
var minutesPerHour = Settings.minutesPerHour;
var totalDays = totalMinutes / minutesPerDay;
var remainderMinutes = (int)(totalMinutes % minutesPerDay);
var hour = remainderMinutes / minutesPerHour;
var minute = remainderMinutes % minutesPerHour;
var daysInYear = Settings.TotalDaysInYear;
var year = (int)(totalDays / daysInYear);
var remainingDays = (int)(totalDays % daysInYear);
var month = 0;
for(var m = 0; m < Settings.daysPerMonth.Length; m++) {
if(remainingDays < Settings.daysPerMonth[m]) {
month = m;
break;
}
remainingDays -= Settings.daysPerMonth[m];
if(m == Settings.daysPerMonth.Length - 1) {
month = m;
break;
}
}
return new WorldDateTime {
year = year,
month = month,
day = remainingDays,
hour = hour,
minute = minute
};
}
/// <summary>
/// Inverse of MakeDateTime: given a calendar date, produce total minutes from epoch.
/// </summary>
private static long ComputeMinuteOffset(
CalendarSettings s, int year, int month, int day, int hour, int minute) {
var totalDays = (long)year * s.TotalDaysInYear;
for(var m = 0; m < month; m++) {
totalDays += s.daysPerMonth[m];
}
totalDays += day;
var totalMinutes = totalDays * s.MinutesPerDay;
totalMinutes += (long)hour * s.minutesPerHour;
totalMinutes += minute;
return totalMinutes;
}
/// <summary>
/// Get the current day-of-week (0-indexed), or -1 if weeks are disabled.
/// </summary>
public int DayOfWeek {
get {
if(Settings.daysPerWeek <= 0) {
return -1;
}
var totalDays = (startOffsetMinutes + TotalElapsedMinutes) / Settings.MinutesPerDay;
return (int)(totalDays % Settings.daysPerWeek);
}
}
/// <summary>
/// Normalized time of day as 0-1 float, derived from the current WorldDateTime.
/// Useful for lighting, skybox lerp, etc.
/// </summary>
public float NormalizedTimeOfDay {
get {
float currentMinute = (Now.hour * Settings.minutesPerHour) + Now.minute;
return currentMinute / Settings.MinutesPerDay;
}
}
/// <summary>Returns the name of the current month from settings.</summary>
public string GetMonthName() {
var month = Now.month;
if(Settings.monthNames == null || month < 0 || month >= Settings.monthNames.Length) {
return "???";
}
return Settings.monthNames[month];
}
/// <summary>Returns a full display string with named month and ordinal day.</summary>
public string FullStringNamed() {
var displayDay = Now.day;
var postFix = displayDay switch {
1 => "st",
2 => "nd",
3 => "rd",
_ => "th"
};
var year = Now.year;
var timeString = Now.TimeString;
return $"{timeString}, {displayDay}{postFix} day of {GetMonthName()}, \nyear {year}";
}
private static float Clamp01(float v) {
return v < 0f ? 0f : v > 1f ? 1f : v;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5121873037b1b704dbee5b3f060332d9

View File

@@ -0,0 +1,92 @@
using System;
namespace Jovian.Calendar {
/// <summary>
/// Represents a point in world-calendar time. Display-friendly.
/// All fields are 0-indexed internally; display properties are 1-indexed where expected.
/// </summary>
[Serializable]
public struct WorldDateTime : IEquatable<WorldDateTime>, IComparable<WorldDateTime> {
public int year;
public int month; // 0-indexed
public int day; // 0-indexed
public int hour;
public int minute;
/// <summary>1-indexed day for display.</summary>
public int DisplayDay => day + 1;
/// <summary>1-indexed month for display.</summary>
public int DisplayMonth => month + 1;
/// <summary>Returns "HH:MM" style time string.</summary>
public string TimeString => $"{hour:D2}:{minute:D2}";
/// <summary>Returns "Day/Month/Year" display string (1-indexed).</summary>
public string DateString => $"{DisplayDay}/{DisplayMonth}/{year}";
/// <summary>Returns full "Day/Month/Year HH:MM".</summary>
public string FullString => $"{DateString} {TimeString}";
public bool Equals(WorldDateTime other) {
return year == other.year && month == other.month && day == other.day
&& hour == other.hour && minute == other.minute;
}
public int CompareTo(WorldDateTime other) {
var c = year.CompareTo(other.year);
if(c != 0) {
return c;
}
c = month.CompareTo(other.month);
if(c != 0) {
return c;
}
c = day.CompareTo(other.day);
if(c != 0) {
return c;
}
c = hour.CompareTo(other.hour);
if(c != 0) {
return c;
}
return minute.CompareTo(other.minute);
}
public override bool Equals(object obj) {
return obj is WorldDateTime other && Equals(other);
}
public override int GetHashCode() {
return HashCode.Combine(year, month, day, hour, minute);
}
public override string ToString() {
return FullString;
}
public static bool operator ==(WorldDateTime a, WorldDateTime b) {
return a.Equals(b);
}
public static bool operator !=(WorldDateTime a, WorldDateTime b) {
return !a.Equals(b);
}
public static bool operator <(WorldDateTime a, WorldDateTime b) {
return a.CompareTo(b) < 0;
}
public static bool operator >(WorldDateTime a, WorldDateTime b) {
return a.CompareTo(b) > 0;
}
public static bool operator <=(WorldDateTime a, WorldDateTime b) {
return a.CompareTo(b) <= 0;
}
public static bool operator >=(WorldDateTime a, WorldDateTime b) {
return a.CompareTo(b) >= 0;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 14218276a99cfd94d805fff6fbbb621e

View File

@@ -0,0 +1,14 @@
# Calendar Samples
## Settings
| Asset | Description |
|---|---|
| `CalendarSettings` | Example calendar configuration with fantasy month names and a 10-second day cycle |
## How to use
1. Import the samples via the Unity Package Manager (select the package, expand Samples, click Import)
2. Copy the CalendarSettings asset into your project
3. Adjust the values to match your game's calendar (day length, months, month names, etc.)
4. Load via Addressables or direct reference and pass to `new WorldClock(settings)`

View File

@@ -0,0 +1,29 @@
%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: e3a6df85a820d0a4db469ae8a20ea773, type: 3}
m_Name: CalendarSettings
m_EditorClassIdentifier: Assembly-CSharp::Nox.Game.CalendarSettings
secondsPerFullDay: 60
hoursPerDay: 24
minutesPerHour: 60
daysPerMonth: 5a0000005a0000005a0000005a000000
monthNames:
- Ashveil
- Thornmere
- Duskhollow
- 'Frosthollow '
daysPerWeek: 7
startYear: 4232
startMonth: 1
startDay: 0
startHour: 8
startMinute: 0

View File

@@ -0,0 +1,16 @@
{
"name": "com.jovian.calendar",
"version": "0.1.0",
"displayName": "Jovian Calendar",
"description": "A configurable in-game calendar and world clock system with custom months, day lengths, week tracking, and serializable date-time.",
"unity": "2022.3",
"keywords": [
"calendar",
"time",
"clock",
"date"
],
"author": {
"name": "Jovian"
}
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f75f1da22b70e43499179c6452e92709
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7d89f89053ce0384c9f7b48a5b491bca
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,106 @@
using Jovian.EncounterSystem;
using UnityEditor;
using UnityEngine;
namespace Jovian.EncounterSystem.Editor {
/// <summary>Id dropdown (library inherited from the owning asset's <c>library</c> field) + inline fallback + resolved preview.</summary>
[CustomPropertyDrawer(typeof(DialogLineRef))]
public class DialogLineRefDrawer : PropertyDrawer {
private const string NonePlaceholder = "<none>";
private const string EmptyLibraryPlaceholder = "<set library on the parent asset>";
private const float PreviewHeight = 32f;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
var idProp = property.FindPropertyRelative("id");
var inlineProp = property.FindPropertyRelative("inlineText");
var library = ResolveLibrary(property);
EditorGUI.BeginProperty(position, label, property);
var lineHeight = EditorGUIUtility.singleLineHeight;
var spacing = EditorGUIUtility.standardVerticalSpacing;
var idRect = new Rect(position.x, position.y, position.width, lineHeight);
DrawIdPicker(idRect, library, idProp, label);
var inlineRect = new Rect(
position.x,
position.y + lineHeight + spacing,
position.width,
lineHeight * 2);
EditorGUI.PropertyField(inlineRect, inlineProp, new GUIContent("Inline"));
var previewRect = new Rect(
position.x,
position.y + lineHeight + spacing + lineHeight * 2 + spacing,
position.width,
PreviewHeight);
DrawPreview(previewRect, library, idProp, inlineProp);
EditorGUI.EndProperty();
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
var lineHeight = EditorGUIUtility.singleLineHeight;
var spacing = EditorGUIUtility.standardVerticalSpacing;
// id + (inline 2 lines) + preview
return lineHeight + spacing + lineHeight * 2 + spacing + PreviewHeight;
}
private static DialogLineLibrary ResolveLibrary(SerializedProperty property) {
var libraryProp = property.serializedObject.FindProperty("library");
return libraryProp?.objectReferenceValue as DialogLineLibrary;
}
private static void DrawIdPicker(Rect rect, DialogLineLibrary library, SerializedProperty idProp, GUIContent label) {
if(library == null || library.lines == null || library.lines.Count == 0) {
using(new EditorGUI.DisabledScope(true)) {
EditorGUI.Popup(rect, label.text, 0, new[] { EmptyLibraryPlaceholder });
}
return;
}
var count = library.lines.Count;
var ids = new string[count + 1];
var names = new string[count + 1];
ids[0] = string.Empty;
names[0] = NonePlaceholder;
var currentIndex = 0;
for(int i = 0; i < count; i++) {
var line = library.lines[i];
var id = line?.id ?? string.Empty;
ids[i + 1] = id;
names[i + 1] = string.IsNullOrEmpty(id) ? $"<unnamed {i}>" : id;
if(id == idProp.stringValue && !string.IsNullOrEmpty(id)) {
currentIndex = i + 1;
}
}
var newIndex = EditorGUI.Popup(rect, label.text, currentIndex, names);
if(newIndex != currentIndex) {
idProp.stringValue = ids[newIndex];
}
}
private static void DrawPreview(Rect rect, DialogLineLibrary library, SerializedProperty idProp, SerializedProperty inlineProp) {
var id = idProp.stringValue;
var inline = inlineProp.stringValue;
string resolved = null;
if(library != null && !string.IsNullOrEmpty(id)) {
resolved = library.Resolve(id);
}
if(string.IsNullOrEmpty(resolved)) {
resolved = inline;
}
var style = new GUIStyle(EditorStyles.helpBox) {
fontStyle = FontStyle.Italic,
wordWrap = true
};
var label = string.IsNullOrEmpty(resolved) ? "<no text will display>" : resolved;
EditorGUI.LabelField(rect, new GUIContent("Preview: " + label), style);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a55b866cc153f5749a71928930faeb62

View File

@@ -0,0 +1,673 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Jovian.EncounterSystem;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace Jovian.EncounterSystem.Editor {
/// <summary>Browser for every encounter across all tables. Search + kind filter + detail pane. Quest chains render as a tree rooted at the first step.</summary>
public class EncounterBrowserWindow : EditorWindow {
private const string AllKinds = "All";
private class Record {
public EncounterTable table;
public int index;
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 string searchText = string.Empty;
private string kindFilter = AllKinds;
private readonly Dictionary<IEncounter, List<ValidationIssue>> issuesByEncounter = new();
private TreeView treeView;
private VisualElement detailPane;
private ToolbarMenu kindDropdown;
private VisualElement statusBanner;
[MenuItem("Jovian/Encounters/Encounter Browser")]
public static void Open() {
var window = GetWindow<EncounterBrowserWindow>("Encounters");
window.minSize = new Vector2(640, 360);
}
private void CreateGUI() {
BuildToolbar();
BuildSplit();
Refresh();
}
private void BuildToolbar() {
var toolbar = new Toolbar();
var search = new ToolbarSearchField();
search.style.flexGrow = 1f;
search.RegisterValueChangedCallback(evt => {
searchText = evt.newValue ?? string.Empty;
ApplyFilter();
});
toolbar.Add(search);
kindDropdown = new ToolbarMenu { text = $"Kind: {AllKinds}" };
foreach(var choice in GetKindChoices()) {
var captured = choice;
kindDropdown.menu.AppendAction(captured, _ => {
kindFilter = captured;
kindDropdown.text = $"Kind: {captured}";
ApplyFilter();
});
}
toolbar.Add(kindDropdown);
var refreshButton = new ToolbarButton(Refresh) { text = "Refresh" };
toolbar.Add(refreshButton);
rootVisualElement.Add(toolbar);
}
private void BuildSplit() {
statusBanner = new VisualElement {
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);
treeView = new TreeView {
makeItem = MakeRow,
bindItem = BindRow,
fixedItemHeight = 22,
selectionType = SelectionType.Single
};
treeView.selectionChanged += OnSelectionChanged;
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);
detailPane = new ScrollView(ScrollViewMode.Vertical) {
style = { paddingLeft = 8, paddingTop = 8, paddingRight = 8, flexGrow = 1f }
};
ShowEmptyDetail();
split.Add(detailPane);
}
private static VisualElement MakeRow() {
var row = new VisualElement {
style = {
flexDirection = FlexDirection.Row,
alignItems = Align.Center,
paddingLeft = 6,
paddingRight = 6,
height = 22,
flexGrow = 1f,
flexShrink = 0f
}
};
var badge = new VisualElement {
name = "issue-badge",
style = {
width = 8,
height = 8,
marginRight = 6,
borderTopLeftRadius = 4,
borderTopRightRadius = 4,
borderBottomLeftRadius = 4,
borderBottomRightRadius = 4,
visibility = Visibility.Hidden
}
};
row.Add(badge);
var label = new Label {
name = "row-label",
style = {
flexGrow = 1f,
unityTextAlign = TextAnchor.MiddleLeft
}
};
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;
}
private void BindRow(VisualElement element, int index) {
var record = treeView.GetItemDataForIndex<Record>(index);
var label = element.Q<Label>("row-label");
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 kind = record.encounter?.EncounterDefinition?.Kind?.GetType().Name ?? "—";
label.text = string.IsNullOrEmpty(name)
? $"<unnamed> [{kind}]"
: $"{name} [{kind}]";
if(record.encounter != null && issuesByEncounter.TryGetValue(record.encounter, out var issues) && issues.Count > 0) {
var hasError = issues.Exists(i => i.severity == ValidationSeverity.Error);
badge.style.backgroundColor = new StyleColor(hasError ? new Color(0.85f, 0.25f, 0.25f) : new Color(0.95f, 0.75f, 0.1f));
badge.style.visibility = Visibility.Visible;
element.tooltip = BuildTooltip(issues);
}
else {
badge.style.visibility = Visibility.Hidden;
element.tooltip = string.Empty;
}
}
private static string BuildTooltip(List<ValidationIssue> issues) {
var lines = new List<string>(issues.Count);
foreach(var issue in issues) {
var prefix = issue.severity == ValidationSeverity.Error ? "ERROR" : "WARN";
lines.Add($"[{prefix}] {issue.path} — {issue.message}");
}
return string.Join("\n", lines);
}
private static IEnumerable<string> GetKindChoices() {
yield return AllKinds;
var kindTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => {
try { return assembly.GetTypes(); }
catch { return Array.Empty<Type>(); }
})
.Where(type => typeof(IEncounterKind).IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface)
.Select(type => type.Name)
.OrderBy(name => name);
foreach(var name in kindTypes) {
yield return name;
}
}
private void Refresh() {
allRecords.Clear();
var registries = FindAssetsOfType<EncounterRegistry>().ToList();
UpdateStatusBanner(registries);
var seenTables = new HashSet<EncounterTable>();
foreach(var registry in registries) {
if(registry?.encounterCollections == null) {
continue;
}
foreach(var collection in registry.encounterCollections) {
if(collection?.encounterTables == null) {
continue;
}
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]
});
}
}
}
}
RebuildIssueIndex();
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() {
issuesByEncounter.Clear();
var issues = EncounterValidator.ValidateProject();
foreach(var issue in issues) {
if(issue.encounter == null) {
continue;
}
if(!issuesByEncounter.TryGetValue(issue.encounter, out var list)) {
list = new List<ValidationIssue>();
issuesByEncounter[issue.encounter] = list;
}
list.Add(issue);
}
}
private void ApplyFilter() {
var filtered = allRecords.Where(Matches).ToList();
var items = BuildTreeItems(filtered);
if(treeView == null) {
return;
}
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();
}
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>();
foreach(var r in records) {
if(r.encounter != null) {
byEncounter[r.encounter] = r;
}
}
// Chain nesting only applies to chains contained within this table. Cross-table chains
// naturally appear flat (the target encounter lives under its own table header).
var predecessorCount = new Dictionary<IEncounter, int>();
foreach(var r in records) {
if(r.encounter?.EncounterDefinition?.Kind is not QuestKind quest) {
continue;
}
var next = quest.nextEncounter.Resolve();
if(next != null && byEncounter.ContainsKey(next)) {
predecessorCount.TryGetValue(next, out var count);
predecessorCount[next] = count + 1;
}
}
var parentOf = new Dictionary<IEncounter, IEncounter>();
foreach(var r in records) {
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;
}
r.depth = depth;
var rootId = uid++;
var children = BuildChainChildren(r, byEncounter, parentOf, depth + 1, ref uid);
nodes.Add(new TreeViewItemData<Record>(rootId, r, children));
}
return nodes;
}
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>>();
if(root.encounter?.EncounterDefinition?.Kind is not QuestKind) {
return children;
}
var current = root.encounter;
var visited = new HashSet<IEncounter> { current };
var currentDepth = depth;
while(current?.EncounterDefinition?.Kind is QuestKind quest) {
var next = quest.nextEncounter.Resolve();
if(next == null || !visited.Add(next)) {
break;
}
if(!byEncounter.TryGetValue(next, out var nextRecord)) {
break;
}
if(!parentOf.TryGetValue(next, out var parent) || parent != current) {
break;
}
nextRecord.depth = currentDepth;
children.Add(new TreeViewItemData<Record>(uid++, nextRecord));
current = next;
currentDepth++;
}
return children;
}
private bool Matches(Record record) {
var kindName = record.encounter?.EncounterDefinition?.Kind?.GetType().Name ?? string.Empty;
if(kindFilter != AllKinds && kindName != kindFilter) {
return false;
}
if(string.IsNullOrEmpty(searchText)) {
return true;
}
var needle = searchText.ToLowerInvariant();
var definition = record.encounter?.EncounterDefinition;
return Contains(definition?.id, needle)
|| Contains(definition?.name, needle)
|| Contains(definition?.description, needle);
}
private static bool Contains(string source, string needle) {
return !string.IsNullOrEmpty(source) && source.ToLowerInvariant().Contains(needle);
}
private void OnSelectionChanged(IEnumerable<object> selection) {
var record = selection.OfType<Record>().FirstOrDefault();
if(record == null) {
ShowEmptyDetail();
return;
}
if(record.IsTableHeader) {
ShowTableHeaderDetail(record.table);
return;
}
detailPane.Clear();
var serializedObject = new SerializedObject(record.table);
var encountersProp = serializedObject.FindProperty(nameof(EncounterTable.encounters));
var elementProp = encountersProp.GetArrayElementAtIndex(record.index);
var headerRow = new VisualElement {
style = {
flexDirection = FlexDirection.Row,
alignItems = Align.Center,
marginBottom = 6
}
};
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;
var field = new PropertyField(elementProp);
field.Bind(serializedObject);
detailPane.Add(field);
AddChainPreviewIfQuest(record);
}
private void AddChainPreviewIfQuest(Record record) {
if(record.encounter?.EncounterDefinition?.Kind is not QuestKind questKind) {
return;
}
var predecessor = FindPredecessor(record.encounter.EncounterDefinition?.internalId);
var next = questKind.nextEncounter.Resolve();
var predName = predecessor?.encounter.EncounterDefinition?.name ?? "—";
var currName = record.encounter.EncounterDefinition?.name ?? "<unnamed>";
var nextName = next?.EncounterDefinition?.name ?? "—";
var chainLabel = new Label($"Chain: {predName} ← {currName} → {nextName}") {
style = {
marginTop = 12,
paddingTop = 6,
paddingBottom = 6,
paddingLeft = 6,
paddingRight = 6,
backgroundColor = new StyleColor(new Color(0.2f, 0.2f, 0.2f, 0.4f)),
unityFontStyleAndWeight = FontStyle.Bold
}
};
detailPane.Add(chainLabel);
}
private Record FindPredecessor(string targetId) {
if(string.IsNullOrEmpty(targetId)) {
return null;
}
foreach(var record in allRecords) {
if(record.encounter?.EncounterDefinition?.Kind is not QuestKind kind) {
continue;
}
var next = kind.nextEncounter.Resolve();
if(next?.EncounterDefinition?.internalId == targetId) {
return record;
}
}
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() {
if(detailPane == null) {
return;
}
detailPane.Clear();
var empty = new Label("Select an encounter to edit.") {
style = { color = new StyleColor(Color.gray), marginTop = 8 }
};
detailPane.Add(empty);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0312d015c183e2f4582358d17867585c

View File

@@ -0,0 +1,76 @@
using Jovian.EncounterSystem;
using UnityEditor;
using UnityEngine;
namespace Jovian.EncounterSystem.Editor {
/// <summary>Label list elements with the option's text id (fallback: inline text preview, then default).</summary>
[CustomPropertyDrawer(typeof(EncounterDialogOption))]
public class EncounterDialogOptionDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
var displayLabel = ResolveLabel(property, label);
var foldoutRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, displayLabel, true);
if(!property.isExpanded) {
return;
}
EditorGUI.indentLevel++;
var y = position.y + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
var iterator = property.Copy();
var end = iterator.GetEndProperty();
if(iterator.NextVisible(true)) {
while(!SerializedProperty.EqualContents(iterator, end)) {
var h = EditorGUI.GetPropertyHeight(iterator, true);
var r = new Rect(position.x, y, position.width, h);
EditorGUI.PropertyField(r, iterator, true);
y += h + EditorGUIUtility.standardVerticalSpacing;
if(!iterator.NextVisible(false)) {
break;
}
}
}
EditorGUI.indentLevel--;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
var height = EditorGUIUtility.singleLineHeight;
if(!property.isExpanded) {
return height;
}
var iterator = property.Copy();
var end = iterator.GetEndProperty();
if(iterator.NextVisible(true)) {
while(!SerializedProperty.EqualContents(iterator, end)) {
height += EditorGUI.GetPropertyHeight(iterator, true) + EditorGUIUtility.standardVerticalSpacing;
if(!iterator.NextVisible(false)) {
break;
}
}
}
return height;
}
private static GUIContent ResolveLabel(SerializedProperty property, GUIContent fallback) {
var textProp = property.FindPropertyRelative("text");
if(textProp == null) {
return fallback;
}
var id = textProp.FindPropertyRelative("id")?.stringValue;
if(!string.IsNullOrEmpty(id)) {
return new GUIContent(id);
}
var inline = textProp.FindPropertyRelative("inlineText")?.stringValue;
if(!string.IsNullOrEmpty(inline)) {
var preview = inline.Length > 40 ? inline.Substring(0, 40) + "…" : inline;
return new GUIContent(preview);
}
return fallback;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5636dc9f15ce02c4ca189c3d5f46eb34

View File

@@ -0,0 +1,76 @@
using UnityEditor;
using UnityEngine;
namespace Jovian.EncounterSystem.Editor {
/// <summary>Label list elements with the encounter id (fallback: name, then default).</summary>
[CustomPropertyDrawer(typeof(Encounter))]
public class EncounterDrawer : PropertyDrawer {
private const string DefinitionBackingField = "<EncounterDefinition>k__BackingField";
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
var displayLabel = ResolveLabel(property, label);
var foldoutRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, displayLabel, true);
if(!property.isExpanded) {
return;
}
EditorGUI.indentLevel++;
var y = position.y + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
var iterator = property.Copy();
var end = iterator.GetEndProperty();
if(iterator.NextVisible(true)) {
while(!SerializedProperty.EqualContents(iterator, end)) {
var h = EditorGUI.GetPropertyHeight(iterator, true);
var r = new Rect(position.x, y, position.width, h);
EditorGUI.PropertyField(r, iterator, true);
y += h + EditorGUIUtility.standardVerticalSpacing;
if(!iterator.NextVisible(false)) {
break;
}
}
}
EditorGUI.indentLevel--;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
var height = EditorGUIUtility.singleLineHeight;
if(!property.isExpanded) {
return height;
}
var iterator = property.Copy();
var end = iterator.GetEndProperty();
if(iterator.NextVisible(true)) {
while(!SerializedProperty.EqualContents(iterator, end)) {
height += EditorGUI.GetPropertyHeight(iterator, true) + EditorGUIUtility.standardVerticalSpacing;
if(!iterator.NextVisible(false)) {
break;
}
}
}
return height;
}
private static GUIContent ResolveLabel(SerializedProperty property, GUIContent fallback) {
var definition = property.FindPropertyRelative(DefinitionBackingField);
if(definition == null) {
return fallback;
}
var id = definition.FindPropertyRelative("id")?.stringValue;
if(!string.IsNullOrEmpty(id)) {
return new GUIContent(id);
}
var name = definition.FindPropertyRelative("name")?.stringValue;
if(!string.IsNullOrEmpty(name)) {
return new GUIContent(name);
}
return fallback;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0ee5ffe2ea6903547ac75470249af31f

View File

@@ -0,0 +1,82 @@
using Jovian.EncounterSystem;
using UnityEditor;
using UnityEngine;
namespace Jovian.EncounterSystem.Editor {
/// <summary>Table object-field + encounter dropdown picker. Changing tables clears the id.</summary>
[CustomPropertyDrawer(typeof(EncounterLink))]
public class EncounterLinkDrawer : PropertyDrawer {
private const string NonePlaceholder = "<none>";
private const string EmptyTablePlaceholder = "<select a table first>";
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
var tableProp = property.FindPropertyRelative("table");
var idProp = property.FindPropertyRelative("internalId");
EditorGUI.BeginProperty(position, label, property);
var lineHeight = EditorGUIUtility.singleLineHeight;
var spacing = EditorGUIUtility.standardVerticalSpacing;
var tableRect = new Rect(position.x, position.y, position.width, lineHeight);
var encounterRect = new Rect(position.x, position.y + lineHeight + spacing, position.width, lineHeight);
EditorGUI.BeginChangeCheck();
EditorGUI.PropertyField(tableRect, tableProp, label);
var tableChanged = EditorGUI.EndChangeCheck();
using(new EditorGUI.IndentLevelScope()) {
var table = tableProp.objectReferenceValue as EncounterTable;
if(table == null || table.encounters == null || table.encounters.Count == 0) {
using(new EditorGUI.DisabledScope(true)) {
EditorGUI.Popup(encounterRect, "Encounter", 0, new[] { EmptyTablePlaceholder });
}
if(tableChanged) {
idProp.stringValue = string.Empty;
}
}
else {
DrawEncounterPicker(encounterRect, table, idProp, tableChanged);
}
}
EditorGUI.EndProperty();
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
return EditorGUIUtility.singleLineHeight * 2 + EditorGUIUtility.standardVerticalSpacing;
}
private static void DrawEncounterPicker(Rect rect, EncounterTable table, SerializedProperty idProp, bool tableChanged) {
var count = table.encounters.Count;
var ids = new string[count + 1];
var names = new string[count + 1];
ids[0] = string.Empty;
names[0] = NonePlaceholder;
var currentIndex = 0;
for(int i = 0; i < count; i++) {
var encounter = table.encounters[i];
var id = encounter?.EncounterDefinition?.internalId ?? string.Empty;
var name = encounter?.EncounterDefinition?.name;
ids[i + 1] = id;
names[i + 1] = string.IsNullOrEmpty(name)
? $"<unnamed> ({encounter?.GetType().Name ?? "null"})"
: name;
if(!tableChanged && id == idProp.stringValue && !string.IsNullOrEmpty(id)) {
currentIndex = i + 1;
}
}
if(tableChanged) {
idProp.stringValue = string.Empty;
currentIndex = 0;
}
var newIndex = EditorGUI.Popup(rect, "Encounter", currentIndex, names);
if(newIndex != currentIndex) {
idProp.stringValue = ids[newIndex];
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 385fe4b7b2663e54aa3f520a809a33bc

View File

@@ -0,0 +1,335 @@
using System.Collections.Generic;
using Jovian.EncounterSystem;
using UnityEditor;
using UnityEngine;
namespace Jovian.EncounterSystem.Editor {
public enum ValidationSeverity {
Warning,
Error
}
public class ValidationIssue {
public Object asset;
public Encounter encounter;
public string path;
public ValidationSeverity severity;
public string message;
}
/// <summary>Project-wide scan of encounter tables and rewards. Runs on demand, no caching.</summary>
public static class EncounterValidator {
public static List<ValidationIssue> ValidateProject() {
var issues = new List<ValidationIssue>();
ValidateRegistries(issues);
var tables = FindAssetsOfType<EncounterTable>();
var idIndex = new Dictionary<string, (Encounter encounter, EncounterTable table)>();
foreach(var table in tables) {
ValidateTable(table, issues, idIndex);
}
foreach(var reward in FindAssetsOfType<Reward>()) {
ValidateReward(reward, 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) {
var issues = new List<ValidationIssue>();
if(table?.encounters == null || index < 0 || index >= table.encounters.Count) {
return issues;
}
var encounter = table.encounters[index];
ValidateEncounterEntry(table, index, encounter, issues, duplicateCheck: null);
return issues;
}
private static void ValidateTable(EncounterTable table, List<ValidationIssue> issues, Dictionary<string, (Encounter, EncounterTable)> idIndex) {
if(table?.encounters == null) {
return;
}
for(int i = 0; i < table.encounters.Count; i++) {
ValidateEncounterEntry(table, i, table.encounters[i], issues, idIndex);
}
}
private static void ValidateEncounterEntry(EncounterTable table, int index, Encounter encounter, List<ValidationIssue> issues, Dictionary<string, (Encounter, EncounterTable)> duplicateCheck) {
var pathPrefix = $"encounters[{index}]";
if(encounter == null) {
issues.Add(new ValidationIssue {
asset = table,
path = pathPrefix,
severity = ValidationSeverity.Error,
message = "Null encounter entry."
});
return;
}
var definition = encounter.EncounterDefinition;
if(definition == null || string.IsNullOrEmpty(definition.internalId)) {
issues.Add(new ValidationIssue {
asset = table,
encounter = encounter,
path = $"{pathPrefix}.EncounterDefinition.internalId",
severity = ValidationSeverity.Error,
message = "Missing internalId (cannot be referenced by EncounterLink)."
});
}
else if(duplicateCheck != null) {
if(duplicateCheck.TryGetValue(definition.internalId, out var prior)) {
issues.Add(new ValidationIssue {
asset = table,
encounter = encounter,
path = $"{pathPrefix}.EncounterDefinition.internalId",
severity = ValidationSeverity.Error,
message = $"Duplicate internalId '{definition.internalId}' (also in table '{prior.Item2.name}')."
});
}
else {
duplicateCheck[definition.internalId] = (encounter, table);
}
}
if(encounter.EncounterDefinition?.Kind == null) {
issues.Add(new ValidationIssue {
asset = table,
encounter = encounter,
path = $"{pathPrefix}.EncounterDefinition.Kind",
severity = ValidationSeverity.Warning,
message = "Encounter.Kind is null — pick a kind in the inspector."
});
}
if(encounter.EncounterDefinition?.Kind is QuestKind questKind) {
ValidateEncounterLink(table, pathPrefix + ".EncounterDefinition.Kind.nextEncounter", encounter, questKind.nextEncounter, issues);
}
ValidateDialogEvents(table, index, encounter, issues);
}
private static void ValidateEncounterLink(EncounterTable owningTable, string path, Encounter encounter, EncounterLink link, List<ValidationIssue> issues) {
// No id picked — terminal quest step / unset link. Not an error regardless of table value.
if(string.IsNullOrEmpty(link.internalId)) {
return;
}
if(link.table == null) {
issues.Add(new ValidationIssue {
asset = owningTable,
encounter = encounter,
path = path,
severity = ValidationSeverity.Error,
message = "EncounterLink has internalId set but no table assigned."
});
return;
}
if(link.Resolve() == null) {
issues.Add(new ValidationIssue {
asset = owningTable,
encounter = encounter,
path = path,
severity = ValidationSeverity.Error,
message = $"Broken EncounterLink — table '{link.table.name}' has no encounter with internalId '{link.internalId}'."
});
}
}
private static void ValidateDialogEvents(EncounterTable table, int index, Encounter encounter, List<ValidationIssue> issues) {
var optionSet = encounter.EncounterDialogOptionSet;
if(optionSet?.options == null) {
return;
}
for(int o = 0; o < optionSet.options.Count; o++) {
var option = optionSet.options[o];
if(option == null) {
continue;
}
ValidateDialogLineRef(optionSet, encounter, $"options[{o}].text", option.text, issues);
if(option.events == null) {
continue;
}
for(int e = 0; e < option.events.Count; e++) {
var evt = option.events[e];
if(evt == null) {
issues.Add(new ValidationIssue {
asset = optionSet,
encounter = encounter,
path = $"options[{o}].events[{e}]",
severity = ValidationSeverity.Warning,
message = "Null event entry (type may have been renamed/deleted)."
});
continue;
}
if(evt is GiveRewardEvent give && give.reward == null) {
issues.Add(new ValidationIssue {
asset = optionSet,
encounter = encounter,
path = $"options[{o}].events[{e}].reward",
severity = ValidationSeverity.Warning,
message = "GiveRewardEvent has no Reward asset assigned."
});
}
}
}
}
private static void ValidateDialogLineRef(EncounterDialogOptionSet optionSet, Encounter encounter, string path, DialogLineRef lineRef, List<ValidationIssue> issues) {
var library = optionSet.library;
var hasId = !string.IsNullOrEmpty(lineRef.id);
var hasInline = !string.IsNullOrEmpty(lineRef.inlineText);
if(!hasId && !hasInline) {
issues.Add(new ValidationIssue {
asset = optionSet,
encounter = encounter,
path = path,
severity = ValidationSeverity.Warning,
message = "Dialog line is empty (no id and no inline text)."
});
return;
}
if(hasId && library == null) {
issues.Add(new ValidationIssue {
asset = optionSet,
encounter = encounter,
path = path,
severity = ValidationSeverity.Error,
message = $"DialogLineRef references id '{lineRef.id}' but the option set has no library assigned."
});
return;
}
if(hasId && library != null && string.IsNullOrEmpty(library.Resolve(lineRef.id))) {
issues.Add(new ValidationIssue {
asset = optionSet,
encounter = encounter,
path = path,
severity = ValidationSeverity.Error,
message = $"DialogLineRef id '{lineRef.id}' not found in library '{library.name}'."
});
}
}
private static void ValidateReward(Reward reward, List<ValidationIssue> issues) {
if(reward == null) {
return;
}
if(reward.kind == null) {
issues.Add(new ValidationIssue {
asset = reward,
path = "kind",
severity = ValidationSeverity.Warning,
message = "Reward.kind is null — pick a reward kind in the inspector."
});
}
if(string.IsNullOrEmpty(reward.id)) {
issues.Add(new ValidationIssue {
asset = reward,
path = "id",
severity = ValidationSeverity.Warning,
message = "Reward has no id."
});
}
}
private static List<T> FindAssetsOfType<T>() where T : Object {
var result = new List<T>();
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) {
result.Add(asset);
}
}
return result;
}
}
public static class EncounterValidatorMenu {
[MenuItem("Jovian/Encounters/Validate All")]
public static void ValidateAll() {
var issues = EncounterValidator.ValidateProject();
if(issues.Count == 0) {
Debug.Log("[EncounterValidator] No issues found.");
return;
}
int errors = 0;
int warnings = 0;
foreach(var issue in issues) {
if(issue.severity == ValidationSeverity.Error) {
errors++;
}
else {
warnings++;
}
}
Debug.Log($"[EncounterValidator] {issues.Count} issue(s) found — {errors} error(s), {warnings} warning(s). Click any log row to ping the offending asset.");
foreach(var issue in issues) {
var assetName = issue.asset != null ? issue.asset.name : "<null>";
var message = $"[EncounterValidator] {assetName} · {issue.path} — {issue.message}";
if(issue.severity == ValidationSeverity.Error) {
Debug.LogError(message, issue.asset);
}
else {
Debug.LogWarning(message, issue.asset);
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More