# Mapping Tools

## Current baseline
- `Code/World/MappingTools/Core/MapSignalRouting.cs` is still the shared IO backbone: named inputs, optional direct component links, text-based `TargetName` fallback, tag-based broadcasts, optional delays, and `IMapSignalReceiver`.
- `Code/World/MappingTools/Interaction/Buttons/FuncButton.cs` is the authoritative generic button primitive. It combines direct use, signal inputs, optional physical press movement, lock state, cooldown/hold/toggle behavior, reset-safe state, start/finish button sounds, and automatic model-collider fallback when authored on renderer-based objects.
- `Code/World/MappingTools/Movement/Binary/FuncMoveLinear.cs` is the authoritative linear movement primitive for authored sliding doors, elevators, and other two-point movers. It can mirror partner movers through `PartnerName`, play start/finish movement sounds, and auto-create model colliders for renderer-authored content when no custom collider exists.
- `Code/World/MappingTools/Movement/Path/PathTrack.cs` and `Code/World/MappingTools/Movement/Path/PathPoint.cs` are the mapper-facing path authoring primitives. They keep multi-stop route data visible in-editor through point objects, ordered route resolution, optional track-name fallbacks, stop/pass-through metadata, wait times, optional call/depart targets, and full polyline gizmo previews.
- `Code/World/MappingTools/Movement/Path/FuncMovePath.cs` is the authoritative multi-point movement primitive. It resolves a `PathTrack`, exposes payload-driven path inputs like `GoTo`, `CallOrDepart`, `Next`, `Previous`, `Start`, `Stop`, `Pause`, `Resume`, `Reverse`, and `Reset`, keeps explicit host-side runtime state, and leaves spline sampling as an obvious future extension.
- `Code/World/MappingTools/Movement/Binary/FuncDoorRotating.cs` is the authoritative rotating-door primitive with reset-safe baseline capture, lock state, signal inputs, open-away behavior, start/finish door sounds, optional partner-door mirroring through `PartnerName`, and an optional `PivotTarget` hinge anchor for Hammer/brush-authored doors.
- `Code/World/MappingTools/Interaction/Buttons/RoleButtonComponent.cs` is the authored role-gated button primitive. It keeps the existing world-space UI panel flow, but now participates in map IO, reset state, lock state, and multiplayer-safe activation.
- `Code/World/MappingTools/Interaction/State/MapEnableTarget.cs` is the generic authored enable-state receiver for lights, emitters, and other component or GameObject toggles that need to participate in map IO.
- `Code/World/MappingTools/Triggers/MapTriggerBox.cs` is the authored trigger-volume base primitive for occupancy-driven logic and signal-controlled trigger spaces.
- `Code/World/MappingTools/Triggers/MapTriggerHurt.cs` mirrors the engine `TriggerHurt` authoring surface, but routes damage through the TerrorTown damage pipeline.
- `Code/World/MappingTools/Triggers/MapTriggerRoleTester.cs` is the authored role-aware tester volume for chambers, trap logic, and role-sensitive occupancy checks.
- `Code/World/MappingTools/Spawners/` remains the mapper-facing home for authored weapon, ammo, and grenade spawners, while `Code/World/MappingTools/Legacy/LegacyObjectSpawner.cs` holds the compatibility-only object bridge.

## Folder and editor layout
- Interaction sources live under `TTT Mapping Tools/Interaction/Buttons`.
- Generic state receivers live under `TTT Mapping Tools/Interaction/State`.
- Two-state movers and doors live under `TTT Mapping Tools/Movement/Binary`.
- Track-based movers and path authoring helpers live under `TTT Mapping Tools/Movement/Path`.
- Occupancy-driven logic stays under `TTT Mapping Tools/Triggers`.
- Compatibility bridges live under `TTT Mapping Tools/Legacy`.

## Authoring model
- The intended authored surface is one authoritative component per primitive:
  - `FuncButton`
  - `FuncMoveLinear`
  - `FuncMovePath`
  - `FuncDoorRotating`
  - `RoleButtonComponent`
  - `MapEnableTarget`
  - `MapTriggerBox`
  - `MapTriggerHurt`
  - `MapTriggerRoleTester`
  - `PathTrack`
  - `PathPoint`
- Higher-level concepts like sliding doors and elevators should be presets or prefabs built on top of these primitives, not duplicate runtime wrapper components.
- Multi-stop elevators should now be authored as `FuncMovePath` plus `PathTrack` plus floor buttons. The mover owns the runtime state, while the track and points stay mapper-facing and reusable for trains or future spline-following movers.
- For targeting, prefer `TargetName` as the baseline authoring path because it works in both Hammer-style workflows and scene-authored maps. Use direct component references as a convenience when the editor supports them cleanly, and use `TargetTag` for one-to-many broadcasts.
- For path authoring, prefer a `PathTrack` root with child `PathPoint` objects in scene-authored content. For Hammer-style workflows, `FuncMovePath.TrackName` and `PathPoint.TrackName` provide text-match fallbacks when direct references or clean parenting are unavailable.
- `PathPoint.DepartureTarget` and `PathPoint.DepartureTargetName` are optional helpers for `CallOrDepart` authoring. They are mainly useful on 3+ stop tracks; 2-point tracks automatically depart to the other point.
- For rotating doors authored from Hammer meshes or brush-like geometry, either set the Hammer origin to the hinge and leave `Pivot` at zero, or assign `FuncDoorRotating.PivotTarget` to a dedicated hinge helper object when that is more convenient.
- `FuncMoveLinear`, `FuncMovePath`, `FuncDoorRotating`, and `FuncButton` will auto-create model colliders from authored renderer trees when no collider exists yet. This is meant to remove the extra "add a collider just so use/traces work" step for common model-based map props while still letting custom colliders win when authors place them explicitly.
- `PartnerName` on `FuncMoveLinear` and `FuncDoorRotating` is intended for Source-style double doors and other paired movers. It resolves exact GameObject names in-scene and mirrors open, close, toggle, lock, and unlock actions across the matching partner objects.
- `RoleButtonComponent` still respects `RoleVisibilityPolicy`: the overlay only appears for valid viewers, and activation requires a real player activator instead of a null-activator logic bypass.
- `MapEnableTarget` is the generic glue for map-authored lights and similar stateful scene pieces. Attach it next to the target component you want to drive, then feed it `Start`/`Stop`, `Toggle`, or `Activate`. It also accepts `Open`/`Close` and `Occupied`/`Empty` aliases to make trigger and tester wiring less awkward.

## Elevator patterns
- Standard call buttons should usually send `GoTo` with the destination point name or zero-based index.
- Floor buttons that should also send the platform away when it is already present should send `CallOrDepart` with that floor's point name.
- `CallOrDepart` first resolves the payload to a point on the track.
- If the mover is away from that point, it behaves exactly like `GoTo` and calls the mover there.
- If the mover is already idle at that point, it departs from that point instead.
- On 2-point tracks, departure automatically means "go to the other point."
- On 3+ point tracks, departure uses `PathPoint.DepartureTarget` or `PathPoint.DepartureTargetName` on the named point.
- If a 3+ point track receives `CallOrDepart` while already at that point and no valid departure target is configured, the input is rejected and the mover warns in the log.
- This keeps bunker lifts, hidden floor platforms, and similar "present here means send away, absent means call here" interactions mapper-friendly without changing the meaning of plain `Toggle`.

## Reset and map-root notes
- Authored primitives should reset themselves through `IResettable`; they should not spawn helper children just to function.
- `MapNetworkRoot` should stay focused on true runtime-spawned objects such as spawner products or legacy-load conversions.
- `FuncButton`, `FuncMoveLinear`, `FuncMovePath`, `FuncDoorRotating`, `RoleButtonComponent`, `MapEnableTarget`, `MapTriggerBox`, `MapTriggerHurt`, and `MapTriggerRoleTester` are all intended to participate in the existing fast-reset path.
- This keeps the reset registry simpler and avoids scene churn from unnecessary helper objects.

## Multiplayer motion pattern
- For authored movers and buttons, the host remains authoritative for signal acceptance, direct-use acceptance, lock state, queueing, traversal decisions, and completion/output firing.
- Hammer-authored runtime primitives must be promoted into real network objects during map load. `Code/World/MapEntities/MapAuthoredNetworkingBootstrap.cs` does this in place for `FuncButton`, `FuncMoveLinear`, `FuncDoorRotating`, `FuncMovePath`, `RoleButtonComponent`, `MapEnableTarget`, `MapTriggerBox`, `MapTriggerHurt`, and `MapTriggerRoleTester` by switching them to `NetworkMode.Object` and host-spawning them when needed.
- Once the authored primitive is a real network object, host-owned `LocalPosition` and `LocalTransform` writes replicate normally. This is the intended path for button travel, sliding doors, rotating doors, and path movers.
- Keep synced state focused on gameplay semantics that other systems care about:
  - toggle/open state,
  - lock state,
  - moving/busy state,
  - and explicit path runtime state like current and target point indices.
- Do not add per-motion replicated clocks or transform snapshots unless a future primitive proves that plain network-object transform replication is insufficient.
- `Code/World/MapEntities/MapMotionPlayback.cs` remains a small helper for host-side motion timing and normalized-progress evaluation. It is not the primary replication mechanism for authored map movers.
- Reset, stop, interrupt, pause, resume, reverse, and auto-reset paths must still update gameplay state and the host-side motion clock together so late outputs and stale timers do not survive a reset.
- `MapNetworkRoot` is still not the fix for authored mover replication. It is a parent for true runtime-spawned map objects, not a general-purpose authority layer for authored scene objects.
- When adding a new authored movement primitive, first make sure it is part of the authored-network bootstrap, then verify presentation and collision from both host and client perspectives before adding extra sync state.

## Immediate follow-up work
- Validate direct use and signal-driven activation in the s&box editor.
- Verify elevator ride-along with the current movement controller assumptions.
- Extend `PathTrack` sampling from polyline motion to optional spline interpolation when the editor-side UX is ready.
- Add logic primitives inspired by the old Hammer set: `logic_auto`, `logic_relay`, `math_counter`, and `logic_case`.
