> For the complete documentation index, see [llms.txt](https://megacrush.gitbook.io/megacrush-unity-assets/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://megacrush.gitbook.io/megacrush-unity-assets/runtime-spawner/runtime-spawner-user-manual/getting-started/specials-telemetry-system/how-to-using-specials-telemetry.md).

# How to: Using Specials Telemetry

## Prerequisites

* Runtime Spawner is in your scene and calls `Init(...)` → `Begin()` on startup.
* A `SpecialEncounterManager` is present and assigned a `SpecialProfile` with at least one `SpecialRule`.
* Your project has TextMeshPro and the Diagnostics HUD in the scene (or you’ve added it).

## 1) Choose how you’ll provide telemetry

You can feed “Pressure” and “Average Player HP” into specials via either:

* **Option A (Inspector / ScriptableObject):** subclass `SpecialsTelemetryProvider` and assign the asset on the manager.
* **Option B (Code / Interface):** implement `ISpecialsTelemetry` and inject the instance at runtime.

Both options can coexist; if you call `SetTelemetryProvider(...)` at runtime, that overrides the SO field.

***

## 2) Option A - ScriptableObject provider (Inspector setup)

1. Create a provider asset:
   * Right‑click in Project: **Create → MegaCrush → Spawner → Specials Telemetry** (use your subclass or the `BasicSpecialsTelemetry` sample under `Samples~` for testing).
2. Assign it:
   * Select your `SpecialEncounterManager` in the scene.
   * Drag the provider asset into the **Telemetry Provider** field.
3. Hook your real data (recommended):
   * In your subclass of `SpecialsTelemetryProvider`, implement:

     ```csharp
     public override bool TryGetPressure(out float value) { /* set value */ }
     public override bool TryGetAveragePlayerHP(out float value) { /* set value */ }
     ```
   * Pull values from your game systems (difficulty/AI director, health system, etc.).

Notes:

* The sample asset exposes static sliders - useful to prove the pipeline works, then replace with a real subclass.

***

## 3) Option B - Code provider (runtime injection)

1. Implement the interface anywhere in your game:

   ```csharp
   using MegaCrush.Spawner;

   public sealed class MyTelemetry : ISpecialsTelemetry
   {
       public bool TryGetPressure(out float value)
       {
           // Example: normalized by your max enemy budget
           value = CurrentEnemyCount / (float)MaxEnemyBudget;
           return true;
       }

       public bool TryGetAveragePlayerHP(out float value)
       {
           // Example: average over all active players (0..1)
           value = ComputeAveragePlayerHealthNormalized();
           return true;
       }
   }
   ```
2. Inject it before specials begin:

   ```csharp
   // wherever you bootstrap spawner systems after SpecialEncounterManager.Init(...)
   var specials = FindAnyObjectByType<SpecialEncounterManager>();
   specials.SetTelemetryProvider(new MyTelemetry());
   ```

***

## 4) Configure rules that use telemetry

Open your `SpecialProfile` and for any `SpecialRule` you want gated:

* Set **minPressure** to a threshold (e.g., `0.75`).
* Set **minAvgPlayerHP** (0..1) if you want to avoid spawning when players are very low.
* Ensure **stepRange**, **maxAlive**, **evalEverySeconds**, **cooldownSeconds**, **distanceRange**, and **spawnTag** are configured sensibly.

Behavior:

* If a rule requires telemetry but no provider is available, the rule’s condition fails (special won’t spawn). Everything else continues to work.

***

## 5) Enable the Diagnostics HUD timing (optional but recommended)

If you’ve updated the HUD with the added fields:

* Assign in the HUD inspector:
  * **SpecialsTimerText**
  * **SpecialsLastSpawnText**
  * **SpecialsNextTagText**
* In play mode, you’ll see:
  * “Specials: next in Xs (at Y.s)” - the next evaluation ETA.
  * “Last special: Ns ago” - last successful special time.
  * “Next Tag: …” - the planned tag (best effort debug hint).

The Population section’s **Total Active** shows the live count, and the per‑source breakdown helps confirm sources (Global/Region/Wave/Special).

***

## 6) Quick test workflow

1. Put your player into the scene and ensure `RuntimeSpawner` knows the **PlayerTransform**.
2. Use the sample `BasicSpecialsTelemetry` asset (Option A) and set:
   * `pressure = 0.9`
   * `averagePlayerHP = 1.0`
3. In your `SpecialProfile`, set one rule with:
   * `minPressure = 0.8`
   * `minAvgPlayerHP = 0.5`
   * Reasonable `evalEverySeconds` (e.g., 1–3s) and `cooldownSeconds` (e.g., 10–20s).
4. Enter Play:
   * Watch the HUD: ETA should count down; last spawn updates when a special appears.
   * If you’re step‑gated, advance your Director step and verify the HUD updates “Intensity Step”.

Tip (Editor only): you can use the context menu **Force Specials Roll Now** on `SpecialEncounterManager` to arm all rules immediately. This is wrapped in `#if UNITY_EDITOR` and excluded from builds.

***

## 7) Troubleshooting

* **“Specials: (unscheduled)”**\
  Likely all rules are ineligible (step gating, no rules, or evaluation times in the future). Advance the Director step or reduce thresholds.
* **No spawns despite positive thresholds**\
  Check:
  * `minGapSeconds` on the profile (global cooldown).
  * `maxAlive` for the rule (you may be at cap).
  * Anchor availability: ensure `WaveSpawnPoint`s exist with matching `spawnTag`, correct `distanceRange`, and LOS setting (if `requireNoLOS`, confirm an occluder actually blocks).
  * Telemetry provider returns `true` and supplies values that meet thresholds.
* **HUD “Total Active” climbs forever**\
  Ensure you’re on the updated HUD that uses `_pop.Current` for the live count.
* **Nothing happens after scene load**\
  Confirm your flow calls: `RuntimeSpawner.Init(...)` → `SpecialEncounterManager.Init(...)` (done by spawner) → `RuntimeSpawner.StartSpawners()` → `SpecialEncounterManager.Begin()` (called by spawner).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://megacrush.gitbook.io/megacrush-unity-assets/runtime-spawner/runtime-spawner-user-manual/getting-started/specials-telemetry-system/how-to-using-specials-telemetry.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
