Before 6.4 upgrade

This commit is contained in:
2026-05-13 20:29:56 +01:00
parent 602e1ec0d3
commit 806cf80110
38 changed files with 19990 additions and 16155 deletions

View File

@@ -9,7 +9,8 @@ It revolves around our central heroine, who's returned to her birthplace after h
But not all is what she thought, she was expecting a wondrous and vibrant land of mysticism and magicks, but instead
she comes across a desolate land of despair and terror. Vines have overgrown the villages, houses sit abandoned, and
the streets desolate. Her task (and the players) is to discover what happened to the lands once known as prosperous
and wonderful, and perhaps, just perhaps, discover herself in the process.
and wonderful, and perhaps, just perhaps, discover herself in the process. Keep the actual briars to a minium, and focus
mainly on vines and thorns.
## Gameplay Design

View File

@@ -99,6 +99,7 @@ namespace BriarQueen.Data.IO.Saves
{
None = 0,
MarketGateOpen,
MarketplaceFirstEntry,
}
[Serializable]

View File

@@ -28,7 +28,10 @@ namespace BriarQueen.Data.Identifiers
ChapterOneAshwickRidgeway,
ChapterOneInsideBrokenDownCar,
ChapterOneAshwickMarketplace,
ChapterOneHarrowVale,
ChapterOneAshwickMournfall,
ChapterOneAshwickRavensQuill,
ChapterOneGloomedVeil,
ChapterOneAshwickWaxworks
}
public enum AssetItemKey

View File

@@ -18,6 +18,7 @@ namespace BriarQueen.Data.Identifiers
public enum LevelInteractKey
{
None = 0,
MarketplaceFirstEntry
}
public enum EnvironmentInteractKey
@@ -32,6 +33,7 @@ namespace BriarQueen.Data.Identifiers
AshwickBlockedRidgwayRoad = 7,
AshwickRidgewaySkeleton = 8,
AskwickMarketplaceSign = 9,
FirstSkeleton = 10,
}
public enum UIInteractKey
@@ -60,6 +62,7 @@ namespace BriarQueen.Data.Identifiers
new ReadOnlyDictionary<LevelInteractKey, string>(
new Dictionary<LevelInteractKey, string>
{
{ LevelInteractKey.MarketplaceFirstEntry, "I wonder if any of these are unlocked."}
});
public static readonly IReadOnlyDictionary<EnvironmentInteractKey, string> EnvironmentInteractions =
@@ -72,7 +75,8 @@ namespace BriarQueen.Data.Identifiers
{ EnvironmentInteractKey.FireHot, "Too hot to get close." },
{ EnvironmentInteractKey.AshwickHallowSign, "Ashwick Hallow… Even the name feels like a warning."},
{ EnvironmentInteractKey.AshwickRidgewayStatue, "Lovely sculpture. Mildly terrifying, but lovely."},
{ EnvironmentInteractKey.AshwickBlockedRidgwayRoad, "Right. Closed road. Of course it is."}
{ EnvironmentInteractKey.AshwickBlockedRidgwayRoad, "Right. Closed road. Of course it is."},
{ EnvironmentInteractKey.FirstSkeleton, "What the hell happened here?"}
});
public static readonly IReadOnlyDictionary<UIInteractKey, string> UIInteractions =

View File

@@ -125,6 +125,11 @@ namespace BriarQueen.Framework.Managers.Player
return _codex?.GetEntriesByType(codexType) ?? Enumerable.Empty<CodexEntrySo>();
}
public bool AnyCodexEntriesForCategory(CodexType codexType)
{
return _codex != null && GetDiscoveredCodexEntriesByType(codexType).Any();
}
public bool HasCodexEntry(string uniqueIdentifier)
{
return _codex != null && _codex.HasEntry(uniqueIdentifier);

View File

@@ -1,4 +1,7 @@
using System.Threading;
using Cysharp.Threading.Tasks;
using PrimeTween;
using UnityEngine;
namespace BriarQueen.Framework.Managers.UI.Base
{
@@ -8,5 +11,6 @@ namespace BriarQueen.Framework.Managers.UI.Base
UniTask Hide();
WindowType WindowType { get; }
}
}

