30 lines
12 KiB
JSON
30 lines
12 KiB
JSON
{
|
|
"name": "Clients",
|
|
"type": "script",
|
|
"command": "// =========================================================\n// 1. RECUPERATION DES CLIENTS\n// =========================================================\nconst clients = canvas.scene.tokens.filter(token =>\n token.actor.hasPlayerOwner === false &&\n token.actor.type === \"pnj\" &&\n token.actor.system.categorie === \"Client\"\n);\n\nif (clients.length === 0) {\n ui.notifications.warn(\"Aucun Client trouvé.\");\n return;\n}\n\n// =========================================================\n// 2. CONSTRUCTION DU CODE HTML (avec onglets et panel)\n// =========================================================\nlet tabsHtml = `<div class=\"macro-nav-container\" style=\"display: flex !important; flex-wrap: wrap !important; gap: 6px !important; margin-bottom: 12px !important; border-bottom: 2px solid #5b4634 !important; padding-bottom: 8px !important;\">`;\nlet panelsHtml = ``;\n\n// =========================================================\n// 3. POUR CHAQUE CLIENT\n// =========================================================\nclients.forEach((client, index) => {\n const sys = client.actor.system || {};\n \n // ---------------------------\n // Bouton d'onglet\n // ---------------------------\n tabsHtml += `\n <button class=\"custom-tab-trigger\" data-pc-id=\"${client.id}\" style=\"flex: 0 1 auto !important; background: rgba(226, 208, 177, 0.6) !important; border: 1px solid #5b4634 !important; border-radius: 6px !important; color: #221b18 !important; font-weight: bold !important; padding: 6px 12px !important; cursor: pointer !important; font-size: 0.85rem !important;\">\n ${client.name}\n </button>\n `;\n // ---------------------------\n // PERSONNAGE\n // ---------------------------\n const espece = sys.espece ?? \"humain\";\n const role = sys.role ?? \"\";\n const resume = sys.resume ?? \"\";\n const courage = sys.defense.courage.delta ?? \"\";\n \n // ---------------------------\n // SANTE\n // ---------------------------\n const pvVal = sys.sante?.pv?.value ?? 0;\n const pvMax = sys.sante?.pv?.max ?? 0;\n const dv = sys.sante?.dv ?? \"1d6\";\n\n // ---------------------------\n // ATTAQUES\n // ---------------------------\n const armureDelta = sys.defense.armure.delta;\n const armureProtectionStockee = sys.defense.armure.resultatProtection;\n const attaques = sys.attaques;\n let attaquesHtml = null;\n if(attaques.length > 0) {\n attaquesHtml = `\n <div class=\"favor-card\" style=\"grid-template-columns: repeat(3, 1fr); margin-top: 0; background: rgba(255, 255, 255, 0.45); border-radius: 10px;\">\n <div class=\"favor-header\"><h2>Attaques</h2></div>\n `;\n attaques.forEach(attaque => {\n attaquesHtml += `\n <div class=\"identity-grid\" style=\"display: flex; flex-direction: row; margin-bottom: 1rem; gap: 0.75rem;\">\n <div class=\"readonly-field\" style=\"flex: 2;\">\n <span>Arme</span>\n <p>${attaque.nom}</p>\n </div>\n <div class=\"readonly-field\" style=\"flex: 1;\">\n <span>Dégats</span>\n <p>${attaque.degats}</p>\n </div>\n </div> \n `;\n });\n attaquesHtml += `</div>`;\n }\n \n // ---------------------------\n // SORTS\n // ---------------------------\n const sorts = client.actor.items?.filter(item => item.type === \"sortilege\")\n let sortsHtml = \"\";\n if(sorts.length > 0) {\n sortsHtml = `\n <div class=\"favor-card\" style=\"margin-top: 0; background: rgba(255, 255, 255, 0.45); border-radius: 10px;\">\n <div class=\"favor-header\"><h2>SORTILEGES</h2></div>\n `;\n \n sorts.forEach(sort => {\n sortsHtml += `\n <div class=\"identity-grid\" style=\"display: flex; flex-direction: row; margin-bottom: 1rem; gap: 0.75rem;\">\n <div class=\"readonly-field\" style=\"flex: 1;\">\n <span>Nom</span>\n <p>${sort.name}</p>\n </div>\n <div class=\"readonly-field\" style=\"flex: 2;\">\n <span>Effet</span>\n <p>${sort.system.effet}</p>\n </div>\n </div> \n `;\n });\n sortsHtml += `</div>`;\n } \n\n // ---------------------------\n // CAPACITES\n // ---------------------------\n const capacites = client.actor.items?.filter(item => item.type === \"capacite\")\n let capacitesHtml = \"\";\n if(capacites.length > 0) {\n capacitesHtml = `\n <div class=\"favor-card\" style=\"margin-top: 0; background: rgba(255, 255, 255, 0.45); border-radius: 10px;\">\n <div class=\"favor-header\"><h2>CAPACITES</h2></div>\n `;\n \n capacites.forEach(capacite => {\n capacitesHtml += `\n <div class=\"identity-grid\" style=\"display: flex; flex-direction: row; margin-bottom: 1rem; gap: 0.75rem;\">\n <div class=\"readonly-field\" style=\"flex: 2;\">\n <span>Nom</span>\n <p>${capacite.name}</p>\n </div>\n <div class=\"readonly-field\" style=\"flex: 1;\">\n <span>Cout</span>\n <p>${capacite.system.cout}</p>\n </div>\n <div class=\"readonly-field\" style=\"flex: 4;\">\n <span>Effet</span>\n <p>${capacite.system.effet}</p>\n </div>\n </div> \n `;\n });\n capacitesHtml += `</div>`;\n }\n\n \n // ---------------------------\n // CONSTITUER LE HTML COMPLET\n // ---------------------------\n panelsHtml += `\n <div class=\"custom-pc-panel\" id=\"panel-pc-${client.id}\" style=\"width: 100% !important;\">\n <div class=\"identity-grid\" style=\"grid-template-columns: repeat(5, 1fr); margin-bottom: 1rem; gap: 0.75rem;\">\n <div class=\"readonly-field\">\n <span>Espèce</span>\n <p>${espece}</p>\n </div>\n <div class=\"readonly-field\">\n <span>Rôle</span>\n <p>${role}</p>\n </div> \n <div class=\"readonly-field\">\n <span>DV</span>\n <p>${dv}</p>\n </div>\n <div class=\"readonly-field\">\n <span>PV</span>\n <p><strong class=\"${pvVal <= 2 ? 'warning' : ''}\">${pvVal}</strong> / ${pvMax}</p>\n </div>\n <div class=\"readonly-field\">\n <span>Courage</span>\n <p>Δ${courage}</p>\n </div> \n </div>\n <div class=\"identity-grid\" style=\"grid-template-columns: repeat(1, 1fr); margin-bottom: 1rem; gap: 0.75rem;\">\n <div class=\"readonly-field\">\n <span>resume</span>\n <p>${resume}</p>\n </div>\n </div> \n\n ${attaquesHtml}\n\n <div class=\"favor-card\" style=\"margin-top: 0; background: rgba(255, 255, 255, 0.45); border-radius: 10px;\">\n <div class=\"favor-header\"><h2>Protection</h2></div>\n <div class=\"identity-grid\" style=\"grid-template-columns: repeat(2, 1fr); margin-bottom: 1rem; gap: 0.75rem;\">\n <div class=\"readonly-field\">\n <span>Armure</span>\n <p>${armureDelta}</p>\n </div>\n <div class=\"readonly-field\">\n <span>Protection stockée</span>\n <p>${armureProtectionStockee}</p>\n </div> \n </div>\n </div>\n \n ${sortsHtml}\n \n ${capacitesHtml}\n \n </div>`;\n});\n\ntabsHtml += `</div>`;\n\nlet content = `\n<div class=\"fvtt-donjon-et-cie dnc-sheet\" style=\"padding: 0; min-width: 580px; max-width: 700px;\">\n <div class=\"sheet-card\" style=\"display: flex !important; flex-direction: column !important;\">\n <h2>Les Clients</h2>\n ${tabsHtml}\n <div class=\"macro-panels-container\" style=\"width:100% !important;\">\n ${panelsHtml}\n </div>\n </div>\n</div>\n`;\n\n// =========================================================\n// 4. AFFICHE DE LA BOITE DE DIALOGUE\n// =========================================================\nconst dialog = await foundry.applications.api.DialogV2.wait({\n window: {\n title: \"Les Clients\",\n icon: \"fa-solid fa-shield-halved\"\n },\n content: content,\n classes: [\"fvtt-donjon-et-cie\"],\n buttons: [\n {\n action: \"close\",\n label: \"Fermer\",\n icon: \"fas fa-xmark\",\n callback: () => ({action: \"Fermer\"})\n } \n ],\n rejectClose: false,\n render: (event, dialog) => {\n const root = dialog.element;\n \n const triggers = root.querySelectorAll('.custom-tab-trigger');\n const panels = root.querySelectorAll('.custom-pc-panel');\n \n const setActiveTab = (activeId) => {\n triggers.forEach(btn => {\n const pcId = btn.getAttribute('data-pc-id');\n if (pcId === activeId) {\n btn.style.setProperty('background', '#8b2e17', 'important');\n btn.style.setProperty('color', '#ffffff', 'important');\n btn.style.setProperty('border-color', '#561d0e', 'important');\n } else {\n btn.style.setProperty('background', 'rgba(226, 208, 177, 0.6)', 'important');\n btn.style.setProperty('color', '#221b18', 'important');\n btn.style.setProperty('border-color', '#561d0e', 'important');\n }\n });\n \n panels.forEach(panel => {\n const panelId = panel.getAttribute('id');\n if (panelId === `panel-pc-${activeId}`) {\n panel.style.setProperty('display', 'block', 'important');\n } else {\n panel.style.setProperty('display', 'none', 'important');\n }\n });\n };\n \n if (triggers.length > 0) {\n const firstId = triggers[0].getAttribute('data-pc-id');\n setActiveTab(firstId);\n }\n \n triggers.forEach(btn => {\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const pcId = btn.getAttribute('data-pc-id');\n setActiveTab(pcId);\n });\n });\n }, \n submit: (result) => {}\n});",
|
|
"img": "icons/environment/people/cleric-grey.webp",
|
|
"author": "eibNkxM8PO50SgGM",
|
|
"scope": "global",
|
|
"folder": null,
|
|
"flags": {},
|
|
"_stats": {
|
|
"compendiumSource": null,
|
|
"duplicateSource": null,
|
|
"exportSource": {
|
|
"worldId": "donjon-et-cie",
|
|
"uuid": "Macro.JHKPpJNz2LP5YDUd",
|
|
"coreVersion": "13.351",
|
|
"systemId": "fvtt-donjon-et-cie",
|
|
"systemVersion": "14.0.14"
|
|
},
|
|
"coreVersion": "13.351",
|
|
"systemId": "fvtt-donjon-et-cie",
|
|
"systemVersion": "14.0.14",
|
|
"createdTime": 1780430930887,
|
|
"modifiedTime": 1780468322761,
|
|
"lastModifiedBy": "eibNkxM8PO50SgGM"
|
|
},
|
|
"ownership": {
|
|
"default": 0
|
|
}
|
|
} |