> For the complete documentation index, see [llms.txt](https://malbersanimations.gitbook.io/animal-controller/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://malbersanimations.gitbook.io/animal-controller/malbers-questforge/dialogue-system/dialogue-trigger.md).

# Dialogue Trigger

### Overview

**DialogueTrigger** is a MonoBehaviour that connects the physical game world to a `DialogueContainerSO` graph. Add it to any GameObject — an NPC, a trigger zone, a chest, a doorway — and configure how and when it fires. It handles all gate logic (cooldowns, conditions, one-shot flags), integrates automatically with the **Malbers MInteract** system, reports NPC conversations to the **Quest System** for TalkTo objectives, and persists its triggered state through the **Dialogue Save System**.

> Add via **Component menu: `Malbers Quest Forge → Dialogue Trigger`**

***

<figure><img src="/files/VKFNQa5wfREho7S82oCc" alt=""><figcaption></figcaption></figure>

### Trigger Types

The **Trigger Type** field determines what causes the dialogue to fire.

| Type                | Behaviour                                                                                                            | Requirements                                                                                            |
| ------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| **OnInteract**      | Auto-subscribes to the `MInteract.OnInteractWithGO` event on the same GameObject.                                    | MInteract component on the same GameObject (can be auto-added from the Inspector).                      |
| **OnEnter**         | Fires when a tagged GameObject enters the attached Collider or Collider2D.                                           | A Collider/Collider2D set as **Is Trigger**. The Inspector provides quick-add buttons if none is found. |
| **OnQuestStart**    | Fires when a specific quest becomes active. Connect `QuestManager.OnQuestStarted` → `OnQuestStarted(string)`.        | Requires **Required Quest Active** to be assigned.                                                      |
| **OnQuestComplete** | Fires when a specific quest is completed. Connect `QuestManager.OnQuestCompleted` → `OnQuestCompleted(string)`.      | Requires **Required Quest Completed** to be assigned.                                                   |
| **Manual**          | Does nothing automatically. Call `TriggerDialogue()` or `TriggerDialogue(GameObject)` from any UnityEvent or script. | None.                                                                                                   |

***

### Inspector Sections

The custom Inspector organises all settings into collapsible foldouts.

**Dialogue Settings**

| Property     | Type                  | Description                                                                                         |
| ------------ | --------------------- | --------------------------------------------------------------------------------------------------- |
| **Dialogue** | `DialogueContainerSO` | The dialogue graph to execute when this trigger fires. Required — a warning is shown if left empty. |

**Trigger Settings**

| Property          | Type   | Default      | Description                                                                                                                                                              |
| ----------------- | ------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Trigger Type**  | Enum   | `OnInteract` | How the dialogue is initiated. See the Trigger Types table above.                                                                                                        |
| **Required Tag**  | String | `"Player"`   | The GameObject tag that is allowed to trigger this dialogue. Leave empty to accept any tag. Used for MInteract, OnEnter, and the `TriggerDialogue(GameObject)` overload. |
| **Trigger Once**  | Bool   | `false`      | When `true`, the trigger deactivates after the first successful activation. Subsequent calls invoke `OnTriggerBlocked` instead.                                          |
| **Cooldown Time** | Float  | `0`          | Minimum seconds between consecutive triggers. `OnTriggerBlocked` fires if the cooldown has not elapsed.                                                                  |

**MInteract Integration&#x20;*****(OnInteract mode only)***

| Property                | Type        | Default     | Description                                                                                                 |
| ----------------------- | ----------- | ----------- | ----------------------------------------------------------------------------------------------------------- |
| **Auto-Subscribe**      | Bool        | `true`      | Automatically subscribes to `MInteract.OnInteractWithGO` at runtime Start. Disable to wire it manually.     |
| **MInteract Reference** | `MInteract` | Auto-detect | Explicit reference to the MInteract component. If left blank, `GetComponent<MInteract>()` is used at Awake. |

The Inspector displays the detected MInteract's **Index**, **Auto Interact**, and **Single Interaction** settings, and provides an **Add MInteract Component** button if none is found.

**Quest System Integration**

Controls whether talking to this NPC marks a **TalkTo** quest objective as complete.

| Property                   | Type   | Default | Description                                                                                                                                 |
| -------------------------- | ------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| **Report to Quest System** | Bool   | `true`  | When enabled, triggers `QuestEventReporter.ReportNPCTalkedTo(npcId, dialogueName)`.                                                         |
| **Use GameObject Name**    | Bool   | `true`  | Derives the NPC ID from the GameObject's name. Strips `(Clone)`, `(clone)`, trailing numbers, and whitespace.                               |
| **NPC ID**                 | String | `""`    | Manual NPC ID. Only shown when **Use GameObject Name** is disabled. Must exactly match the `npcId` field on the matching `TalkToObjective`. |
| **Report On Start**        | Bool   | `true`  | `true` = report when dialogue *begins*. `false` = report when dialogue *ends* (uses a `pendingQuestReport` flag).                           |

The Inspector previews the resolved NPC ID in real time and, while playing, lists all active quests whose `TalkToObjective.npcId` matches this trigger.

**NPC ID Resolution Priority:**

1. `npcId` field (if not empty)
2. Cleaned GameObject name (if **Use GameObject Name** is `true`)
3. Empty string (quest reporting silently skipped with a warning)

**Save System Integration**

| Property                     | Type   | Default | Description                                                                                                                                                                                                  |
| ---------------------------- | ------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Auto Generate Trigger ID** | Bool   | `true`  | Generates a deterministic ID from: `{SceneName}_{ObjectName}_{posX*100}_{posY*100}_{posZ*100}`. Stable across sessions as long as the object doesn't move.                                                   |
| **Custom Trigger ID**        | String | `""`    | Overrides auto-generation. Use this for spawned/procedural triggers, or when the same NPC exists in multiple scenes.                                                                                         |
| **Save Trigger State**       | Bool   | `true`  | Writes to `DialogueSaveSystem` immediately on trigger (before the dialogue starts, so destruction mid-dialogue is safe). On `Start`, reads the save system and pre-sets `hasTriggered` if already completed. |

> The current Trigger ID is displayed as a selectable label during Play Mode for easy debugging or manual save manipulation.

**Conditions**

All conditions are optional. All assigned conditions must pass for the trigger to fire.

| Property                     | Type     | Description                                                                                                                                                                             |
| ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Required Quest Active**    | `Quest`  | The referenced quest must currently be active in the QuestManager.                                                                                                                      |
| **Required Objective**       | Dropdown | *(Shown when Required Quest Active is assigned.)* A specific objective within that quest must match the status below. Populated as a labelled dropdown from the quest's objective list. |
| **Objective Status**         | Enum     | `InProgress` = objective not yet complete. `Completed` = objective already finished.                                                                                                    |
| **Required Quest Completed** | `Quest`  | The referenced quest must be in the completed state.                                                                                                                                    |
| **Required Dialogue Flag**   | String   | A flag with this name must be set (`true`) in `DialogueManager.GetFlag()`.                                                                                                              |

**Events**

| Event                   | Signature    | When It Fires                                                                                                  |
| ----------------------- | ------------ | -------------------------------------------------------------------------------------------------------------- |
| **OnDialogueTriggered** | `UnityEvent` | Immediately after `DialogueManager.StartDialogue()` is called.                                                 |
| **OnDialogueEnded**     | `UnityEvent` | When `DialogueManager` raises `OnDialogueEnded` (subscribed at runtime Start).                                 |
| **OnTriggerBlocked**    | `UnityEvent` | When an activation attempt is rejected by: active dialogue, Trigger Once flag, cooldown, or failed conditions. |

***

### Trigger Gate Order

When `TriggerDialogue()` is called, checks run in this exact order. The first failure aborts the trigger and fires `OnTriggerBlocked` (where noted):

1. **Dialogue already active** — silently ignored (no `OnTriggerBlocked`).
2. **Trigger Once + already triggered** → `OnTriggerBlocked`.
3. **Cooldown not elapsed** → `OnTriggerBlocked`.
4. **Conditions not met** → `OnTriggerBlocked`.
5. **Dialogue asset null** → logs an error, aborts silently.
6. **DialogueManager.Instance null** → logs an error, aborts silently.
7. **All checks passed** → sets `hasTriggered = true`, records `lastTriggerTime`, saves state, reports to quest system if configured, calls `DialogueManager.Instance.StartDialogue(dialogue)`, fires `OnDialogueTriggered`.

***

### Public API

| Method                                   | Description                                                                                                                                                          |
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `TriggerDialogue()`                      | Runs the full gate check sequence and starts dialogue if all pass.                                                                                                   |
| `TriggerDialogue(GameObject interactor)` | Same as above but first validates `interactor.tag` against `requiredTag`. Suitable for wiring directly to MInteract's `OnInteractWithGO(GameObject)` event manually. |
| `ForceTriggerDialogue()`                 | Bypasses all gate checks (Trigger Once, cooldown, conditions). Skips directly to starting the dialogue. Quest reporting still occurs.                                |
| `ResetTrigger()`                         | Clears `hasTriggered`, allowing a Trigger Once trigger to fire again. Does not alter the save system record.                                                         |
| `ManualReportToQuestSystem()`            | Calls `QuestEventReporter.ReportNPCTalkedTo()` immediately. Safe to call from UnityEvents.                                                                           |
| `SetNpcId(string)`                       | Overrides the runtime NPC ID. Useful for dynamically assigned characters.                                                                                            |
| `SetCustomTriggerID(string)`             | Overrides the trigger ID at runtime. Use for spawned objects that need stable save IDs.                                                                              |
| `GetTriggerID()`                         | Returns the current resolved trigger ID string.                                                                                                                      |
| `RecheckSavedState()`                    | Re-queries the save system after a save file is loaded mid-session. Marks `hasTriggered` if the ID is already in the save.                                           |
| `OnQuestStarted(string questId)`         | Called by quest events; fires the dialogue if Trigger Type is `OnQuestStart` and the ID matches.                                                                     |
| `OnQuestCompleted(string questId)`       | Called by quest events; fires the dialogue if Trigger Type is `OnQuestComplete` and the ID matches.                                                                  |

**Read-only properties:**

| Property       | Type   | Description                                                                                          |
| -------------- | ------ | ---------------------------------------------------------------------------------------------------- |
| `HasTriggered` | Bool   | Whether this trigger has successfully fired at least once this session (or was loaded as completed). |
| `CanTrigger`   | Bool   | `true` if \`!hasTriggered                                                                            |
| `TriggerID`    | String | The resolved save-system identifier.                                                                 |
| `NpcId`        | String | The runtime-resolved NPC ID used for quest reporting.                                                |

***

### Scene Gizmos

In Scene view, the trigger always renders a **cyan wire sphere** (radius `0.5`) at its position. When selected, the sphere is drawn solid-cyan and a Scene label appears 1.5 units above showing:

```
Dialogue Trigger
<DialogueName or "No Dialogue">
<TriggerType> [(<MInteract Index or "No MInteract!">)]
```

***

### Inspector Testing Tools *(Play Mode Only)*

The **Status & Testing** foldout displays live runtime state and one-click test buttons:

| Button               | Action                                                                    |
| -------------------- | ------------------------------------------------------------------------- |
| **Trigger Dialogue** | Calls `TriggerDialogue()` — subject to all gate checks.                   |
| **Force Trigger**    | Calls `ForceTriggerDialogue()` — bypasses all checks.                     |
| **Reset Trigger**    | Calls `ResetTrigger()` — clears the `hasTriggered` flag.                  |
| **Report to Quest**  | Calls `ManualReportToQuestSystem()` — fires the quest report immediately. |

***

### Setup Checklist

Use this checklist when adding a Dialogue Trigger to a new NPC or zone:

* [ ] &#x20;Assign a **Dialogue** graph (`DialogueContainerSO`).
* [ ] &#x20;Choose the correct **Trigger Type** for your use case.
* [ ] &#x20;For **OnInteract**: ensure an `MInteract` component exists on the same GameObject.
* [ ] &#x20;For **OnEnter**: ensure the GameObject has a Collider with **Is Trigger** enabled.
* [ ] &#x20;For **OnQuestStart / OnQuestComplete**: wire the QuestManager events to `OnQuestStarted(string)` / `OnQuestCompleted(string)`.
* [ ] &#x20;If this NPC completes a **TalkTo** objective, confirm the **NPC ID** (shown in the Inspector preview) exactly matches `TalkToObjective.npcId` in the quest asset.
* [ ] &#x20;For one-shot cutscenes or story beats, enable **Trigger Once** and **Save Trigger State**.
* [ ] &#x20;For dialogue gated on quest progress, configure the **Conditions** section.
* [ ] &#x20;Enable **Debug Mode** during development to trace all trigger events in the console.

***

### Usage Tips

* **NPC with multiple dialogue states** — Use multiple `DialogueTrigger` components on the same NPC, each assigned a different dialogue, with Conditions gating which one fires. Order components so the most restrictive condition is checked first.
* **Preventing repeat cutscenes** — Enable both **Trigger Once** and **Save Trigger State** together. The save write happens *before* `StartDialogue` so the state is preserved even if the scene is destroyed or the player quits mid-dialogue.
* **Spawned NPCs** — For procedurally instantiated characters, call `SetCustomTriggerID()` immediately after spawning to assign a stable, unique ID. Auto-generation uses `transform.position` which may not be unique for spawned objects.
* **Cutscene zones** — Set Trigger Type to **OnEnter**, add a large Box Collider, enable **Trigger Once**, and leave Required Tag as `"Player"`. The dialogue fires the moment the player walks into the area with no interaction required.
* **Quest-gated introductions** — Set **Required Quest Active** to the relevant quest and leave **Required Objective** blank. The NPC will only speak once that quest is in progress.
* **Debug logging** — Enable **Debug Mode** to see every gate check, MInteract subscription, NPC ID resolution, and save write logged to the console, prefixed with `[DialogueTrigger] 'ObjectName'`.
