6.3 KiB
sotc-clash-arrow — Spécification Technique v1.0
Vue d'ensemble
Module FoundryVTT v11 permettant de tracer des flèches courbées entre les Dés de Vitesse du module Stars Initiative Overlay (SIO) de Vani, pour visualiser les clashes dans Star of the City (SotC).
S'appuie sur le module SBSA (clash-resolver) pour lire les compétences assignées aux dés.
Dépendances
| Module | Rôle |
|---|---|
stars-initiative-overlay |
Fournit les marqueurs PIXI des Dés de Vitesse |
clash-resolver (SBSA) |
Fournit les compétences stockées par dé via flags |
Logique des couleurs
| Couleur | Condition |
|---|---|
Bleu #4a9eff |
A cible B, mais B n'a pas de compétence active sur son dé |
Jaune #ffd84a |
A→B ET B→A existent simultanément (clash mutuel automatique) |
Gris #888899 |
Flèche de preview pendant le drag (avant relâchement) |
La détection du clash mutuel est automatique : dès que la flèche A→B est créée alors que B→A existe déjà, les deux flèches passent en jaune.
Interactions utilisateur
Tracer une flèche
- Maintenir clic gauche sur un Dé de Vitesse SIO
- Déplacer la souris vers un autre dé — la flèche preview change de couleur en temps réel selon la cible survolée
- Relâcher sur le dé cible → la flèche devient persistante
Qui peut tracer ? Tous les utilisateurs (GM et joueurs), depuis n'importe quel token.
Supprimer une flèche
- Clic droit sur un Dé de Vitesse → supprime toutes les flèches depuis/vers ce dé
Reset global
- Automatique au début d'un nouveau round (hook
updateCombat+ hook SIOsioRoundReset) - Automatique à la fin du combat (
deleteCombat) - Manuel via le bouton GM dans la barre de contrôles de scène (icône
×)
Architecture des fichiers
sotc-clash-arrow/
├── module.json
├── styles/
│ └── sotc-clash-arrow.css
├── lang/
│ ├── fr.json
│ └── en.json
└── scripts/
├── main.js ← point d'entrée
├── Hooks.js ← enregistrement des hooks FoundryVTT
├── ArrowStore.js ← store centralisé + sync socket
├── ClashArrowLayer.js ← couche PIXI (dessin des flèches)
├── DieInteraction.js ← gestion du drag souris
└── SIOBridge.js ← intégration SIO + détection compétences SBSA
Description des modules JS
main.js
- Point d'entrée unique chargé par
module.json - Expose
globalThis.sotcClashArrowpour débogage console - Vérifie la présence du module SIO au
ready
ArrowStore.js
- Store en mémoire (
Map<id, Arrow>) - Détecte automatiquement le clash mutuel à chaque
addArrow() - Synchronise via
game.socket(événementmodule.sotc-clash-arrow) pour que tous les clients voient les mêmes flèches - Émet un événement
change→ClashArrowLayerse redessine
Structure d'une flèche :
{
id : "tokenA:0→tokenB:1",
fromToken : "tokenA_id",
fromDie : 0,
toToken : "tokenB_id",
toDie : 1,
x1, y1 : number, // coords canvas du centre du dé source
x2, y2 : number, // coords canvas du centre du dé cible
mutual : boolean, // true = flèche jaune
}
ClashArrowLayer.js
- Hérite de
CanvasLayer(FoundryVTT v11) zIndex: 180→ au-dessus des tokens (100), sous l'UI (900+)- Deux
PIXI.Graphicsséparés : flèches persistantes + preview - Courbe de Bézier cubique avec pointe de flèche trigonométrique
BEZIER_CURVE = 0.35: facteur de courbure ajustable
DieInteraction.js
- Écoute
pointerdown(via hook internesotcca:diePointerDown) → démarre le drag pointermove→ met à jour la preview avec la couleur calculée en temps réelpointerup→ crée la flèche dansArrowStoresi une cible valide est sous le curseur
SIOBridge.js
getSIODieCenter(): littoken._initiativeMarkers[i].getBounds()pour les coords canvasfindDieUnderPoint(): parcourt tous les tokens/marqueurs, hit-test à ±24pxtokenHasActiveSkillOnDie(): combine état SIO (diceStates[i] !== 0) ET présence d'une compétence SBSA (flag "clash-resolver" → "dieSkills"[i])hookSIOMarkers(): attache les listeners sur les marqueurs PIXI existants + futurs (via hookrefreshToken)
Hooks.js
init: enregistrement du layer dansCONFIG.Canvas.layerscanvasReady: init socket + interactions + hook SIO markerscanvasTearDown:ArrowStore.clear()updateCombat(nouveau round) +sioRoundReset+deleteCombat→ resetgetSceneControlButtons: bouton reset GMsotcca:mutualClash: message chat signalant un clash mutuel
Chemins de données supposés (à vérifier)
⚠️ Ces chemins sont des hypothèses basées sur l'analyse du module SIO et SBSA. À valider lors des tests avec les modules installés.
| Donnée | Chemin supposé |
|---|---|
| Marqueurs PIXI SIO | token._initiativeMarkers[] |
| États des dés SIO | tokenDoc.getFlag("stars-initiative-overlay", "diceStates") → int[] |
| Nombre de dés | actor.system.speed_dice.num_dice |
| Compétences par dé (SBSA) | tokenDoc.getFlag("clash-resolver", "dieSkills") → string[] |
| Hook reset SIO | "sioRoundReset" (à confirmer dans la source SIO) |
Synchronisation multi-clients
Toutes les modifications du store sont broadcastées via game.socket.emit("module.sotc-clash-arrow", payload).
Les autres clients reçoivent le payload et appliquent la même modification localement sans re-broadcaster, pour éviter les boucles.
Actions socket :
add: nouvelle flèche (+ mise à jour éventuelle de la flèche inverse)remove: suppression d'une flèche (+ dés-mutualisation de l'inverse)clear: reset total
Notes d'implémentation
- Le layer PIXI est enregistré dans
CONFIG.Canvas.layersau hookinit, avant la construction du canvas - Les listeners sur les marqueurs SIO sont attachés avec un délai de 50ms après
refreshTokenpour laisser SIO finir de recréer ses containers PIXI - Un marqueur déjà hookié est marqué
marker._sotcca_hooked = truepour éviter les doublons - La flèche de preview utilise
alpha = 0.55pour la distinguer des flèches persistantes (alpha = 0.92)