Working on Chapter 2, draft of Chapter 1 is completed
This commit is contained in:
8
Assets/Scripts/Editor.meta
Normal file
8
Assets/Scripts/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5760393482f758846baca6c2a3700f87
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,14 +1,20 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using EasyTalk.Controller;
|
||||
|
||||
public class GameManager : MonoBehaviour
|
||||
{
|
||||
private Player player;
|
||||
private DialogueController dialogueController;
|
||||
void Awake()
|
||||
{
|
||||
player = GetComponent<Player>();
|
||||
}
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
dialogueController = FindFirstObjectByType<DialogueController>();
|
||||
if(dialogueController == null)
|
||||
if (dialogueController == null)
|
||||
Debug.LogError("DialogueController not found in the scene.");
|
||||
else
|
||||
dialogueController.PlayDialogue();
|
||||
@@ -17,6 +23,26 @@ public class GameManager : MonoBehaviour
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
public void ShowPlayerSkills(InputAction.CallbackContext ctx)
|
||||
{
|
||||
if (!ctx.performed) return;
|
||||
player.GetSkills(out var skills);
|
||||
foreach (var skill in skills)
|
||||
{
|
||||
Debug.Log($"Skill: {skill.Key}, Level: {skill.Value.level}, Description: {skill.Value.Description}");
|
||||
}
|
||||
}
|
||||
public void SkillCheck(string skillName, int requiredLevel, out bool hasSkill)
|
||||
{
|
||||
if (player.skills.TryGetValue(skillName, out Skill skill))
|
||||
{
|
||||
hasSkill = skill.level >= requiredLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasSkill = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
331
Assets/Scripts/Inventory.cs
Normal file
331
Assets/Scripts/Inventory.cs
Normal file
@@ -0,0 +1,331 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[CreateAssetMenu(fileName = "NewItem", menuName = "Inventory/Item")]
|
||||
public class Item : ScriptableObject
|
||||
{
|
||||
public string itemName;
|
||||
public string itemDescription;
|
||||
public int itemID;
|
||||
public int maxStackSize = 1;
|
||||
public bool isStackable;
|
||||
public enum ItemType { Weapon, Armor, Consumable, QuestItem, Miscellaneous }
|
||||
public ItemType itemType;
|
||||
public Sprite itemIcon;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class InventorySlot
|
||||
{
|
||||
public Item item;
|
||||
public int quantity;
|
||||
|
||||
public InventorySlot(Item newItem, int qty)
|
||||
{
|
||||
item = newItem;
|
||||
quantity = qty;
|
||||
}
|
||||
}
|
||||
|
||||
public class Inventory : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject inventoryUI;
|
||||
[SerializeField] private int maxCapacity = 20;
|
||||
[SerializeField] private List<Item> allItems = new List<Item>(); // All available items in game
|
||||
private List<InventorySlot> inventorySlots = new List<InventorySlot>();
|
||||
|
||||
// Equipment slots
|
||||
private Item equippedWeapon;
|
||||
private Item equippedArmor;
|
||||
|
||||
private Item FindItemByName(string itemName)
|
||||
{
|
||||
return allItems.Find(i => i.itemName == itemName);
|
||||
}
|
||||
|
||||
private Item FindItemByID(int itemID)
|
||||
{
|
||||
return allItems.Find(i => i.itemID == itemID);
|
||||
}
|
||||
|
||||
public bool AddItem(string itemName, int quantity = 1)
|
||||
{
|
||||
Item item = FindItemByName(itemName);
|
||||
if (item == null)
|
||||
{
|
||||
Debug.LogWarning($"Item '{itemName}' not found.");
|
||||
return false;
|
||||
}
|
||||
return AddItemInternal(item, quantity);
|
||||
}
|
||||
|
||||
public bool AddItem(int itemID, int quantity = 1)
|
||||
{
|
||||
Item item = FindItemByID(itemID);
|
||||
if (item == null)
|
||||
{
|
||||
Debug.LogWarning($"Item with ID {itemID} not found.");
|
||||
return false;
|
||||
}
|
||||
return AddItemInternal(item, quantity);
|
||||
}
|
||||
|
||||
private bool AddItemInternal(Item item, int quantity = 1)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
Debug.LogWarning("Tried to add null item to inventory.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to add to existing stack if stackable
|
||||
if (item.isStackable)
|
||||
{
|
||||
foreach (var slot in inventorySlots)
|
||||
{
|
||||
if (slot.item == item && slot.quantity < item.maxStackSize)
|
||||
{
|
||||
int spaceAvailable = item.maxStackSize - slot.quantity;
|
||||
int amountToAdd = Mathf.Min(quantity, spaceAvailable);
|
||||
slot.quantity += amountToAdd;
|
||||
Debug.Log($"Added {amountToAdd} {item.itemName} to existing stack. Stack size: {slot.quantity}");
|
||||
|
||||
if (amountToAdd < quantity)
|
||||
{
|
||||
// Recursively add remaining items
|
||||
return AddItemInternal(item, quantity - amountToAdd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add new slot if space available
|
||||
if (inventorySlots.Count < maxCapacity)
|
||||
{
|
||||
inventorySlots.Add(new InventorySlot(item, quantity));
|
||||
Debug.Log($"Added {quantity} {item.itemName} to inventory. Slots used: {inventorySlots.Count}/{maxCapacity}");
|
||||
return true;
|
||||
}
|
||||
|
||||
Debug.Log("Inventory is full!");
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool RemoveItem(string itemName, int quantity = 1)
|
||||
{
|
||||
Item item = FindItemByName(itemName);
|
||||
if (item == null)
|
||||
{
|
||||
Debug.LogWarning($"Item '{itemName}' not found.");
|
||||
return false;
|
||||
}
|
||||
return RemoveItemInternal(item, quantity);
|
||||
}
|
||||
|
||||
public bool RemoveItem(int itemID, int quantity = 1)
|
||||
{
|
||||
Item item = FindItemByID(itemID);
|
||||
if (item == null)
|
||||
{
|
||||
Debug.LogWarning($"Item with ID {itemID} not found.");
|
||||
return false;
|
||||
}
|
||||
return RemoveItemInternal(item, quantity);
|
||||
}
|
||||
|
||||
private bool RemoveItemInternal(Item item, int quantity = 1)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
Debug.LogWarning("Tried to remove null item from inventory.");
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var slot in inventorySlots)
|
||||
{
|
||||
if (slot.item == item)
|
||||
{
|
||||
if (slot.quantity >= quantity)
|
||||
{
|
||||
slot.quantity -= quantity;
|
||||
Debug.Log($"Removed {quantity} {item.itemName} from inventory.");
|
||||
|
||||
// Remove slot if empty
|
||||
if (slot.quantity <= 0)
|
||||
{
|
||||
inventorySlots.Remove(slot);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Not enough {item.itemName} in inventory. Have: {slot.quantity}, Need: {quantity}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LogWarning($"{item.itemName} not found in inventory.");
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetItemQuantity(string itemName)
|
||||
{
|
||||
Item item = FindItemByName(itemName);
|
||||
if (item == null) return 0;
|
||||
return GetItemQuantityInternal(item);
|
||||
}
|
||||
|
||||
public int GetItemQuantity(int itemID)
|
||||
{
|
||||
Item item = FindItemByID(itemID);
|
||||
if (item == null) return 0;
|
||||
return GetItemQuantityInternal(item);
|
||||
}
|
||||
|
||||
private int GetItemQuantityInternal(Item item)
|
||||
{
|
||||
foreach (var slot in inventorySlots)
|
||||
{
|
||||
if (slot.item == item)
|
||||
return slot.quantity;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public List<InventorySlot> GetInventorySlots()
|
||||
{
|
||||
return new List<InventorySlot>(inventorySlots);
|
||||
}
|
||||
|
||||
public int GetAvailableSlots()
|
||||
{
|
||||
return maxCapacity - inventorySlots.Count;
|
||||
}
|
||||
|
||||
public void ClearInventory()
|
||||
{
|
||||
inventorySlots.Clear();
|
||||
Debug.Log("Inventory cleared.");
|
||||
}
|
||||
|
||||
public bool EquipItem(string itemName)
|
||||
{
|
||||
Item item = FindItemByName(itemName);
|
||||
if (item == null)
|
||||
{
|
||||
Debug.LogWarning($"Item '{itemName}' not found.");
|
||||
return false;
|
||||
}
|
||||
return EquipItemInternal(item);
|
||||
}
|
||||
|
||||
public bool EquipItem(int itemID)
|
||||
{
|
||||
Item item = FindItemByID(itemID);
|
||||
if (item == null)
|
||||
{
|
||||
Debug.LogWarning($"Item with ID {itemID} not found.");
|
||||
return false;
|
||||
}
|
||||
return EquipItemInternal(item);
|
||||
}
|
||||
|
||||
private bool EquipItemInternal(Item item)
|
||||
{
|
||||
if (item == null) return false;
|
||||
|
||||
if (item.itemType == Item.ItemType.Weapon)
|
||||
{
|
||||
if (equippedWeapon != null)
|
||||
AddItemInternal(equippedWeapon);
|
||||
equippedWeapon = item;
|
||||
RemoveItemInternal(item, 1);
|
||||
Debug.Log($"Equipped weapon: {item.itemName}");
|
||||
return true;
|
||||
}
|
||||
else if (item.itemType == Item.ItemType.Armor)
|
||||
{
|
||||
if (equippedArmor != null)
|
||||
AddItemInternal(equippedArmor);
|
||||
equippedArmor = item;
|
||||
RemoveItemInternal(item, 1);
|
||||
Debug.Log($"Equipped armor: {item.itemName}");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Item GetEquippedItem(Item.ItemType type)
|
||||
{
|
||||
return type == Item.ItemType.Weapon ? equippedWeapon :
|
||||
type == Item.ItemType.Armor ? equippedArmor : null;
|
||||
}
|
||||
|
||||
public bool UseItem(string itemName)
|
||||
{
|
||||
Item item = FindItemByName(itemName);
|
||||
if (item == null)
|
||||
{
|
||||
Debug.LogWarning($"Item '{itemName}' not found.");
|
||||
return false;
|
||||
}
|
||||
return UseItemInternal(item);
|
||||
}
|
||||
|
||||
public bool UseItem(int itemID)
|
||||
{
|
||||
Item item = FindItemByID(itemID);
|
||||
if (item == null)
|
||||
{
|
||||
Debug.LogWarning($"Item with ID {itemID} not found.");
|
||||
return false;
|
||||
}
|
||||
return UseItemInternal(item);
|
||||
}
|
||||
|
||||
private bool UseItemInternal(Item item)
|
||||
{
|
||||
if (item.itemType == Item.ItemType.Consumable)
|
||||
{
|
||||
Debug.Log($"Used {item.itemName}");
|
||||
RemoveItemInternal(item, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool DropItem(string itemName, int quantity = 1)
|
||||
{
|
||||
Item item = FindItemByName(itemName);
|
||||
if (item == null)
|
||||
{
|
||||
Debug.LogWarning($"Item '{itemName}' not found.");
|
||||
return false;
|
||||
}
|
||||
return DropItemInternal(item, quantity);
|
||||
}
|
||||
|
||||
public bool DropItem(int itemID, int quantity = 1)
|
||||
{
|
||||
Item item = FindItemByID(itemID);
|
||||
if (item == null)
|
||||
{
|
||||
Debug.LogWarning($"Item with ID {itemID} not found.");
|
||||
return false;
|
||||
}
|
||||
return DropItemInternal(item, quantity);
|
||||
}
|
||||
|
||||
private bool DropItemInternal(Item item, int quantity = 1)
|
||||
{
|
||||
if (RemoveItemInternal(item, quantity))
|
||||
{
|
||||
Debug.Log($"Dropped {quantity} {item.itemName}");
|
||||
// TODO: Instantiate item drop in world
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Inventory.cs.meta
Normal file
2
Assets/Scripts/Inventory.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c696bcbb1e2bba4489d42a102676ca1
|
||||
67
Assets/Scripts/InventoryItemUI.cs
Normal file
67
Assets/Scripts/InventoryItemUI.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
public class InventoryItemUI : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerClickHandler
|
||||
{
|
||||
private Item item;
|
||||
private int quantity;
|
||||
private InventoryUI inventoryUI;
|
||||
private Image itemImage;
|
||||
private Text quantityText;
|
||||
private Canvas canvas;
|
||||
private GraphicRaycaster raycaster;
|
||||
private CanvasGroup canvasGroup;
|
||||
|
||||
public void Initialize(Item newItem, int qty, InventoryUI ui)
|
||||
{
|
||||
item = newItem;
|
||||
quantity = qty;
|
||||
inventoryUI = ui;
|
||||
|
||||
itemImage = GetComponent<Image>();
|
||||
quantityText = GetComponentInChildren<Text>();
|
||||
canvas = GetComponentInParent<Canvas>();
|
||||
canvasGroup = GetComponent<CanvasGroup>();
|
||||
|
||||
if (itemImage != null && item.itemIcon != null)
|
||||
itemImage.sprite = item.itemIcon;
|
||||
|
||||
if (quantityText != null)
|
||||
quantityText.text = quantity > 1 ? quantity.ToString() : "";
|
||||
|
||||
// Make draggable
|
||||
if (canvasGroup == null)
|
||||
canvasGroup = gameObject.AddComponent<CanvasGroup>();
|
||||
|
||||
GetComponent<RectTransform>().sizeDelta = new Vector2(64, 64);
|
||||
}
|
||||
|
||||
public void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
canvasGroup.alpha = 0.6f;
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
GetComponent<RectTransform>().anchoredPosition += eventData.delta / canvas.scaleFactor;
|
||||
}
|
||||
|
||||
public void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
canvasGroup.alpha = 1f;
|
||||
canvasGroup.blocksRaycasts = true;
|
||||
|
||||
// Reset position on drop (TODO: check if dropped on equip slot)
|
||||
GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
|
||||
}
|
||||
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (eventData.button == PointerEventData.InputButton.Right)
|
||||
{
|
||||
inventoryUI.ShowContextMenu(this, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/InventoryItemUI.cs.meta
Normal file
2
Assets/Scripts/InventoryItemUI.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 29fa03381fdd17e4d952a4ea6ea898e1
|
||||
176
Assets/Scripts/InventoryUI.cs
Normal file
176
Assets/Scripts/InventoryUI.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class InventoryUI : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform inventoryContent; // Panel > ScrollView > Viewport > Content
|
||||
[SerializeField] private GameObject inventoryItemPrefab;
|
||||
[SerializeField] private Transform weaponSlot;
|
||||
[SerializeField] private Transform armorSlot;
|
||||
[SerializeField] private Inventory inventory;
|
||||
|
||||
private Canvas canvas;
|
||||
private GameObject contextMenu;
|
||||
private InventoryItemUI selectedItem;
|
||||
|
||||
void Start()
|
||||
{
|
||||
canvas = GetComponentInParent<Canvas>();
|
||||
if (inventory == null)
|
||||
inventory = FindObjectOfType<Inventory>();
|
||||
|
||||
RefreshInventoryUI();
|
||||
}
|
||||
|
||||
public void RefreshInventoryUI()
|
||||
{
|
||||
// Clear existing items
|
||||
foreach (Transform child in inventoryContent)
|
||||
Destroy(child.gameObject);
|
||||
|
||||
// Populate inventory slots
|
||||
var slots = inventory.GetInventorySlots();
|
||||
foreach (var slot in slots)
|
||||
{
|
||||
CreateInventoryItemUI(slot.item, slot.quantity);
|
||||
}
|
||||
|
||||
// Update equipment slots
|
||||
UpdateEquipmentSlots();
|
||||
}
|
||||
|
||||
private void CreateInventoryItemUI(Item item, int quantity)
|
||||
{
|
||||
GameObject itemUI = Instantiate(inventoryItemPrefab, inventoryContent);
|
||||
InventoryItemUI itemScript = itemUI.GetComponent<InventoryItemUI>();
|
||||
itemScript.Initialize(item, quantity, this);
|
||||
}
|
||||
|
||||
private void UpdateEquipmentSlots()
|
||||
{
|
||||
Item equippedWeapon = inventory.GetEquippedItem(Item.ItemType.Weapon);
|
||||
Item equippedArmor = inventory.GetEquippedItem(Item.ItemType.Armor);
|
||||
|
||||
UpdateEquipSlot(weaponSlot, equippedWeapon);
|
||||
UpdateEquipSlot(armorSlot, equippedArmor);
|
||||
}
|
||||
|
||||
private void UpdateEquipSlot(Transform slot, Item item)
|
||||
{
|
||||
Image slotImage = slot.GetComponent<Image>();
|
||||
if (item != null && item.itemIcon != null)
|
||||
{
|
||||
slotImage.sprite = item.itemIcon;
|
||||
slotImage.color = Color.white;
|
||||
}
|
||||
else
|
||||
{
|
||||
slotImage.sprite = null;
|
||||
slotImage.color = new Color(1, 1, 1, 0.3f);
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowContextMenu(InventoryItemUI itemUI, Item item)
|
||||
{
|
||||
selectedItem = itemUI;
|
||||
|
||||
if (contextMenu != null)
|
||||
Destroy(contextMenu);
|
||||
|
||||
contextMenu = new GameObject("ContextMenu");
|
||||
contextMenu.transform.SetParent(canvas.transform, false);
|
||||
|
||||
VerticalLayoutGroup layout = contextMenu.AddComponent<VerticalLayoutGroup>();
|
||||
layout.childForceExpandHeight = false;
|
||||
layout.childForceExpandWidth = false;
|
||||
layout.spacing = 2;
|
||||
|
||||
LayoutElement layoutElement = contextMenu.AddComponent<LayoutElement>();
|
||||
layoutElement.preferredWidth = 120;
|
||||
layoutElement.preferredHeight = 140;
|
||||
|
||||
RectTransform rectTransform = contextMenu.GetComponent<RectTransform>();
|
||||
rectTransform.sizeDelta = new Vector2(120, 140);
|
||||
rectTransform.anchoredPosition = Input.mousePosition / canvas.scaleFactor;
|
||||
|
||||
Image bgImage = contextMenu.AddComponent<Image>();
|
||||
bgImage.color = new Color(0.1f, 0.1f, 0.1f, 0.9f);
|
||||
|
||||
// Add menu options based on item type
|
||||
if (item.itemType == Item.ItemType.Weapon || item.itemType == Item.ItemType.Armor)
|
||||
AddMenuButton(contextMenu, "Equip", () => OnEquip(item));
|
||||
|
||||
if (item.itemType == Item.ItemType.Consumable)
|
||||
AddMenuButton(contextMenu, "Use", () => OnUse(item));
|
||||
|
||||
AddMenuButton(contextMenu, "Info", () => OnInfo(item));
|
||||
AddMenuButton(contextMenu, "Drop", () => OnDrop(item));
|
||||
|
||||
// Close menu on click elsewhere
|
||||
StartCoroutine(WaitForClickOutside());
|
||||
}
|
||||
|
||||
private void AddMenuButton(GameObject parent, string label, UnityEngine.Events.UnityAction onClick)
|
||||
{
|
||||
GameObject buttonObj = new GameObject(label);
|
||||
buttonObj.transform.SetParent(parent.transform, false);
|
||||
|
||||
Button button = buttonObj.AddComponent<Button>();
|
||||
Text text = buttonObj.AddComponent<Text>();
|
||||
text.text = label;
|
||||
text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||||
text.alignment = TextAnchor.MiddleCenter;
|
||||
text.color = Color.white;
|
||||
text.fontSize = 12;
|
||||
|
||||
RectTransform rect = buttonObj.GetComponent<RectTransform>();
|
||||
rect.sizeDelta = new Vector2(100, 30);
|
||||
|
||||
LayoutElement layoutElement = buttonObj.AddComponent<LayoutElement>();
|
||||
layoutElement.preferredWidth = 100;
|
||||
layoutElement.preferredHeight = 30;
|
||||
|
||||
button.onClick.AddListener(onClick);
|
||||
button.onClick.AddListener(() => Destroy(contextMenu));
|
||||
}
|
||||
|
||||
private void OnEquip(Item item)
|
||||
{
|
||||
inventory.EquipItem(item.itemName);
|
||||
RefreshInventoryUI();
|
||||
}
|
||||
|
||||
private void OnUse(Item item)
|
||||
{
|
||||
inventory.UseItem(item.itemName);
|
||||
RefreshInventoryUI();
|
||||
}
|
||||
|
||||
private void OnInfo(Item item)
|
||||
{
|
||||
Debug.Log($"--- {item.itemName} ---\n{item.itemDescription}\nType: {item.itemType}\nID: {item.itemID}");
|
||||
// TODO: Show item info panel
|
||||
}
|
||||
|
||||
private void OnDrop(Item item)
|
||||
{
|
||||
inventory.DropItem(item.itemName, 1);
|
||||
RefreshInventoryUI();
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator WaitForClickOutside()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0) && contextMenu != null)
|
||||
{
|
||||
// Destroy menu when clicking anywhere (simplified approach)
|
||||
Destroy(contextMenu);
|
||||
yield break;
|
||||
}
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/InventoryUI.cs.meta
Normal file
2
Assets/Scripts/InventoryUI.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fbb322e4f92cd9a40ac342f7d34a81d5
|
||||
99
Assets/Scripts/Player.cs
Normal file
99
Assets/Scripts/Player.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
[System.Serializable]
|
||||
public class Skill // class, not struct
|
||||
{
|
||||
public enum SkillType { Swordsmanship, Archer, Magic, Unarmed, Stealth, Alchemy, Blacksmithing, Cooking, Speech, Perception, Lockpicking, Pickpocketing, Persuasion, Bartering, Leadership, Tactics, Strategy, Healing, Enchanting, Summoning, Necromancy, ElementalMagic, IllusionMagic, RestorationMagic, ConjurationMagic, DestructionMagic }
|
||||
public SkillType skillType;
|
||||
public enum SkillTier { Novice, Apprentice, Journeyman, Expert, Master }
|
||||
public SkillTier skillTier;
|
||||
public int level;
|
||||
|
||||
private static readonly Dictionary<SkillType, string> Descriptions = new Dictionary<SkillType, string>
|
||||
{
|
||||
{ SkillType.Swordsmanship, "Mastery of the sword." },
|
||||
{ SkillType.Archer, "Mastery of the bow." },
|
||||
{ SkillType.Magic, "Mastery of arcane arts." },
|
||||
{ SkillType.Unarmed, "Mastery of hand-to-hand combat." },
|
||||
{ SkillType.Stealth, "Mastery of moving unseen." },
|
||||
{ SkillType.Alchemy, "Mastery of potion making and chemical reactions." },
|
||||
{ SkillType.Blacksmithing, "Mastery of forging weapons and armor." },
|
||||
{ SkillType.Cooking, "Mastery of preparing food and potions." },
|
||||
{ SkillType.Speech, "Mastery of persuasion and communication." },
|
||||
{ SkillType.Perception, "Mastery of noticing details and hidden objects." },
|
||||
{ SkillType.Lockpicking, "Mastery of opening locks without a key." },
|
||||
{ SkillType.Pickpocketing, "Mastery of stealing undetected." },
|
||||
{ SkillType.Persuasion, "Mastery of convincing others." },
|
||||
{ SkillType.Bartering, "Mastery of trading and negotiation." },
|
||||
{ SkillType.Leadership, "Mastery of commanding others." },
|
||||
{ SkillType.Tactics, "Mastery of battlefield planning." },
|
||||
{ SkillType.Strategy, "Mastery of long-term planning and warfare." },
|
||||
{ SkillType.Healing, "Mastery of mending wounds and ailments." },
|
||||
{ SkillType.Enchanting, "Mastery of imbuing items with magic." },
|
||||
{ SkillType.Summoning, "Mastery of calling forth creatures." },
|
||||
{ SkillType.Necromancy, "Mastery of death and undead magic." },
|
||||
{ SkillType.ElementalMagic, "Mastery of fire, ice, and lightning." },
|
||||
{ SkillType.IllusionMagic, "Mastery of deceiving the senses." },
|
||||
{ SkillType.RestorationMagic, "Mastery of healing and ward magic." },
|
||||
{ SkillType.ConjurationMagic, "Mastery of summoning and binding." },
|
||||
{ SkillType.DestructionMagic, "Mastery of destructive spells." },
|
||||
};
|
||||
|
||||
public string Description => Descriptions.TryGetValue(skillType, out var desc) ? desc : string.Empty;
|
||||
}
|
||||
public class Player : MonoBehaviour
|
||||
{
|
||||
[Header("Player Stats")]
|
||||
[SerializeField] private int maxHealth, maxStamina, maxMana;
|
||||
private int curHealth, curStamina, curMana;
|
||||
[Header("Player Skills")]
|
||||
[SerializeField] private List<Skill> skillList = new List<Skill>(); // serializable
|
||||
public Dictionary<string, Skill> skills; // runtime lookup
|
||||
|
||||
|
||||
void Start()
|
||||
{
|
||||
skills = skillList.ToDictionary(s => s.skillType.ToString(), s => s); // convert list to dictionary for runtime lookup
|
||||
// Initialize player stats
|
||||
curHealth = maxHealth;
|
||||
curStamina = maxStamina;
|
||||
curMana = maxMana;
|
||||
}
|
||||
public void GetStats(out int health, out int stamina, out int mana)
|
||||
{
|
||||
health = curHealth;
|
||||
stamina = curStamina;
|
||||
mana = curMana;
|
||||
}
|
||||
public void GetSkills(out Dictionary<string, Skill> playerSkills)
|
||||
{
|
||||
playerSkills = new Dictionary<string, Skill>(skills);
|
||||
}
|
||||
public int GetSkillLevel(string skillName)
|
||||
{
|
||||
if (skills.TryGetValue(skillName, out Skill skill))
|
||||
{
|
||||
return skill.level;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Skill '{skillName}' not found for player.");
|
||||
return -1; // or throw an exception, or return a default value
|
||||
}
|
||||
}
|
||||
public void TakeDamage(int damage)
|
||||
{
|
||||
curHealth -= damage;
|
||||
if (curHealth <= 0)
|
||||
{
|
||||
Die();
|
||||
}
|
||||
}
|
||||
private void Die()
|
||||
{
|
||||
Debug.Log("Player has died.");
|
||||
// Handle player death (e.g., respawn, game over, etc.)
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Player.cs.meta
Normal file
2
Assets/Scripts/Player.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03d6b15fc412de94cb7824b32753e73b
|
||||
@@ -1,114 +1,209 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[System.Serializable]
|
||||
public class Quest
|
||||
{
|
||||
public string questName;
|
||||
public string questDescription;
|
||||
public int requiredLevel;
|
||||
public int rewardGold;
|
||||
public int rewardExperience;
|
||||
public int requiredQuantity;
|
||||
public string[] prerequisiteNames; // Store quest names instead of direct references
|
||||
}
|
||||
|
||||
public class Quests : MonoBehaviour
|
||||
{
|
||||
private string questName;
|
||||
private string questDescription;
|
||||
private int requiredLevel;
|
||||
private int rewardGold;
|
||||
private int rewardExperience;
|
||||
private int requiredQuantity;
|
||||
private Quests[] prerequisites;
|
||||
private List<Quests> completedQuests = new List<Quests>();
|
||||
private List<Quests> activeQuests = new List<Quests>();
|
||||
private List<Quests> availableQuests = new List<Quests>();
|
||||
// Start is called before the first frame update
|
||||
[SerializeField] private List<Quest> completedQuests = new List<Quest>();
|
||||
[SerializeField] private List<Quest> activeQuests = new List<Quest>();
|
||||
[SerializeField] private List<Quest> availableQuests = new List<Quest>();
|
||||
[SerializeField] private List<Quest> allQuests = new List<Quest>(); // All quests in the game
|
||||
|
||||
void Start()
|
||||
{
|
||||
|
||||
RefreshAvailableQuests();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
public Quests(string name, string description, int level, int gold, int experience, int quantity, Quests[] prerequisites)
|
||||
|
||||
public void StartQuest(Quest quest)
|
||||
{
|
||||
this.questName = name;
|
||||
this.questDescription = description;
|
||||
this.requiredLevel = level;
|
||||
this.rewardGold = gold;
|
||||
this.rewardExperience = experience;
|
||||
this.requiredQuantity = quantity;
|
||||
this.prerequisites = prerequisites;
|
||||
}
|
||||
public void StartQuest()
|
||||
{
|
||||
// Logic to start the quest
|
||||
activeQuests.Add(this);
|
||||
}
|
||||
public void CompleteQuest()
|
||||
{
|
||||
// Logic to complete the quest
|
||||
activeQuests.Remove(this);
|
||||
completedQuests.Add(this);
|
||||
}
|
||||
public void AbandonQuest()
|
||||
{
|
||||
// Logic to abandon the quest
|
||||
activeQuests.Remove(this);
|
||||
}
|
||||
public void FailQuest()
|
||||
{
|
||||
// Logic to fail the quest
|
||||
activeQuests.Remove(this);
|
||||
}
|
||||
public Quests[] GetPrerequisites()
|
||||
{
|
||||
return prerequisites;
|
||||
}
|
||||
public void GetQuestDetails()
|
||||
{
|
||||
// Logic to get quest details
|
||||
Debug.Log($"Quest Name: {questName}");
|
||||
Debug.Log($"Description: {questDescription}");
|
||||
Debug.Log($"Required Level: {requiredLevel}");
|
||||
Debug.Log($"Reward Gold: {rewardGold}");
|
||||
Debug.Log($"Reward Experience: {rewardExperience}");
|
||||
Debug.Log($"Required Quantity: {requiredQuantity}");
|
||||
}
|
||||
public void CheckQuestStatus()
|
||||
{
|
||||
// Logic to check the status of the quest
|
||||
if (activeQuests.Contains(this))
|
||||
if (availableQuests.Contains(quest) && !activeQuests.Contains(quest))
|
||||
{
|
||||
Debug.Log($"Quest '{questName}' is currently active.");
|
||||
}
|
||||
else if (completedQuests.Contains(this))
|
||||
{
|
||||
Debug.Log($"Quest '{questName}' has been completed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"Quest '{questName}' is not active or completed.");
|
||||
}
|
||||
}
|
||||
public void GetAvailableQuests()
|
||||
{
|
||||
// Logic to get available quests based on prerequisites and player level
|
||||
// This is a placeholder implementation; you would typically check the player's level and completed quests
|
||||
availableQuests.Clear();
|
||||
if (prerequisites == null || prerequisites.Length == 0)
|
||||
{
|
||||
availableQuests.Add(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool allPrerequisitesCompleted = true;
|
||||
foreach (var prerequisite in prerequisites)
|
||||
{
|
||||
if (!completedQuests.Contains(prerequisite))
|
||||
{
|
||||
allPrerequisitesCompleted = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allPrerequisitesCompleted)
|
||||
{
|
||||
availableQuests.Add(this);
|
||||
}
|
||||
activeQuests.Add(quest);
|
||||
availableQuests.Remove(quest);
|
||||
Debug.Log($"Quest '{quest.questName}' started.");
|
||||
}
|
||||
}
|
||||
|
||||
public void StartQuest(string questName)
|
||||
{
|
||||
Quest quest = allQuests.Find(q => q.questName == questName);
|
||||
if (quest != null)
|
||||
StartQuest(quest);
|
||||
else
|
||||
Debug.LogWarning($"Quest '{questName}' not found.");
|
||||
}
|
||||
|
||||
public void CompleteQuest(Quest quest)
|
||||
{
|
||||
if (activeQuests.Contains(quest))
|
||||
{
|
||||
activeQuests.Remove(quest);
|
||||
completedQuests.Add(quest);
|
||||
Debug.Log($"Quest '{quest.questName}' completed.");
|
||||
RefreshAvailableQuests(); // Unlock new quests
|
||||
}
|
||||
}
|
||||
|
||||
public void CompleteQuest(string questName)
|
||||
{
|
||||
Quest quest = allQuests.Find(q => q.questName == questName);
|
||||
if (quest != null)
|
||||
CompleteQuest(quest);
|
||||
else
|
||||
Debug.LogWarning($"Quest '{questName}' not found.");
|
||||
}
|
||||
|
||||
public void AbandonQuest(Quest quest)
|
||||
{
|
||||
if (activeQuests.Contains(quest))
|
||||
{
|
||||
activeQuests.Remove(quest);
|
||||
Debug.Log($"Quest '{quest.questName}' abandoned.");
|
||||
}
|
||||
}
|
||||
|
||||
public void AbandonQuest(string questName)
|
||||
{
|
||||
Quest quest = allQuests.Find(q => q.questName == questName);
|
||||
if (quest != null)
|
||||
AbandonQuest(quest);
|
||||
else
|
||||
Debug.LogWarning($"Quest '{questName}' not found.");
|
||||
}
|
||||
|
||||
public void FailQuest(Quest quest)
|
||||
{
|
||||
if (activeQuests.Contains(quest))
|
||||
{
|
||||
activeQuests.Remove(quest);
|
||||
Debug.Log($"Quest '{quest.questName}' failed.");
|
||||
}
|
||||
}
|
||||
|
||||
public void FailQuest(string questName)
|
||||
{
|
||||
Quest quest = allQuests.Find(q => q.questName == questName);
|
||||
if (quest != null)
|
||||
FailQuest(quest);
|
||||
else
|
||||
Debug.LogWarning($"Quest '{questName}' not found.");
|
||||
}
|
||||
|
||||
public string[] GetPrerequisites(Quest quest)
|
||||
{
|
||||
return quest.prerequisiteNames;
|
||||
}
|
||||
|
||||
private bool ArePrerequisitesMet(Quest quest)
|
||||
{
|
||||
if (quest.prerequisiteNames == null || quest.prerequisiteNames.Length == 0)
|
||||
return true;
|
||||
|
||||
foreach (var prereqName in quest.prerequisiteNames)
|
||||
{
|
||||
Quest prereqQuest = allQuests.Find(q => q.questName == prereqName);
|
||||
if (prereqQuest == null || !completedQuests.Contains(prereqQuest))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void GetQuestDetails(Quest quest)
|
||||
{
|
||||
Debug.Log($"Quest Name: {quest.questName}");
|
||||
Debug.Log($"Description: {quest.questDescription}");
|
||||
Debug.Log($"Required Level: {quest.requiredLevel}");
|
||||
Debug.Log($"Reward Gold: {quest.rewardGold}");
|
||||
Debug.Log($"Reward Experience: {quest.rewardExperience}");
|
||||
Debug.Log($"Required Quantity: {quest.requiredQuantity}");
|
||||
}
|
||||
|
||||
public void GetQuestDetails(string questName)
|
||||
{
|
||||
Quest quest = allQuests.Find(q => q.questName == questName);
|
||||
if (quest != null)
|
||||
GetQuestDetails(quest);
|
||||
else
|
||||
Debug.LogWarning($"Quest '{questName}' not found.");
|
||||
}
|
||||
|
||||
public void CheckQuestStatus(Quest quest)
|
||||
{
|
||||
if (activeQuests.Contains(quest))
|
||||
{
|
||||
Debug.Log($"Quest '{quest.questName}' is currently active.");
|
||||
}
|
||||
else if (completedQuests.Contains(quest))
|
||||
{
|
||||
Debug.Log($"Quest '{quest.questName}' has been completed.");
|
||||
}
|
||||
else if (availableQuests.Contains(quest))
|
||||
{
|
||||
Debug.Log($"Quest '{quest.questName}' is available.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"Quest '{quest.questName}' is not available.");
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckQuestStatus(string questName)
|
||||
{
|
||||
Quest quest = allQuests.Find(q => q.questName == questName);
|
||||
if (quest != null)
|
||||
CheckQuestStatus(quest);
|
||||
else
|
||||
Debug.LogWarning($"Quest '{questName}' not found.");
|
||||
}
|
||||
|
||||
public List<Quest> GetAvailableQuests()
|
||||
{
|
||||
return new List<Quest>(availableQuests);
|
||||
}
|
||||
|
||||
public List<Quest> GetActiveQuests()
|
||||
{
|
||||
return new List<Quest>(activeQuests);
|
||||
}
|
||||
|
||||
public List<Quest> GetCompletedQuests()
|
||||
{
|
||||
return new List<Quest>(completedQuests);
|
||||
}
|
||||
|
||||
private void RefreshAvailableQuests()
|
||||
{
|
||||
availableQuests.Clear();
|
||||
|
||||
foreach (var quest in allQuests)
|
||||
{
|
||||
// Skip if already active or completed
|
||||
if (activeQuests.Contains(quest) || completedQuests.Contains(quest))
|
||||
continue;
|
||||
|
||||
// Check if prerequisites are met
|
||||
if (ArePrerequisitesMet(quest))
|
||||
{
|
||||
availableQuests.Add(quest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user