View File

@@ -306,6 +306,7 @@ namespace BriarQueen.Framework.Managers.UI
return;
var window = GetWindow(windowType);
if (window == null)
{
Debug.LogError($"[UIManager] Window of type {windowType} not registered.");
@@ -316,7 +317,10 @@ namespace BriarQueen.Framework.Managers.UI
return;
if (ActiveWindow != null)
{
await ActiveWindow.Hide();
}
_windowStack.Push(window);
await window.Show();

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c64fffd784df4e67be81962b3f485feb
timeCreated: 1778696777

View File

@@ -0,0 +1,24 @@
using BriarQueen.Data.Identifiers;
using BriarQueen.Data.IO.Saves;
using BriarQueen.Framework.Events.Save;
using BriarQueen.Framework.Events.UI;
using BriarQueen.Framework.Managers.Levels.Data;
using Cysharp.Threading.Tasks;
namespace BriarQueen.Game.Levels.ChapterOne.Ashwick
{
public class Marketplace : BaseLevel
{
protected override UniTask PostActivateInternal()
{
if (SaveManager.GetLevelFlag(LevelFlag.MarketplaceFirstEntry))
return UniTask.CompletedTask;
EventCoordinator.Publish(new DisplayInteractEvent(InteractEventIDs.Get(LevelInteractKey.MarketplaceFirstEntry)));
SaveManager.SetLevelFlag(LevelFlag.MarketplaceFirstEntry, true);
return UniTask.CompletedTask;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2d9beb847a184e2e897942fff18a396e
timeCreated: 1778696777

View File

@@ -48,7 +48,6 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow.GatePuzzle
private Color _blue = new(0.1490196f, 0.6001954f, 1f, 1f);
private bool _isChanging;
private bool _isLocked;
private StreetlightGlowState _currentState = StreetlightGlowState.Off;
public StreetlightGlowState CurrentState => _currentState;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using BriarQueen.Data.Identifiers;
using BriarQueen.Framework.Extensions;
using BriarQueen.Framework.Managers.Assets;
using BriarQueen.Framework.Managers.Interaction;
using BriarQueen.Framework.Managers.Player;
@@ -28,6 +29,7 @@ namespace BriarQueen.UI.Codex
{
[Header("Root UI")]
[SerializeField] private CanvasGroup _canvasGroup;
[SerializeField] private RectTransform _windowRect;
[Header("Content")]
@@ -35,22 +37,26 @@ namespace BriarQueen.UI.Codex
[Header("Left Panel — Header")]
[SerializeField] private TextMeshProUGUI _leftPanelTitleText;
[SerializeField] private CanvasGroup _leftPanelTitleGroup;
[Header("Left Panel — Categories")]
[SerializeField] private CanvasGroup _categoriesGroup;
[SerializeField] private UnderlineButton _booksButton;
[SerializeField] private UnderlineButton _cluesButton;
[SerializeField] private UnderlineButton _photosButton;
[Header("Left Panel — Locations")]
[SerializeField] private CanvasGroup _locationListGroup;
[SerializeField] private RectTransform _locationListContainer;
[SerializeField] private VerticalScrollbar _locationScrollbar;
[SerializeField] private Button _backToCategoriesButton;
[Header("Left Panel — Entries")]
[SerializeField] private CanvasGroup _entryListGroup;
[SerializeField] private RectTransform _entryListContainer;
[SerializeField] private VerticalScrollbar _entryScrollbar;
[SerializeField] private Button _backToLocationsButton;
@@ -58,6 +64,7 @@ namespace BriarQueen.UI.Codex
[Header("Right Panel — Display")]
[SerializeField] private CanvasGroup _rightPanelGroup;
[SerializeField] private RectTransform _rightPanelRoot;
[SerializeField] private TextMeshProUGUI _titleText;
[SerializeField] private CanvasGroup _titleGroup;
@@ -112,82 +119,45 @@ namespace BriarQueen.UI.Codex
[Header("Internal")]
[SerializeField] private GraphicRaycaster _graphicRaycaster;
private enum LeftPanelState { Categories, Locations, Entries }
private LeftPanelState _leftPanelState = LeftPanelState.Categories;
private CodexType _currentCategory = CodexType.DocumentEntry;
private Location _currentLocation = Location.None;
private CodexEntrySo _currentEntry;
private readonly List<CodexEntryButton> _activeEntryButtons = new();
private readonly List<CodexLocationButton> _activeLocationButtons = new();
private ObjectPool<CodexLocationButton> _locationButtonPool;
private ObjectPool<CodexEntryButton> _entryButtonPool;
private readonly Dictionary<string, float> _entryScrollByCategoryAndLocation = new();
private readonly Dictionary<CodexType, string> _lastEntryByCategory = new();
private readonly Dictionary<CodexType, Location> _lastLocationByCategory = new();
private readonly Dictionary<CodexType, float> _locationScrollByCategory = new();
private readonly Dictionary<string, float> _entryScrollByCategoryAndLocation = new();
private readonly Dictionary<CodexType, Location> _lastLocationByCategory = new();
private readonly Dictionary<CodexType, string> _lastEntryByCategory = new();
private AssetReference _locationButtonReference;
private AssetReference _entryButtonReference;
private CodexLocationButton _locationButtonTemplate;
private CodexEntryButton _entryButtonTemplate;
private bool _cached;
private bool _started;
private bool _raycasterRegistered;
private CancellationTokenSource _operationCts;
private Sequence _windowSequence;
private Sequence _leftPanelSequence;
private Sequence _displaySequence;
private Sequence _leftPanelTitleSequence;
private AddressableManager _addressableManager;
private AssetRegistry _assetRegistry;
private InteractManager _interactManager;
private PlayerManager _playerManager;
private bool _cached;
private CodexType _currentCategory = CodexType.DocumentEntry;
private CodexEntrySo _currentEntry;
private Location _currentLocation = Location.None;
private DestructionService _destructionService;
private Sequence _displaySequence;
private ObjectPool<CodexEntryButton> _entryButtonPool;
private AssetReference _entryButtonReference;
private CodexEntryButton _entryButtonTemplate;
private InteractManager _interactManager;
private Sequence _leftPanelSequence;
private LeftPanelState _leftPanelState = LeftPanelState.Categories;
private Sequence _leftPanelTitleSequence;
private ObjectPool<CodexLocationButton> _locationButtonPool;
private AssetReference _locationButtonReference;
private CodexLocationButton _locationButtonTemplate;
private CancellationTokenSource _operationCts;
private PlayerManager _playerManager;
private bool _raycasterRegistered;
private bool _started;
private Sequence _windowSequence;
public bool IsModal => true;
public WindowType WindowType => WindowType.CodexWindow;
// ── Raycaster ─────────────────────────────────────────────────
private void TryRegisterRaycaster()
{
Debug.Log($"[CodexWindow] TryRegisterRaycaster " +
$"registered={_raycasterRegistered} " +
$"interactManager={_interactManager != null} " +
$"raycaster={_graphicRaycaster != null}");
Debug.Log("[CodexWindow] Try register raycaster.");
if (_raycasterRegistered || _interactManager == null || _graphicRaycaster == null) return;
_interactManager.AddUIRaycaster(_graphicRaycaster);
_interactManager.SetExclusiveRaycaster(_graphicRaycaster);
_raycasterRegistered = true;
Debug.Log("[CodexWindow] Registered raycaster.");
}
private void TryUnregisterRaycaster()
{
Debug.Log("[CodexWindow] Try unregister raycaster.");
if (!_raycasterRegistered || _interactManager == null || _graphicRaycaster == null) return;
_interactManager.RemoveUIRaycaster(_graphicRaycaster);
_interactManager.ClearExclusiveRaycaster();
_raycasterRegistered = false;
Debug.Log("[CodexWindow] Raycaster unregistered.");
}
// ── Unity lifecycle ───────────────────────────────────────────
@@ -225,6 +195,28 @@ namespace BriarQueen.UI.Codex
await EnsurePoolsReady();
}
private void Update()
{
var mouse = UnityEngine.InputSystem.Mouse.current;
if (mouse == null || !mouse.leftButton.wasPressedThisFrame)
{
return;
}
var ev = UnityEngine.EventSystems.EventSystem.current;
if (ev == null)
{
Debug.Log("[Click] No EventSystem.current!");
return;
}
var pos = mouse.position.ReadValue();
var ped = new UnityEngine.EventSystems.PointerEventData(ev) { position = pos };
var results = new System.Collections.Generic.List<UnityEngine.EventSystems.RaycastResult>();
ev.RaycastAll(ped, results);
}
private void OnEnable()
{
BindCategoryButtons();
@@ -249,6 +241,21 @@ namespace BriarQueen.UI.Codex
TryUnregisterRaycaster();
}
// ── IUIBackHandler ────────────────────────────────────────────
public bool HandleBackRequest()
{
switch (_leftPanelState)
{
case LeftPanelState.Entries: NavigateBackToLocations().Forget(); return true;
case LeftPanelState.Locations: NavigateBackToCategories().Forget(); return true;
case LeftPanelState.Categories: return false;
default: return false;
}
}
public WindowType WindowType => WindowType.CodexWindow;
// ── IUIWindow ─────────────────────────────────────────────────
public async UniTask Show()
@@ -324,7 +331,7 @@ namespace BriarQueen.UI.Codex
_canvasGroup.alpha = 1f;
await TransitionToCategories(instant: true);
Debug.Log($"[CodexWindow] Codex Window Show Complete.");
}
public async UniTask Hide()
@@ -372,17 +379,38 @@ namespace BriarQueen.UI.Codex
Debug.Log($"[CodexWindow] Codex Window Hide Complete.");
}
// ── IUIBackHandler ────────────────────────────────────────────
// ── Raycaster ─────────────────────────────────────────────────
public bool HandleBackRequest()
private void TryRegisterRaycaster()
{
switch (_leftPanelState)
{
case LeftPanelState.Entries: NavigateBackToLocations().Forget(); return true;
case LeftPanelState.Locations: NavigateBackToCategories().Forget(); return true;
case LeftPanelState.Categories: return false;
default: return false;
}
Debug.Log($"[CodexWindow] TryRegisterRaycaster " +
$"registered={_raycasterRegistered} " +
$"interactManager={_interactManager != null} " +
$"raycaster={_graphicRaycaster != null}");
Debug.Log("[CodexWindow] Try register raycaster.");
if (_raycasterRegistered || _interactManager == null || _graphicRaycaster == null) return;
_interactManager.AddUIRaycaster(_graphicRaycaster);
_interactManager.SetExclusiveRaycaster(_graphicRaycaster);
_raycasterRegistered = true;
Debug.Log("[CodexWindow] Registered raycaster.");
}
private void TryUnregisterRaycaster()
{
Debug.Log("[CodexWindow] Try unregister raycaster.");
if (!_raycasterRegistered || _interactManager == null || _graphicRaycaster == null) return;
_interactManager.RemoveUIRaycaster(_graphicRaycaster);
_interactManager.ClearExclusiveRaycaster();
_raycasterRegistered = false;
Debug.Log("[CodexWindow] Raycaster unregistered.");
}
// ── DI ────────────────────────────────────────────────────────
@@ -505,7 +533,7 @@ namespace BriarQueen.UI.Codex
private void OnCluesClicked(UnderlineButton _) => NavigateToLocations(CodexType.PuzzleClue).Forget();
private void OnDocumentsClicked(UnderlineButton _) => NavigateToLocations(CodexType.DocumentEntry).Forget();
private void OnPhotosClicked(UnderlineButton _) => NavigateToLocations(CodexType.Photo).Forget();
private void OnLocationClicked(Location location) => NavigateToEntries(location).Forget();
@@ -597,6 +625,7 @@ namespace BriarQueen.UI.Codex
try
{
await FadeOutDisplay();
SetEmptyStateVisible(false);
await TransitionToCategories(instant: false);
ReleaseAllLocationButtons();
}
@@ -706,8 +735,10 @@ namespace BriarQueen.UI.Codex
_ => string.Empty
};
private static string GetLocationDisplayName(Location location) =>
location.ToString().Replace("_", " ");
private static string GetLocationDisplayName(Location location)
{
return location.ToString().Prettify();
}
// ── Display area ──────────────────────────────────────────────
@@ -748,9 +779,7 @@ namespace BriarQueen.UI.Codex
SetDisplayImmediate(false);
ClearDisplay();
var hasEntries = _playerManager?
.GetDiscoveredCodexEntriesByType(_currentCategory)
.Any(e => e != null) ?? false;
var hasEntries = _playerManager.AnyCodexEntriesForCategory(_currentCategory);
SetEmptyStateVisible(!hasEntries);
}
@@ -952,6 +981,7 @@ namespace BriarQueen.UI.Codex
button.Initialize(entry);
button.OnEntryClicked += OnEntryClicked;
_activeEntryButtons.Add(button);
if (_entryButtonGroup != null && button.UnderlineButton != null)
_entryButtonGroup.AddButton(button.UnderlineButton);
}
@@ -992,14 +1022,32 @@ namespace BriarQueen.UI.Codex
if (_photoDescription != null)
{
if (showPhotoDesc) { _photoDescription.gameObject.SetActive(true); _photoDescription.SetText(entry.PhotoDescription); }
else { _photoDescription.Clear(); _photoDescription.gameObject.SetActive(false); }
if (showPhotoDesc)
{
_photoDescription.gameObject.SetActive(true);
_photoDescription.SetText(entry.PhotoDescription);
_photoDescription.ScrollToTop();
}
else
{
_photoDescription.Clear();
_photoDescription.gameObject.SetActive(false);
}
}
if (_bodyText != null)
{
if (showText) { _bodyText.gameObject.SetActive(true); _bodyText.SetText(entry.BodyText); }
else { _bodyText.Clear(); _bodyText.gameObject.SetActive(false); }
if (showText)
{
_bodyText.gameObject.SetActive(true);
_bodyText.SetText(entry.BodyText);
}
else
{
_bodyText.Clear();
_bodyText.gameObject.SetActive(false);
}
}
SetEmptyStateVisible(false);
@@ -1089,7 +1137,7 @@ namespace BriarQueen.UI.Codex
}
// ── Binding ───────────────────────────────────────────────────
private void BindCategoryButtons()
{
if (_booksButton != null) _booksButton.SelectionRequested += OnDocumentsClicked;
@@ -1225,5 +1273,7 @@ namespace BriarQueen.UI.Codex
if (_leftPanelTitleSequence.isAlive) _leftPanelTitleSequence.Stop();
_leftPanelTitleSequence = default;
}
private enum LeftPanelState { Categories, Locations, Entries }
}
}

View File

@@ -110,7 +110,7 @@ namespace BriarQueen.UI.Components
LayoutRebuilder.ForceRebuildLayoutImmediate(_content);
yield return null;
_scrollbar?.Rebuild();
_scrollbar?.SetNormalized(1f);
_scrollbar?.SetNormalized(0f);
}
public void Clear()
@@ -138,7 +138,7 @@ namespace BriarQueen.UI.Components
_scrollbar?.Rebuild();
}
public void ScrollToTop() => _scrollbar?.SetNormalized(1f);
public void ScrollToBottom() => _scrollbar?.SetNormalized(0f);
public void ScrollToTop() => _scrollbar?.SetNormalized(0f);
public void ScrollToBottom() => _scrollbar?.SetNormalized(1f);
}
}

View File

@@ -67,6 +67,7 @@ namespace BriarQueen.UI.Menus.Components
public void OnPointerEnter(PointerEventData eventData)
{
Debug.Log($"[UnderlineButton] OnPointerEnter {gameObject.name}");
if (_button != null && !_button.interactable) return;
_isHovered = true;