From 6318b20158ced1c71eec0137ce78fa1b91d5020a Mon Sep 17 00:00:00 2001 From: Dmitry Evdokimov Date: Thu, 4 Jun 2026 19:34:38 +0300 Subject: [PATCH] first commit --- .gitignore | 70 + .vscode/extensions.json | 5 + .vscode/launch.json | 10 + .vscode/settings.json | 55 + .xdp-.~4_Система_диалогов_ОТГ.docx-4vBNF7 | Bin 0 -> 162 bytes Assets/Editor.meta | 8 + Assets/Editor/Lab4SceneBuilder.cs | 776 ++++ Assets/Editor/Lab4SceneBuilder.cs.meta | 11 + Assets/Scenes.meta | 8 + Assets/Scenes/SampleScene.unity | 267 ++ Assets/Scenes/SampleScene.unity.meta | 7 + Assets/_Data.meta | 8 + Assets/_Data/Dialogue.meta | 8 + .../_Data/Dialogue/DialogueGraph_Readme.txt | 9 + .../Dialogue/DialogueGraph_Readme.txt.meta | 7 + .../Dialogue/Node_AmuletQuestComplete.asset | 36 + .../Node_AmuletQuestComplete.asset.meta | 8 + Assets/_Data/Dialogue/Node_Goodbye.asset | 20 + Assets/_Data/Dialogue/Node_Goodbye.asset.meta | 8 + Assets/_Data/Dialogue/Node_HasPass.asset | 48 + Assets/_Data/Dialogue/Node_HasPass.asset.meta | 8 + Assets/_Data/Dialogue/Node_Newcomer.asset | 61 + .../_Data/Dialogue/Node_Newcomer.asset.meta | 8 + .../_Data/Dialogue/Node_NoPassWarning.asset | 35 + .../Dialogue/Node_NoPassWarning.asset.meta | 8 + Assets/_Data/Dialogue/Node_PassInfo.asset | 48 + .../_Data/Dialogue/Node_PassInfo.asset.meta | 8 + Assets/_Data/Dialogue/Node_Reward.asset | 35 + Assets/_Data/Dialogue/Node_Reward.asset.meta | 8 + Assets/_Data/Dialogue/Node_Work.asset | 47 + Assets/_Data/Dialogue/Node_Work.asset.meta | 8 + Assets/_Data/Dialogue/StartNode.asset | 58 + Assets/_Data/Dialogue/StartNode.asset.meta | 8 + Assets/_Data/Items.meta | 8 + Assets/_Data/Items/OldAmulet.asset | 21 + Assets/_Data/Items/OldAmulet.asset.meta | 8 + Assets/_Data/Items/VillagePass.asset | 20 + Assets/_Data/Items/VillagePass.asset.meta | 8 + Assets/_Fonts.meta | 8 + Assets/_Fonts/Ubuntu-Bold.ttf | Bin 0 -> 333612 bytes Assets/_Fonts/Ubuntu-Bold.ttf.meta | 21 + Assets/_Fonts/Ubuntu-Regular.ttf | Bin 0 -> 353824 bytes Assets/_Fonts/Ubuntu-Regular.ttf.meta | 21 + Assets/_Materials.meta | 8 + Assets/_Materials/Accent_Mat.mat | 83 + Assets/_Materials/Accent_Mat.mat.meta | 8 + Assets/_Materials/Ground_Mat.mat | 83 + Assets/_Materials/Ground_Mat.mat.meta | 8 + Assets/_Materials/InteractionZone_Mat.mat | 85 + .../_Materials/InteractionZone_Mat.mat.meta | 8 + Assets/_Materials/NPC_Mat.mat | 83 + Assets/_Materials/NPC_Mat.mat.meta | 8 + Assets/_Materials/Player_Mat.mat | 83 + Assets/_Materials/Player_Mat.mat.meta | 8 + Assets/_Materials/Props_Mat.mat | 83 + Assets/_Materials/Props_Mat.mat.meta | 8 + Assets/_Materials/VillagePass_Mat.mat | 83 + Assets/_Materials/VillagePass_Mat.mat.meta | 8 + Assets/_Prefabs.meta | 8 + Assets/_Prefabs/DialogueResponseButton.prefab | 239 ++ .../DialogueResponseButton.prefab.meta | 7 + Assets/_Scenes.meta | 8 + Assets/_Scenes/Lab04_DialogueSystem.unity | 3341 +++++++++++++++++ .../_Scenes/Lab04_DialogueSystem.unity.meta | 7 + Assets/_Scripts.meta | 8 + Assets/_Scripts/BillboardNameplate.cs | 15 + Assets/_Scripts/BillboardNameplate.cs.meta | 11 + Assets/_Scripts/DialogueHUD.cs | 111 + Assets/_Scripts/DialogueHUD.cs.meta | 11 + Assets/_Scripts/DialogueManager.cs | 404 ++ Assets/_Scripts/DialogueManager.cs.meta | 11 + Assets/_Scripts/DialogueNode.cs | 33 + Assets/_Scripts/DialogueNode.cs.meta | 11 + Assets/_Scripts/Inventory.cs | 119 + Assets/_Scripts/Inventory.cs.meta | 11 + Assets/_Scripts/ItemData.cs | 14 + Assets/_Scripts/ItemData.cs.meta | 11 + Assets/_Scripts/NPCInteract.cs | 114 + Assets/_Scripts/NPCInteract.cs.meta | 11 + Assets/_Scripts/PickupItem.cs | 96 + Assets/_Scripts/PickupItem.cs.meta | 11 + Assets/_Scripts/SimplePlayerController.cs | 88 + .../_Scripts/SimplePlayerController.cs.meta | 11 + Packages/manifest.json | 41 + Packages/packages-lock.json | 382 ++ ProjectSettings/AudioManager.asset | 19 + ProjectSettings/ClusterInputManager.asset | 6 + ProjectSettings/DynamicsManager.asset | 34 + ProjectSettings/EditorBuildSettings.asset | 8 + ProjectSettings/EditorSettings.asset | 30 + ProjectSettings/GraphicsSettings.asset | 63 + ProjectSettings/InputManager.asset | 295 ++ ProjectSettings/MemorySettings.asset | 35 + ProjectSettings/NavMeshAreas.asset | 91 + ProjectSettings/PackageManagerSettings.asset | 35 + .../Settings.json | 5 + ProjectSettings/Physics2DSettings.asset | 56 + ProjectSettings/PresetManager.asset | 7 + ProjectSettings/ProjectSettings.asset | 772 ++++ ProjectSettings/ProjectVersion.txt | 2 + ProjectSettings/QualitySettings.asset | 234 ++ ProjectSettings/SceneTemplateSettings.json | 121 + ProjectSettings/TagManager.asset | 43 + ProjectSettings/TimeManager.asset | 9 + ProjectSettings/UnityConnectSettings.asset | 36 + ProjectSettings/VFXManager.asset | 12 + ProjectSettings/VersionControlSettings.asset | 8 + ProjectSettings/XRSettings.asset | 10 + mono_crash.mem.365251.1.blob | Bin 0 -> 10000001 bytes mono_crash.mem.369308.1.blob | Bin 0 -> 10000001 bytes 110 files changed, 9536 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .xdp-.~4_Система_диалогов_ОТГ.docx-4vBNF7 create mode 100644 Assets/Editor.meta create mode 100644 Assets/Editor/Lab4SceneBuilder.cs create mode 100644 Assets/Editor/Lab4SceneBuilder.cs.meta create mode 100644 Assets/Scenes.meta create mode 100644 Assets/Scenes/SampleScene.unity create mode 100644 Assets/Scenes/SampleScene.unity.meta create mode 100644 Assets/_Data.meta create mode 100644 Assets/_Data/Dialogue.meta create mode 100644 Assets/_Data/Dialogue/DialogueGraph_Readme.txt create mode 100644 Assets/_Data/Dialogue/DialogueGraph_Readme.txt.meta create mode 100644 Assets/_Data/Dialogue/Node_AmuletQuestComplete.asset create mode 100644 Assets/_Data/Dialogue/Node_AmuletQuestComplete.asset.meta create mode 100644 Assets/_Data/Dialogue/Node_Goodbye.asset create mode 100644 Assets/_Data/Dialogue/Node_Goodbye.asset.meta create mode 100644 Assets/_Data/Dialogue/Node_HasPass.asset create mode 100644 Assets/_Data/Dialogue/Node_HasPass.asset.meta create mode 100644 Assets/_Data/Dialogue/Node_Newcomer.asset create mode 100644 Assets/_Data/Dialogue/Node_Newcomer.asset.meta create mode 100644 Assets/_Data/Dialogue/Node_NoPassWarning.asset create mode 100644 Assets/_Data/Dialogue/Node_NoPassWarning.asset.meta create mode 100644 Assets/_Data/Dialogue/Node_PassInfo.asset create mode 100644 Assets/_Data/Dialogue/Node_PassInfo.asset.meta create mode 100644 Assets/_Data/Dialogue/Node_Reward.asset create mode 100644 Assets/_Data/Dialogue/Node_Reward.asset.meta create mode 100644 Assets/_Data/Dialogue/Node_Work.asset create mode 100644 Assets/_Data/Dialogue/Node_Work.asset.meta create mode 100644 Assets/_Data/Dialogue/StartNode.asset create mode 100644 Assets/_Data/Dialogue/StartNode.asset.meta create mode 100644 Assets/_Data/Items.meta create mode 100644 Assets/_Data/Items/OldAmulet.asset create mode 100644 Assets/_Data/Items/OldAmulet.asset.meta create mode 100644 Assets/_Data/Items/VillagePass.asset create mode 100644 Assets/_Data/Items/VillagePass.asset.meta create mode 100644 Assets/_Fonts.meta create mode 100644 Assets/_Fonts/Ubuntu-Bold.ttf create mode 100644 Assets/_Fonts/Ubuntu-Bold.ttf.meta create mode 100644 Assets/_Fonts/Ubuntu-Regular.ttf create mode 100644 Assets/_Fonts/Ubuntu-Regular.ttf.meta create mode 100644 Assets/_Materials.meta create mode 100644 Assets/_Materials/Accent_Mat.mat create mode 100644 Assets/_Materials/Accent_Mat.mat.meta create mode 100644 Assets/_Materials/Ground_Mat.mat create mode 100644 Assets/_Materials/Ground_Mat.mat.meta create mode 100644 Assets/_Materials/InteractionZone_Mat.mat create mode 100644 Assets/_Materials/InteractionZone_Mat.mat.meta create mode 100644 Assets/_Materials/NPC_Mat.mat create mode 100644 Assets/_Materials/NPC_Mat.mat.meta create mode 100644 Assets/_Materials/Player_Mat.mat create mode 100644 Assets/_Materials/Player_Mat.mat.meta create mode 100644 Assets/_Materials/Props_Mat.mat create mode 100644 Assets/_Materials/Props_Mat.mat.meta create mode 100644 Assets/_Materials/VillagePass_Mat.mat create mode 100644 Assets/_Materials/VillagePass_Mat.mat.meta create mode 100644 Assets/_Prefabs.meta create mode 100644 Assets/_Prefabs/DialogueResponseButton.prefab create mode 100644 Assets/_Prefabs/DialogueResponseButton.prefab.meta create mode 100644 Assets/_Scenes.meta create mode 100644 Assets/_Scenes/Lab04_DialogueSystem.unity create mode 100644 Assets/_Scenes/Lab04_DialogueSystem.unity.meta create mode 100644 Assets/_Scripts.meta create mode 100644 Assets/_Scripts/BillboardNameplate.cs create mode 100644 Assets/_Scripts/BillboardNameplate.cs.meta create mode 100644 Assets/_Scripts/DialogueHUD.cs create mode 100644 Assets/_Scripts/DialogueHUD.cs.meta create mode 100644 Assets/_Scripts/DialogueManager.cs create mode 100644 Assets/_Scripts/DialogueManager.cs.meta create mode 100644 Assets/_Scripts/DialogueNode.cs create mode 100644 Assets/_Scripts/DialogueNode.cs.meta create mode 100644 Assets/_Scripts/Inventory.cs create mode 100644 Assets/_Scripts/Inventory.cs.meta create mode 100644 Assets/_Scripts/ItemData.cs create mode 100644 Assets/_Scripts/ItemData.cs.meta create mode 100644 Assets/_Scripts/NPCInteract.cs create mode 100644 Assets/_Scripts/NPCInteract.cs.meta create mode 100644 Assets/_Scripts/PickupItem.cs create mode 100644 Assets/_Scripts/PickupItem.cs.meta create mode 100644 Assets/_Scripts/SimplePlayerController.cs create mode 100644 Assets/_Scripts/SimplePlayerController.cs.meta create mode 100644 Packages/manifest.json create mode 100644 Packages/packages-lock.json create mode 100644 ProjectSettings/AudioManager.asset create mode 100644 ProjectSettings/ClusterInputManager.asset create mode 100644 ProjectSettings/DynamicsManager.asset create mode 100644 ProjectSettings/EditorBuildSettings.asset create mode 100644 ProjectSettings/EditorSettings.asset create mode 100644 ProjectSettings/GraphicsSettings.asset create mode 100644 ProjectSettings/InputManager.asset create mode 100644 ProjectSettings/MemorySettings.asset create mode 100644 ProjectSettings/NavMeshAreas.asset create mode 100644 ProjectSettings/PackageManagerSettings.asset create mode 100644 ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json create mode 100644 ProjectSettings/Physics2DSettings.asset create mode 100644 ProjectSettings/PresetManager.asset create mode 100644 ProjectSettings/ProjectSettings.asset create mode 100644 ProjectSettings/ProjectVersion.txt create mode 100644 ProjectSettings/QualitySettings.asset create mode 100644 ProjectSettings/SceneTemplateSettings.json create mode 100644 ProjectSettings/TagManager.asset create mode 100644 ProjectSettings/TimeManager.asset create mode 100644 ProjectSettings/UnityConnectSettings.asset create mode 100644 ProjectSettings/VFXManager.asset create mode 100644 ProjectSettings/VersionControlSettings.asset create mode 100644 ProjectSettings/XRSettings.asset create mode 100644 mono_crash.mem.365251.1.blob create mode 100644 mono_crash.mem.369308.1.blob diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..61e8fcb --- /dev/null +++ b/.gitignore @@ -0,0 +1,70 @@ +# Unity generated folders +[Ll]ibrary/ +[Tt]emp/ +[Oo]bj/ +[Bb]uild/ +[Bb]uilds/ +[Ll]ogs/ +[Uu]ser[Ss]ettings/ +[Mm]emoryCaptures/ + +# Unity asset/import artifacts that should not be versioned +*.csproj +*.sln +*.suo +*.tmp +*.user +*.userprefs +*.pidb +*.booproj +*.svd +*.pdb +*.mdb +*.opendb +*.VC.db +*.pidb.meta +sysinfo.txt + +# Unity crash and profiler outputs +*.stackdump +*.dmp +*.raw +*.mem + +# Build outputs and packages +*.apk +*.aab +*.unitypackage +*.app + +# Addressables / streaming generated content +[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin* +[Aa]ssets/[Ss]treamingAssets/aa.meta +[Aa]ssets/[Ss]treamingAssets/aa/ + +# Visual Studio / Rider / VS Code local state +.vs/ +.idea/ +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.DotSettings.user + +# OS files +.DS_Store +Thumbs.db +Desktop.ini + +# Python/local tooling caches +__pycache__/ +*.py[cod] +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ + +# Lab reports and office temporary files +*.docx +~$*.docx +*.tmp.docx diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..ddb6ff8 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "visualstudiotoolsforunity.vstuc" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..da60e25 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,10 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to Unity", + "type": "vstuc", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..2a17750 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,55 @@ +{ + "files.exclude": { + "**/.DS_Store": true, + "**/.git": true, + "**/.gitmodules": true, + "**/*.booproj": true, + "**/*.pidb": true, + "**/*.suo": true, + "**/*.user": true, + "**/*.userprefs": true, + "**/*.unityproj": true, + "**/*.dll": true, + "**/*.exe": true, + "**/*.pdf": true, + "**/*.mid": true, + "**/*.midi": true, + "**/*.wav": true, + "**/*.gif": true, + "**/*.ico": true, + "**/*.jpg": true, + "**/*.jpeg": true, + "**/*.png": true, + "**/*.psd": true, + "**/*.tga": true, + "**/*.tif": true, + "**/*.tiff": true, + "**/*.3ds": true, + "**/*.3DS": true, + "**/*.fbx": true, + "**/*.FBX": true, + "**/*.lxo": true, + "**/*.LXO": true, + "**/*.ma": true, + "**/*.MA": true, + "**/*.obj": true, + "**/*.OBJ": true, + "**/*.asset": true, + "**/*.cubemap": true, + "**/*.flare": true, + "**/*.mat": true, + "**/*.meta": true, + "**/*.prefab": true, + "**/*.unity": true, + "build/": true, + "Build/": true, + "Library/": true, + "library/": true, + "obj/": true, + "Obj/": true, + "ProjectSettings/": true, + "temp/": true, + "Temp/": true + }, + "dotnet.defaultSolution": "OTG_Lab04_DialogueSystem.sln" +} \ No newline at end of file diff --git a/.xdp-.~4_Система_диалогов_ОТГ.docx-4vBNF7 b/.xdp-.~4_Система_диалогов_ОТГ.docx-4vBNF7 new file mode 100644 index 0000000000000000000000000000000000000000..b0f443f6d4e144bfd1a949883a5afe1ef5911bed GIT binary patch literal 162 dcmZQ6Dov_nAQiAM6fu-CBr%Y#lT@1+7y!~!1C0Ox literal 0 HcmV?d00001 diff --git a/Assets/Editor.meta b/Assets/Editor.meta new file mode 100644 index 0000000..43dc2ed --- /dev/null +++ b/Assets/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f204c61df8aefbf72a0d2d40f00aa2c8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/Lab4SceneBuilder.cs b/Assets/Editor/Lab4SceneBuilder.cs new file mode 100644 index 0000000..97d5800 --- /dev/null +++ b/Assets/Editor/Lab4SceneBuilder.cs @@ -0,0 +1,776 @@ +using System.IO; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.SceneManagement; +using UnityEngine.UI; + +public static class Lab4SceneBuilder +{ + private const string ScriptsPath = "Assets/_Scripts"; + private const string DataPath = "Assets/_Data"; + private const string DialoguePath = "Assets/_Data/Dialogue"; + private const string ItemsPath = "Assets/_Data/Items"; + private const string PrefabsPath = "Assets/_Prefabs"; + private const string ScenesPath = "Assets/_Scenes"; + private const string MaterialsPath = "Assets/_Materials"; + private const string FontsPath = "Assets/_Fonts"; + private const string ScenePath = "Assets/_Scenes/Lab04_DialogueSystem.unity"; + private const string ResponseButtonPrefabPath = "Assets/_Prefabs/DialogueResponseButton.prefab"; + + [MenuItem("Tools/Technical Game Design/Lab4/Create Dialogue System Scene")] + public static void CreateDialogueSystemScene() + { + CreateFolders(); + Font regularFont = InstallUbuntuFont(); + MaterialLibrary materials = CreateMaterials(); + ItemLibrary items = CreateItems(); + DialogueLibrary dialogue = CreateDialogue(items); + CreateGraphReadme(); + GameObject responseButtonPrefab = CreateResponseButtonPrefab(regularFont); + + Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); + scene.name = "Lab04_DialogueSystem"; + + BuildScene(materials, items, dialogue, responseButtonPrefab, regularFont); + + EditorSceneManager.SaveScene(scene, ScenePath); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + Debug.Log("Lab04 dialogue system scene generated: " + ScenePath); + } + + private static void CreateFolders() + { + string[] paths = + { + ScriptsPath, DataPath, DialoguePath, ItemsPath, PrefabsPath, + ScenesPath, MaterialsPath, FontsPath, "Assets/Editor" + }; + + foreach (string path in paths) + Directory.CreateDirectory(path); + + AssetDatabase.Refresh(); + } + + private static Font InstallUbuntuFont() + { + string regularDestination = FontsPath + "/Ubuntu-Regular.ttf"; + string boldDestination = FontsPath + "/Ubuntu-Bold.ttf"; + + string regularSource = FindFirstExistingFile( + "/usr/share/fonts/truetype/ubuntu/Ubuntu-Regular.ttf", + "/usr/share/fonts/truetype/ubuntu/Ubuntu-R.ttf", + "/usr/share/fonts/TTF/Ubuntu-Regular.ttf", + "/usr/share/fonts/TTF/Ubuntu-R.ttf", + "/usr/share/fonts/Ubuntu-Regular.ttf", + "/usr/share/fonts/Ubuntu-R.ttf"); + + string boldSource = FindFirstExistingFile( + "/usr/share/fonts/truetype/ubuntu/Ubuntu-Bold.ttf", + "/usr/share/fonts/truetype/ubuntu/Ubuntu-B.ttf", + "/usr/share/fonts/TTF/Ubuntu-Bold.ttf", + "/usr/share/fonts/TTF/Ubuntu-B.ttf", + "/usr/share/fonts/Ubuntu-Bold.ttf", + "/usr/share/fonts/Ubuntu-B.ttf"); + + if (!string.IsNullOrEmpty(regularSource)) + File.Copy(regularSource, regularDestination, true); + else + Debug.LogWarning("Ubuntu font was not found in common Linux font folders. Falling back to built-in Arial."); + + if (!string.IsNullOrEmpty(boldSource)) + File.Copy(boldSource, boldDestination, true); + + if (File.Exists(regularDestination)) + AssetDatabase.ImportAsset(regularDestination); + + if (File.Exists(boldDestination)) + AssetDatabase.ImportAsset(boldDestination); + AssetDatabase.Refresh(); + + Font font = AssetDatabase.LoadAssetAtPath(regularDestination); + return font != null ? font : Resources.GetBuiltinResource("Arial.ttf"); + } + + private static string FindFirstExistingFile(params string[] candidates) + { + foreach (string candidate in candidates) + { + if (File.Exists(candidate)) + return candidate; + } + + return null; + } + + private static MaterialLibrary CreateMaterials() + { + MaterialLibrary library = new MaterialLibrary + { + ground = CreateMaterial("Ground_Mat", new Color(0.34f, 0.43f, 0.34f)), + player = CreateMaterial("Player_Mat", new Color(0.17f, 0.43f, 0.74f)), + npc = CreateMaterial("NPC_Mat", new Color(0.68f, 0.44f, 0.17f)), + pass = CreateMaterial("VillagePass_Mat", new Color(0.95f, 0.78f, 0.25f)), + prop = CreateMaterial("Props_Mat", new Color(0.42f, 0.34f, 0.25f)), + accent = CreateMaterial("Accent_Mat", new Color(0.14f, 0.62f, 0.75f)), + interactionZone = CreateMaterial("InteractionZone_Mat", new Color(0.25f, 0.75f, 1f, 0.22f), true) + }; + + return library; + } + + private static Material CreateMaterial(string name, Color color, bool transparent = false) + { + string path = MaterialsPath + "/" + name + ".mat"; + Material material = AssetDatabase.LoadAssetAtPath(path); + + if (material == null) + { + material = new Material(Shader.Find("Standard")); + AssetDatabase.CreateAsset(material, path); + } + + material.name = name; + material.color = color; + + if (transparent) + { + material.SetFloat("_Mode", 3f); + material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); + material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + material.SetInt("_ZWrite", 0); + material.DisableKeyword("_ALPHATEST_ON"); + material.EnableKeyword("_ALPHABLEND_ON"); + material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); + material.renderQueue = 3000; + } + else + { + material.SetFloat("_Mode", 0f); + material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); + material.SetInt("_ZWrite", 1); + material.DisableKeyword("_ALPHATEST_ON"); + material.DisableKeyword("_ALPHABLEND_ON"); + material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); + material.renderQueue = -1; + } + + EditorUtility.SetDirty(material); + return material; + } + + private static ItemLibrary CreateItems() + { + ItemLibrary library = new ItemLibrary + { + villagePass = LoadOrCreateAsset(ItemsPath + "/VillagePass.asset"), + oldAmulet = LoadOrCreateAsset(ItemsPath + "/OldAmulet.asset") + }; + + library.villagePass.itemId = "VillagePass"; + library.villagePass.itemName = "Пропуск"; + library.villagePass.description = "Временный документ для прохода к старосте."; + library.villagePass.itemColor = new Color(0.95f, 0.78f, 0.25f); + library.villagePass.maxStack = 1; + + library.oldAmulet.itemId = "OldAmulet"; + library.oldAmulet.itemName = "Старый амулет"; + library.oldAmulet.description = "Потёртый амулет, который ценит смотритель ворот."; + library.oldAmulet.itemColor = new Color(0.35f, 0.82f, 0.8f); + library.oldAmulet.maxStack = 1; + + EditorUtility.SetDirty(library.villagePass); + EditorUtility.SetDirty(library.oldAmulet); + AssetDatabase.SaveAssets(); + return library; + } + + private static DialogueLibrary CreateDialogue(ItemLibrary items) + { + DialogueLibrary library = new DialogueLibrary + { + start = LoadOrCreateAsset(DialoguePath + "/StartNode.asset"), + newcomer = LoadOrCreateAsset(DialoguePath + "/Node_Newcomer.asset"), + passInfo = LoadOrCreateAsset(DialoguePath + "/Node_PassInfo.asset"), + noPassWarning = LoadOrCreateAsset(DialoguePath + "/Node_NoPassWarning.asset"), + hasPass = LoadOrCreateAsset(DialoguePath + "/Node_HasPass.asset"), + work = LoadOrCreateAsset(DialoguePath + "/Node_Work.asset"), + reward = LoadOrCreateAsset(DialoguePath + "/Node_Reward.asset"), + amuletComplete = LoadOrCreateAsset(DialoguePath + "/Node_AmuletQuestComplete.asset"), + goodbye = LoadOrCreateAsset(DialoguePath + "/Node_Goodbye.asset") + }; + + SetupNode(library.start, "StartNode", "Смотритель ворот", "Приветствую, путник. Ты впервые в нашем поселении?", false, + Response("Да, я только пришёл.", library.newcomer), + Response("Я ищу работу.", library.work), + Response("Мне пора.", library.goodbye)); + + SetupNode(library.newcomer, "Node_Newcomer", "Смотритель ворот", "Тогда тебе понадобится пропуск. Без него стража не пустит тебя к старосте.", false, + Response("Где его получить?", library.passInfo), + Response("У меня уже есть пропуск.", library.hasPass, requiredItem: items.villagePass, unavailableText: "Нужен предмет: Пропуск"), + Response("Понятно.", library.goodbye)); + + SetupNode(library.passInfo, "Node_PassInfo", "Смотритель ворот", "Осмотри площадку рядом с воротами. Иногда там оставляют временные пропуска.", false, + Response("Спасибо, я поищу.", library.goodbye), + Response("Я лучше сразу пойду к старосте.", library.noPassWarning)); + + SetupNode(library.noPassWarning, "Node_NoPassWarning", "Смотритель ворот", "Без пропуска тебя не примут. Сначала найди документ.", false, + Response("Хорошо, найду пропуск.", library.goodbye)); + + SetupNode(library.hasPass, "Node_HasPass", "Смотритель ворот", "Отлично. Раз у тебя есть пропуск, можешь пройти дальше. Передай старосте, что я тебя направил.", false, + Response("Спасибо за помощь.", library.reward, rewardItem: items.oldAmulet, rewardAmount: 1, eventId: "Gatekeeper_Rewards_Amulet"), + Response("До встречи.", library.goodbye)); + + SetupNode(library.work, "Node_Work", "Смотритель ворот", "Работа есть. Принеси старый амулет, и я расскажу больше.", false, + Response("У меня есть амулет.", library.amuletComplete, requiredItem: items.oldAmulet, consumeRequiredItem: true, unavailableText: "Нужен предмет: Старый амулет", eventId: "Gatekeeper_Amulet_TurnedIn"), + Response("Я вернусь позже.", library.goodbye)); + + SetupNode(library.reward, "Node_Reward", "Смотритель ворот", "Возьми этот старый амулет. Он может пригодиться в разговоре о работе.", false, + Response("Благодарю.", library.goodbye)); + + SetupNode(library.amuletComplete, "Node_AmuletQuestComplete", "Смотритель ворот", "Ты справился. Теперь я доверяю тебе. Для следующего задания приходи позже.", false, + Response("Понял.", library.goodbye)); + + SetupNode(library.goodbye, "Node_Goodbye", "Смотритель ворот", "Удачи тебе.", true); + + AssetDatabase.SaveAssets(); + return library; + } + + private static DialogueResponse Response( + string text, + DialogueNode nextNode, + bool endsDialogue = false, + ItemData requiredItem = null, + int requiredItemAmount = 1, + string unavailableText = "", + bool hideIfRequirementsNotMet = false, + bool consumeRequiredItem = false, + ItemData rewardItem = null, + int rewardAmount = 0, + string eventId = "") + { + return new DialogueResponse + { + responseText = text, + nextNode = nextNode, + endsDialogue = endsDialogue, + requiredItem = requiredItem, + requiredItemAmount = Mathf.Max(1, requiredItemAmount), + unavailableText = unavailableText, + hideIfRequirementsNotMet = hideIfRequirementsNotMet, + consumeRequiredItem = consumeRequiredItem, + rewardItem = rewardItem, + rewardAmount = rewardAmount, + eventId = eventId + }; + } + + private static void SetupNode(DialogueNode node, string id, string speaker, string line, bool isEnd, params DialogueResponse[] responses) + { + node.nodeId = id; + node.speakerName = speaker; + node.npcLine = line; + node.isEndNode = isEnd; + node.responses = responses; + node.editorNote = "Generated by Lab4SceneBuilder."; + EditorUtility.SetDirty(node); + } + + private static T LoadOrCreateAsset(string path) where T : ScriptableObject + { + T asset = AssetDatabase.LoadAssetAtPath(path); + if (asset != null) + return asset; + + asset = ScriptableObject.CreateInstance(); + AssetDatabase.CreateAsset(asset, path); + return asset; + } + + private static void CreateGraphReadme() + { + const string text = + "StartNode\n" + + "├─ Да, я только пришёл → Node_Newcomer\n" + + "│ ├─ Где его получить? → Node_PassInfo → Node_Goodbye\n" + + "│ ├─ У меня уже есть пропуск [requires VillagePass] → Node_HasPass → Node_Reward [gives OldAmulet] → Node_Goodbye\n" + + "│ └─ Понятно → Node_Goodbye\n" + + "├─ Я ищу работу → Node_Work\n" + + "│ ├─ У меня есть амулет [requires OldAmulet, consumes] → Node_AmuletQuestComplete → Node_Goodbye\n" + + "│ └─ Я вернусь позже → Node_Goodbye\n" + + "└─ Мне пора → Node_Goodbye\n"; + + File.WriteAllText(DialoguePath + "/DialogueGraph_Readme.txt", text); + } + + private static GameObject CreateResponseButtonPrefab(Font font) + { + GameObject root = new GameObject("DialogueResponseButton", typeof(RectTransform), typeof(Image), typeof(Button), typeof(LayoutElement), typeof(Outline)); + RectTransform rect = root.GetComponent(); + rect.sizeDelta = new Vector2(0f, 38f); + + Image image = root.GetComponent(); + image.color = new Color(0.095f, 0.12f, 0.15f, 0.98f); + + Outline outline = root.GetComponent(); + outline.effectColor = new Color(0.36f, 0.48f, 0.54f, 0.28f); + outline.effectDistance = new Vector2(1f, -1f); + + Button button = root.GetComponent