wasteland till prisoner

This commit is contained in:
2026-02-13 18:16:32 +01:00
parent 9b449b22cb
commit 984deabf49
8 changed files with 3882 additions and 2737 deletions

View File

@@ -1,26 +1,24 @@
// --- THIS SCRIPT CAN BE PLACED ANYWHERE IN YOUR ASSETS FOLDER ---
using UnityEngine;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using PixelCrushers.DialogueSystem; // Required for [ConversationPopup] attribute
using PixelCrushers.QuestMachine;
using Invector.vCharacterController.vActions; // Required for the vTriggerGenericAction reference
using PixelCrushers.DialogueSystem;
using PixelCrushers.QuestMachine; // Required
using Invector.vCharacterController.vActions;
using UnityEngine.Events;
namespace Beyond
{
[AddComponentMenu("Beyond/Quests/Generic Quest Trigger")]
[RequireComponent(typeof(vTriggerGenericAction))] // IMPORTANT: Ensures the Invector trigger is always on the same GameObject
[RequireComponent(typeof(bTriggerGenericAction))]
public class GenericQuestTrigger : MonoBehaviour
{
#region --- ODIN-POWERED INSPECTOR ---
[Title("Invector Trigger Link")]
[InfoBox("This component links into the vTriggerGenericAction below and adds quest/dialogue functionality to its events.")]
[Required("A vTriggerGenericAction component is required on this GameObject.")]
[OnInspectorInit("FindTriggerReference")] // Odin attribute to auto-fill the reference on first view
public vTriggerGenericAction invectorTrigger;
[InfoBox("Links into bTriggerGenericAction to add quest/dialogue functionality.")]
[Required("A bTriggerGenericAction component is required.")]
[OnInspectorInit("FindTriggerReference")]
public bTriggerGenericAction invectorTrigger;
[Title("Quest and Dialogue Actions")]
[ListDrawerSettings(Expanded = true, DraggableItems = true, NumberOfItemsPerPage = 10)]
@@ -30,27 +28,22 @@ namespace Beyond
private GameObject _lastInteractor;
// This is a helper method for the Odin attribute [OnInspectorInit]
private void FindTriggerReference()
{
if (invectorTrigger == null)
{
invectorTrigger = GetComponent<vTriggerGenericAction>();
}
if (invectorTrigger == null) invectorTrigger = GetComponent<bTriggerGenericAction>();
}
#region --- CORE LOGIC (Lifecycle & Event Handlers) ---
#region --- CORE LOGIC ---
private void Start()
{
if (invectorTrigger == null)
{
Debug.LogError("GenericQuestTrigger requires a vTriggerGenericAction component, but none was found. Disabling component.", this);
this.enabled = false;
return;
}
// Subscribe our methods to the events on the Invector component
// Subscribe to Invector Events
invectorTrigger.OnPressActionInput.AddListener(() => HandleEvent(TriggerEventType.OnPressActionInput, _lastInteractor));
invectorTrigger.OnStartAnimation.AddListener(() => HandleEvent(TriggerEventType.OnStartAnimation, _lastInteractor));
invectorTrigger.OnEndAnimation.AddListener(() => HandleEvent(TriggerEventType.OnEndAnimation, _lastInteractor));
@@ -60,29 +53,20 @@ namespace Beyond
invectorTrigger.OnValidate.AddListener((interactor) => HandleEvent(TriggerEventType.OnValidate, interactor));
invectorTrigger.OnInvalidate.AddListener((interactor) => HandleEvent(TriggerEventType.OnInvalidate, interactor));
if (DialogueManager.instance != null)
{
DialogueManager.instance.conversationEnded += OnConversationEnded;
}
if (DialogueManager.instance != null) DialogueManager.instance.conversationEnded += OnConversationEnded;
}
private void OnDisable()
{
if (DialogueManager.instance != null)
{
DialogueManager.instance.conversationEnded -= OnConversationEnded;
}
if (DialogueManager.instance != null) DialogueManager.instance.conversationEnded -= OnConversationEnded;
// It's good practice to unsubscribe from events when disabled/destroyed to prevent memory leaks
if (invectorTrigger != null)
{
invectorTrigger.OnPressActionInput.RemoveListener(() => HandleEvent(TriggerEventType.OnPressActionInput, _lastInteractor));
invectorTrigger.OnStartAnimation.RemoveListener(() => HandleEvent(TriggerEventType.OnStartAnimation, _lastInteractor));
invectorTrigger.OnEndAnimation.RemoveListener(() => HandleEvent(TriggerEventType.OnEndAnimation, _lastInteractor));
invectorTrigger.OnPressActionInput.RemoveAllListeners();
invectorTrigger.OnStartAnimation.RemoveAllListeners();
invectorTrigger.OnEndAnimation.RemoveAllListeners();
invectorTrigger.OnPlayerEnter.RemoveListener(HandlePlayerEnter);
invectorTrigger.OnPlayerExit.RemoveListener(HandlePlayerExit);
invectorTrigger.OnValidate.RemoveListener((interactor) => HandleEvent(TriggerEventType.OnValidate, interactor));
invectorTrigger.OnInvalidate.RemoveListener((interactor) => HandleEvent(TriggerEventType.OnInvalidate, interactor));
}
}
@@ -112,8 +96,24 @@ namespace Beyond
{
if (action.triggerEvent == eventType)
{
// Check if the optional Dialogue System condition is met
if (action.condition == null || action.condition.IsTrue(interactor?.transform))
// 1. Check Dialogue System (Lua)
bool dsConditionMet = action.condition == null || action.condition.IsTrue(interactor?.transform);
// 2. Check Quest Machine (Synchronous State Check)
bool qmConditionMet = true;
if (action.questRequirements != null && action.questRequirements.Count > 0)
{
foreach (var req in action.questRequirements)
{
if (!req.IsMet())
{
qmConditionMet = false;
break;
}
}
}
if (dsConditionMet && qmConditionMet)
{
PerformAction(action, interactor);
}
@@ -136,31 +136,19 @@ namespace Beyond
break;
case ActionType.ExecuteLua:
if (!string.IsNullOrEmpty(action.luaCode))
{
Lua.Run(action.luaCode, true);
}
if (!string.IsNullOrEmpty(action.luaCode)) Lua.Run(action.luaCode, true);
break;
case ActionType.SendQuestMachineMessage:
if (!string.IsNullOrEmpty(action.questMachineMessage))
{
QuestMachineMessages.SendCompositeMessage(this, action.questMachineMessage);
}
if (!string.IsNullOrEmpty(action.questMachineMessage)) QuestMachineMessages.SendCompositeMessage(this, action.questMachineMessage);
break;
case ActionType.SetQuestState:
if (!string.IsNullOrEmpty(action.questID))
{
QuestMachine.SetQuestState(action.questID, action.questState);
}
if (!string.IsNullOrEmpty(action.questID)) QuestMachine.SetQuestState(action.questID, action.questState);
break;
case ActionType.SetQuestNodeState:
if (!string.IsNullOrEmpty(action.questID) && !string.IsNullOrEmpty(action.questNodeID))
{
QuestMachine.SetQuestNodeState(action.questID, action.questNodeID, action.questNodeState);
}
if (!string.IsNullOrEmpty(action.questID) && !string.IsNullOrEmpty(action.questNodeID)) QuestMachine.SetQuestNodeState(action.questID, action.questNodeID, action.questNodeState);
break;
case ActionType.InvokeUnityEvent:
@@ -172,29 +160,19 @@ namespace Beyond
#endregion
}
#region --- Action Definitions (Enums and Class) ---
#region --- Definitions ---
public enum TriggerEventType
{
OnPlayerEnter,
OnPlayerExit,
OnValidate,
OnInvalidate,
OnPressActionInput,
OnStartAnimation,
OnEndAnimation,
OnConversationEnd
OnPlayerEnter, OnPlayerExit, OnValidate, OnInvalidate, OnPressActionInput, OnStartAnimation, OnEndAnimation, OnConversationEnd
}
public enum ActionType
{
StartConversation,
ExecuteLua,
SendQuestMachineMessage,
SetQuestState,
SetQuestNodeState,
InvokeUnityEvent
StartConversation, ExecuteLua, SendQuestMachineMessage, SetQuestState, SetQuestNodeState, InvokeUnityEvent
}
[System.Serializable]
public class TriggeredAction
@@ -208,20 +186,24 @@ namespace Beyond
[EnumToggleButtons, HideLabel]
public ActionType actionType;
[BoxGroup("Settings")]
[Tooltip("Optional Dialogue System condition that must be true for this action to fire.")]
[DrawWithUnity] // <-- Tells Odin to use the Pixel Crushers drawer for this field.
[BoxGroup("Conditions")]
[LabelText("Dialogue Condition")]
[DrawWithUnity]
public Condition condition;
[BoxGroup("Conditions")]
[LabelText("Quest Requirements")]
[InfoBox("All requirements listed here must be met.")]
public List<QuestRequirement> questRequirements = new List<QuestRequirement>();
[BoxGroup("Settings")]
[ShowIf("actionType", ActionType.StartConversation)]
[ConversationPopup(false)] // <-- The Dialogue System attribute that creates the dropdown.
[DrawWithUnity] // <-- The Odin attribute that allows the above attribute to work.
[ConversationPopup(false)]
[DrawWithUnity]
public string conversation;
[BoxGroup("Settings")]
[ShowIf("actionType", ActionType.StartConversation)]
[Tooltip("The other participant in the conversation. If unassigned, this trigger object will be the conversant.")]
public Transform conversant;
[BoxGroup("Settings")]
@@ -235,18 +217,18 @@ namespace Beyond
[BoxGroup("Settings")]
[ShowIf("@this.actionType == ActionType.SetQuestState || this.actionType == ActionType.SetQuestNodeState")]
[DrawWithUnity] // <-- Tells Odin to use the Quest Machine drawer for the quest ID field.
public string questID;
// --- AMBIGUITY FIXED: Explicitly using Quest Machine types ---
[BoxGroup("Settings")]
[ShowIf("actionType", ActionType.SetQuestState)]
public PixelCrushers.QuestMachine.QuestState questState;
[BoxGroup("Settings")]
[ShowIf("actionType", ActionType.SetQuestNodeState)]
[DrawWithUnity] // <-- Tells Odin to use the Quest Machine drawer for the node ID field.
public string questNodeID;
// --- AMBIGUITY FIXED: Explicitly using Quest Machine types ---
[BoxGroup("Settings")]
[ShowIf("actionType", ActionType.SetQuestNodeState)]
public PixelCrushers.QuestMachine.QuestNodeState questNodeState;

View File

@@ -0,0 +1,40 @@
using UnityEngine;
using Sirenix.OdinInspector; // Required for [ShowIf]
using PixelCrushers.QuestMachine; // Required for Quest Machine types
namespace Beyond
{
[System.Serializable]
public class QuestRequirement
{
[Tooltip("The ID of the quest to check. (Case-sensitive, copy from Quest Editor)")]
public string questID;
[Tooltip("If checking a specific node, enter ID here. Leave empty to check the overall Quest State.")]
public string questNodeID;
[ShowIf("@string.IsNullOrEmpty(this.questNodeID)")]
[Tooltip("The state the Main Quest must be in.")]
public QuestState requiredQuestState = QuestState.Active;
[ShowIf("@!string.IsNullOrEmpty(this.questNodeID)")]
[Tooltip("The state the specific Node must be in.")]
public QuestNodeState requiredNodeState = QuestNodeState.Active;
public bool IsMet()
{
if (string.IsNullOrEmpty(questID)) return true;
if (string.IsNullOrEmpty(questNodeID))
{
// CHECK QUEST STATE
return QuestMachine.GetQuestState(questID) == requiredQuestState;
}
else
{
// CHECK NODE STATE
return QuestMachine.GetQuestNodeState(questID, questNodeID) == requiredNodeState;
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4eb8c508c00e347708412631a7d08e68