first commit

This commit is contained in:
2026-06-04 20:14:47 +03:00
commit a70f7fe2b9
143 changed files with 19543 additions and 0 deletions
+108
View File
@@ -0,0 +1,108 @@
using UnityEngine;
using UnityEngine.UI;
public class DialogueUI : MonoBehaviour
{
public static DialogueUI Instance { get; private set; }
public GameObject root;
public Text nameText;
public Text bodyText;
public RectTransform responseContainer;
public Button responseButtonTemplate;
public bool IsOpen => root != null && root.activeSelf;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
Close();
}
public void Open(NPCDialogue npc, DialogueData dialogueData)
{
if (root == null || dialogueData == null)
{
return;
}
root.SetActive(true);
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
if (nameText != null)
{
nameText.text = dialogueData.npcName;
}
if (bodyText != null)
{
bodyText.text = dialogueData.greeting;
}
ClearResponses();
foreach (DialogueResponse response in dialogueData.responses)
{
Button button = Instantiate(responseButtonTemplate, responseContainer, false);
button.name = $"Response - {response.text}";
button.gameObject.SetActive(true);
Text text = button.GetComponentInChildren<Text>();
if (text != null)
{
text.text = response.text;
}
QuestData questToStart = response.questToStart;
button.onClick.AddListener(() =>
{
if (questToStart != null && QuestManager.Instance != null)
{
QuestManager.Instance.StartQuest(questToStart);
}
Close();
});
}
LayoutRebuilder.ForceRebuildLayoutImmediate(responseContainer);
}
public void Close()
{
if (root != null)
{
root.SetActive(false);
}
ClearResponses();
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
private void ClearResponses()
{
if (responseContainer == null)
{
return;
}
for (int i = responseContainer.childCount - 1; i >= 0; i--)
{
Transform child = responseContainer.GetChild(i);
if (responseButtonTemplate != null && child == responseButtonTemplate.transform)
{
continue;
}
Destroy(child.gameObject);
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 925b64e981cf522cfac0cba98e6500d8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+41
View File
@@ -0,0 +1,41 @@
using UnityEngine;
using UnityEngine.UI;
public class InteractionPromptUI : MonoBehaviour
{
public static InteractionPromptUI Instance { get; private set; }
public GameObject root;
public Text promptText;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
Hide();
}
public void Show(string message)
{
if (root == null || promptText == null || string.IsNullOrWhiteSpace(message))
{
return;
}
promptText.text = message;
root.SetActive(true);
}
public void Hide()
{
if (root != null)
{
root.SetActive(false);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 52b3b86afc5b4dd77917ebe683003683
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+158
View File
@@ -0,0 +1,158 @@
using UnityEngine;
using UnityEngine.UI;
public class InventoryUI : MonoBehaviour
{
public RectTransform content;
public Text outputText;
public Font uiFont;
public Color textColor = new Color(0.92f, 0.9f, 0.82f);
private float refreshTimer;
private string lastSignature;
private void OnEnable()
{
Subscribe();
Refresh();
}
private void Start()
{
Subscribe();
Refresh();
}
private void OnDisable()
{
if (Inventory.Instance != null)
{
Inventory.Instance.OnInventoryChanged -= Refresh;
}
}
private void Update()
{
refreshTimer -= Time.unscaledDeltaTime;
if (refreshTimer > 0f)
{
return;
}
refreshTimer = 0.25f;
Subscribe();
string signature = BuildSignature();
if (signature != lastSignature)
{
lastSignature = signature;
Refresh();
}
}
private void Subscribe()
{
if (Inventory.Instance != null)
{
Inventory.Instance.OnInventoryChanged -= Refresh;
Inventory.Instance.OnInventoryChanged += Refresh;
}
}
public void Refresh()
{
if (outputText != null)
{
outputText.text = BuildDisplayText();
return;
}
if (content == null)
{
return;
}
ClearContent();
if (Inventory.Instance == null || Inventory.Instance.Slots.Count == 0)
{
CreateLine("Пусто");
return;
}
foreach (Inventory.InventorySlot slot in Inventory.Instance.Slots)
{
if (slot.item == null)
{
continue;
}
CreateLine($"{slot.item.itemName} x{slot.amount}");
}
}
private string BuildDisplayText()
{
if (Inventory.Instance == null || Inventory.Instance.Slots.Count == 0)
{
return "Пусто";
}
System.Text.StringBuilder builder = new System.Text.StringBuilder();
foreach (Inventory.InventorySlot slot in Inventory.Instance.Slots)
{
if (slot.item == null)
{
continue;
}
builder.AppendLine($"{slot.item.itemName} x{slot.amount}");
}
return builder.Length > 0 ? builder.ToString().TrimEnd() : "Пусто";
}
private string BuildSignature()
{
if (Inventory.Instance == null)
{
return "inventory:null";
}
System.Text.StringBuilder builder = new System.Text.StringBuilder();
foreach (Inventory.InventorySlot slot in Inventory.Instance.Slots)
{
if (slot.item == null)
{
continue;
}
builder.Append(slot.item.itemId).Append(':').Append(slot.amount).Append('|');
}
return builder.ToString();
}
private void ClearContent()
{
for (int i = content.childCount - 1; i >= 0; i--)
{
Destroy(content.GetChild(i).gameObject);
}
}
private void CreateLine(string value)
{
GameObject line = new GameObject("Inventory Line", typeof(RectTransform), typeof(Text));
line.transform.SetParent(content, false);
Text text = line.GetComponent<Text>();
text.font = uiFont != null ? uiFont : Resources.GetBuiltinResource<Font>("Arial.ttf");
text.fontSize = 16;
text.color = textColor;
text.text = value;
RectTransform rect = line.GetComponent<RectTransform>();
rect.sizeDelta = new Vector2(0f, 24f);
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c9554462078ac6bc68e1dc1b149a5fe3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+67
View File
@@ -0,0 +1,67 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class NotificationUI : MonoBehaviour
{
public static NotificationUI Instance { get; private set; }
public Text messageText;
public CanvasGroup canvasGroup;
public float visibleTime = 2.8f;
public float fadeTime = 0.35f;
private readonly Queue<string> queue = new Queue<string>();
private float timer;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
if (canvasGroup == null)
{
canvasGroup = GetComponent<CanvasGroup>();
}
}
private void Update()
{
if (messageText == null || canvasGroup == null)
{
return;
}
if (timer > 0f)
{
timer -= Time.deltaTime;
canvasGroup.alpha = timer < fadeTime ? Mathf.Clamp01(timer / fadeTime) : 1f;
return;
}
if (queue.Count > 0)
{
messageText.text = queue.Dequeue();
timer = visibleTime + fadeTime;
canvasGroup.alpha = 1f;
}
else
{
canvasGroup.alpha = 0f;
}
}
public void Show(string message)
{
if (string.IsNullOrWhiteSpace(message))
{
return;
}
queue.Enqueue(message);
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6b3f91a3da3f8949696f87d49d1e45ed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+208
View File
@@ -0,0 +1,208 @@
using UnityEngine;
using UnityEngine.UI;
public class QuestLogUI : MonoBehaviour
{
public static QuestLogUI Instance { get; private set; }
public GameObject root;
public RectTransform content;
public Font uiFont;
public Color titleColor = new Color(1f, 0.74f, 0.25f);
public Color textColor = new Color(0.92f, 0.9f, 0.82f);
public Color mutedColor = new Color(0.7f, 0.7f, 0.7f);
public KeyCode toggleKey = KeyCode.J;
public bool IsOpen => root != null && root.activeSelf;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(this);
return;
}
Instance = this;
}
private void Start()
{
if (root != null)
{
root.SetActive(false);
}
Subscribe();
Refresh();
}
private void OnEnable()
{
Subscribe();
}
private void OnDisable()
{
if (QuestManager.Instance != null)
{
QuestManager.Instance.OnQuestsChanged -= Refresh;
}
}
private void Subscribe()
{
if (QuestManager.Instance != null)
{
QuestManager.Instance.OnQuestsChanged -= Refresh;
QuestManager.Instance.OnQuestsChanged += Refresh;
}
}
private void Update()
{
if (Input.GetKeyDown(toggleKey))
{
Toggle();
}
}
public void Toggle()
{
if (root == null)
{
return;
}
bool next = !root.activeSelf;
root.SetActive(next);
Cursor.lockState = next ? CursorLockMode.None : CursorLockMode.Locked;
Cursor.visible = next;
Refresh();
}
public void Refresh()
{
if (content == null)
{
return;
}
ClearContent();
if (QuestManager.Instance == null)
{
CreateText("QuestManager не найден", mutedColor, 16, FontStyle.Normal);
return;
}
CreateText("Активные", titleColor, 22, FontStyle.Bold);
if (QuestManager.Instance.ActiveQuests.Count == 0)
{
CreateText("Нет активных квестов", mutedColor, 16, FontStyle.Normal);
}
else
{
foreach (QuestState state in QuestManager.Instance.ActiveQuests)
{
CreateQuestBlock(state);
}
}
CreateText("Завершённые", titleColor, 22, FontStyle.Bold);
if (QuestManager.Instance.CompletedQuests.Count == 0)
{
CreateText("Пока пусто", mutedColor, 16, FontStyle.Normal);
}
else
{
foreach (QuestState state in QuestManager.Instance.CompletedQuests)
{
CreateQuestBlock(state);
}
}
if (QuestManager.Instance.FailedQuests.Count > 0)
{
CreateText("Проваленные", titleColor, 22, FontStyle.Bold);
foreach (QuestState state in QuestManager.Instance.FailedQuests)
{
CreateQuestBlock(state);
}
}
}
private void CreateQuestBlock(QuestState state)
{
if (state == null || state.questData == null)
{
return;
}
QuestData quest = state.questData;
CreateText(quest.questName, titleColor, 18, FontStyle.Bold);
CreateText(quest.description, textColor, 15, FontStyle.Normal);
CreateText($"Статус: {state.status}", mutedColor, 14, FontStyle.Normal);
for (int i = 0; i < quest.goals.Count; i++)
{
QuestGoal goal = quest.goals[i];
CreateText($"{goal.GetDisplayName()} {state.GetProgress(i)}/{goal.requiredAmount}", textColor, 15, FontStyle.Normal);
}
float percent = QuestManager.Instance.GetQuestCompletionPercent(state);
CreateText($"{BuildProgressBar(percent)} {Mathf.RoundToInt(percent * 100f)}%", titleColor, 15, FontStyle.Normal);
CreateSpacer(8f);
}
private string BuildProgressBar(float percent)
{
const int length = 10;
int filled = Mathf.RoundToInt(Mathf.Clamp01(percent) * length);
return new string('█', filled) + new string('░', length - filled);
}
private void ClearContent()
{
for (int i = content.childCount - 1; i >= 0; i--)
{
Destroy(content.GetChild(i).gameObject);
}
}
private void CreateSpacer(float height)
{
GameObject spacer = new GameObject("Quest Log Spacer", typeof(RectTransform));
spacer.transform.SetParent(content, false);
spacer.GetComponent<RectTransform>().sizeDelta = new Vector2(0f, height);
}
private void CreateText(string value, Color color, int size, FontStyle style)
{
GameObject line = new GameObject("Quest Log Text", typeof(RectTransform), typeof(Text));
line.transform.SetParent(content, false);
Text text = line.GetComponent<Text>();
text.font = uiFont != null ? uiFont : Resources.GetBuiltinResource<Font>("Arial.ttf");
text.fontSize = size;
text.fontStyle = style;
text.color = color;
text.text = value;
text.horizontalOverflow = HorizontalWrapMode.Wrap;
text.verticalOverflow = VerticalWrapMode.Overflow;
RectTransform rect = line.GetComponent<RectTransform>();
rect.sizeDelta = new Vector2(0f, Mathf.Max(size + 10f, EstimateHeight(value, size)));
}
private float EstimateHeight(string value, int size)
{
if (string.IsNullOrEmpty(value))
{
return size + 8f;
}
int lineCount = Mathf.Max(1, Mathf.CeilToInt(value.Length / 42f));
return lineCount * (size + 8f);
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6ed352b24b6a3787aa32532fcde461b8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+181
View File
@@ -0,0 +1,181 @@
using UnityEngine;
using UnityEngine.UI;
public class QuestTrackerUI : MonoBehaviour
{
public RectTransform content;
public Text outputText;
public Font uiFont;
public Color titleColor = new Color(1f, 0.74f, 0.25f);
public Color textColor = new Color(0.92f, 0.9f, 0.82f);
private float refreshTimer;
private string lastSignature;
private void OnEnable()
{
Subscribe();
Refresh();
}
private void Start()
{
Subscribe();
Refresh();
}
private void OnDisable()
{
if (QuestManager.Instance != null)
{
QuestManager.Instance.OnQuestsChanged -= Refresh;
}
}
private void Update()
{
refreshTimer -= Time.unscaledDeltaTime;
if (refreshTimer > 0f)
{
return;
}
refreshTimer = 0.25f;
Subscribe();
string signature = BuildSignature();
if (signature != lastSignature)
{
lastSignature = signature;
Refresh();
}
}
private void Subscribe()
{
if (QuestManager.Instance != null)
{
QuestManager.Instance.OnQuestsChanged -= Refresh;
QuestManager.Instance.OnQuestsChanged += Refresh;
}
}
public void Refresh()
{
if (outputText != null)
{
outputText.text = BuildDisplayText();
return;
}
if (content == null)
{
return;
}
ClearContent();
if (QuestManager.Instance == null || QuestManager.Instance.ActiveQuests.Count == 0)
{
CreateLine("Нет активных квестов", textColor, 15);
return;
}
foreach (QuestState state in QuestManager.Instance.ActiveQuests)
{
if (state.questData == null)
{
continue;
}
CreateLine(state.questData.questName, titleColor, 16);
for (int i = 0; i < state.questData.goals.Count; i++)
{
QuestGoal goal = state.questData.goals[i];
CreateLine($"{goal.GetDisplayName()} {state.GetProgress(i)}/{goal.requiredAmount}", textColor, 14);
}
}
}
private string BuildDisplayText()
{
if (QuestManager.Instance == null || QuestManager.Instance.ActiveQuests.Count == 0)
{
return "Нет активных квестов";
}
System.Text.StringBuilder builder = new System.Text.StringBuilder();
foreach (QuestState state in QuestManager.Instance.ActiveQuests)
{
if (state.questData == null)
{
continue;
}
builder.AppendLine(state.questData.questName);
for (int i = 0; i < state.questData.goals.Count; i++)
{
QuestGoal goal = state.questData.goals[i];
builder.Append(" ")
.Append(goal.GetDisplayName())
.Append(' ')
.Append(state.GetProgress(i))
.Append('/')
.Append(goal.requiredAmount)
.AppendLine();
}
}
return builder.Length > 0 ? builder.ToString().TrimEnd() : "Нет активных квестов";
}
private string BuildSignature()
{
if (QuestManager.Instance == null)
{
return "quests:null";
}
System.Text.StringBuilder builder = new System.Text.StringBuilder();
foreach (QuestState state in QuestManager.Instance.ActiveQuests)
{
if (state.questData == null)
{
continue;
}
builder.Append(state.questData.questId).Append(':').Append(state.status).Append(':');
for (int i = 0; i < state.goalProgress.Count; i++)
{
builder.Append(state.goalProgress[i]).Append(',');
}
builder.Append('|');
}
return builder.ToString();
}
private void ClearContent()
{
for (int i = content.childCount - 1; i >= 0; i--)
{
Destroy(content.GetChild(i).gameObject);
}
}
private void CreateLine(string value, Color color, int size)
{
GameObject line = new GameObject("Quest Tracker Line", typeof(RectTransform), typeof(Text));
line.transform.SetParent(content, false);
Text text = line.GetComponent<Text>();
text.font = uiFont != null ? uiFont : Resources.GetBuiltinResource<Font>("Arial.ttf");
text.fontSize = size;
text.color = color;
text.text = value;
RectTransform rect = line.GetComponent<RectTransform>();
rect.sizeDelta = new Vector2(0f, size + 8f);
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5589ed98cd9cd7c6a89980739d1515e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: