# Exports et événements

MasterLadder expose des **exports** et des **événements** pour que vos autres scripts (dispatch, HUD, scripts de feu, métiers…) sachent ce qui se passe sur les échelles. Le nom de la ressource doit rester `MasterLadder`.

Unités : angles en **degrés**, distances en **mètres**. Une échelle est identifiée par le **netId** de son véhicule.

## Places

| Code | Place |
|---|---|
| `seat` | Poste de commande (tourelle) |
| `b1`, `b2`, `b3` | Places de la nacelle |
| `c1`, `c2` | Sur l'échelle (montée à pied) |

## État d'une échelle (`GetLadderState`)

Les deux côtés renvoient la même table (ou `nil` si l'échelle n'est pas déployée) :

| Champ | Contenu |
|---|---|
| `netId`, `model`, `label` | Véhicule, clé dans `Config.Ladders`, nom affiché |
| `phase` | calage automatique : `"deploy"` (calage), `"ready"` (manœuvrable), `"pack"` (repli) · calage manuel : `"setup"` (stabilisateurs au pupitre), `"unfold"` (dépliage), `"ready"`, `"fold"` (repli de la nacelle), `"abort"` (abandon, rangement automatique) |
| `calage` | `"full"`, `"reduced"`, `"left"` (gauche réduit) ou `"right"` (droit réduit) |
| `rotation`, `elevation`, `length`, `arm` | Position de l'échelle (°, °, m de longueur totale, °) |
| `basket` | Position de la nacelle (`vector3`) |
| `reach`, `maxReach` | Déport actuel et déport maximal de l'abaque (m) |
| `load` | Personnes comptées dans la charge |
| `occupants` | `{ seat = id, b1 = id, … }` (0 = libre) |
| `operator` | ID serveur de l'opérateur aux commandes (0 = personne) |
| `basketLocked`, `spotlight` | Verrou de nacelle, projecteur |
| `monitor` | `{ holder, flowing, yaw, pitch }` (+ `impact` côté client) |

Côté client s'ajoutent `vehicle` (entité) et `height` (hauteur de la nacelle au-dessus du sol).

## Exports client

```lua
local ml = exports['MasterLadder']
```

| Export | Retour |
|---|---|
| `ml:GetPlace()` | `netId, place` du joueur, ou `nil` |
| `ml:IsInLadder()` | Le joueur occupe une place |
| `ml:IsInBasket()` / `ml:IsClimbing()` / `ml:IsAtSeat()` | Nacelle / sur l'échelle / au poste |
| `ml:IsOperator()` | Le joueur a les commandes |
| `ml:IsHoldingMonitor()` | Le joueur tient la lance |
| `ml:IsLadderVehicle(veh)` | Ce véhicule est une échelle configurée |
| `ml:IsDeployed(veh)` | Cette échelle est déployée |
| `ml:GetLadderState(netId)` | Table d'état (échelles affichées chez ce joueur) |
| `ml:GetBasketCoords(netId)` | Position de la nacelle |
| `ml:IsWaterFlowing(netId)` | La lance débite |
| `ml:GetWaterImpact(netId)` | Point d'impact du jet (`vector3`) |
| `ml:GetNearestLadder(range)` | `netId, distance` de l'échelle déployée la plus proche (défaut 50 m) |
| `ml:GetVisibleLadders()` | Liste des netId des échelles affichées |

Exemple : couper un HUD de vitesse dans la nacelle.

```lua
CreateThread(function()
    while true do
        Wait(500)
        local inBasket = exports['MasterLadder']:IsInBasket()
        -- masquer / afficher votre HUD ici
    end
end)
```

## Exports serveur

| Export | Retour |
|---|---|
| `IsDeployed(netId)` | L'échelle est déployée |
| `GetLadderState(netId)` | Table d'état |
| `GetDeployedLadders()` | Liste des netId déployés |
| `GetBasketCoords(netId)` | Position de la nacelle |
| `GetPlayerPlace(src)` | `netId, place` du joueur, ou `nil` |
| `GetOccupants(netId)` | `{ place = src }` des places occupées |
| `IsWaterFlowing(netId)` | La lance débite |
| `EjectPlayer(src)` | Fait descendre le joueur de sa place (`true` si fait) |
| `EvictLadder(netId)` | Vide toutes les places et rend les commandes |
| `StopWater(netId)` | Ferme le jet (le porteur peut le rouvrir) |

## Événements serveur

À écouter avec `AddEventHandler` dans une ressource serveur :

| Événement | Paramètres | Quand |
|---|---|---|
| `masterladder:deployed` | `netId, src, calage` | Déploiement lancé (`"full"` / `"reduced"` ; `"manual"` au début d'un calage manuel) |
| `masterladder:ready` | `netId` | Calage terminé |
| `masterladder:packing` | `netId, src` | Repli lancé |
| `masterladder:packed` | `netId` | Échelle rangée |
| `masterladder:ptoChanged` | `netId, src, engagée` | Prise de force engagée / désengagée |
| `masterladder:placeChanged` | `netId, src, place` | Place prise, ou quittée (`place = nil`) |
| `masterladder:controlChanged` | `netId, src` | Opérateur aux commandes (0 = personne) |
| `masterladder:monitorChanged` | `netId, src` | Porteur de la lance (0 = personne) |
| `masterladder:waterChanged` | `netId, src, ouvert` | Jet ouvert / fermé |
| `masterladder:waterImpact` | `netId, src, coords` | Impact du jet, 2 fois par seconde |

### Brancher un script de feu

```lua
-- server.lua de votre script de feu
AddEventHandler('masterladder:waterImpact', function(netId, src, coords)
    -- éteindre / affaiblir vos feux autour de coords (rayon ~3 m)
    MonScriptDeFeu.DamageAt(coords, 3.0, 25.0, src)
end)
```

## Événements client

| Événement | Paramètres | Quand |
|---|---|---|
| `masterladder:client:placeChanged` | `netId, place` | Ma place change (`nil, nil` quand je descends) |
| `masterladder:client:waterImpact` | `coords, rayon` | Impact du jet près de moi (feux éteints localement) |