feat: fiche de Communauté (socle)
- acteur community (identité, géographie, histoire, objectifs, taille/effectif) - 4 Domaines x 2 jauges avec états (Crise/Bas/Stable/Opulent), moral, réserves - onglets Identité / Domaines / Ressources, édition ProseMirror (formInput) - header avec fond, totem, niveau, effectif ; icône par défaut - libellé du type via typeLabels (sans écraser TYPES.* du core)
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
+102
@@ -174,6 +174,15 @@
|
|||||||
"range": "Range",
|
"range": "Range",
|
||||||
"ranges": "Ranges",
|
"ranges": "Ranges",
|
||||||
"mobility": "Mobility",
|
"mobility": "Mobility",
|
||||||
|
"vehicle_specs": "Vehicle specifications",
|
||||||
|
"kind": "Kind",
|
||||||
|
"kind_vehicle": "Vehicle",
|
||||||
|
"kind_mount": "Mount",
|
||||||
|
"distance": "Distance",
|
||||||
|
"speed": "Speed",
|
||||||
|
"speed_duration_ph": "top speed duration (e.g. 10 min)",
|
||||||
|
"effort_reserve": "Effort reserve",
|
||||||
|
"maintenance": "Maintenance",
|
||||||
"rarity": "Rarity",
|
"rarity": "Rarity",
|
||||||
"rarity_sm": "Rar.",
|
"rarity_sm": "Rar.",
|
||||||
"reliability": "Reliability",
|
"reliability": "Reliability",
|
||||||
@@ -204,6 +213,7 @@
|
|||||||
"type_character": "Character",
|
"type_character": "Character",
|
||||||
"type_npc": "NPC",
|
"type_npc": "NPC",
|
||||||
"type_creature": "Creature",
|
"type_creature": "Creature",
|
||||||
|
"type_community": "Community",
|
||||||
"type": "Type",
|
"type": "Type",
|
||||||
"group_members": "Members",
|
"group_members": "Members",
|
||||||
"encounters": "Encounters",
|
"encounters": "Encounters",
|
||||||
@@ -379,6 +389,13 @@
|
|||||||
"totem": "Totem",
|
"totem": "Totem",
|
||||||
"experience": "Experience"
|
"experience": "Experience"
|
||||||
},
|
},
|
||||||
|
"Sheet": {
|
||||||
|
"character": "Character",
|
||||||
|
"npc": "NPC",
|
||||||
|
"group": "Group",
|
||||||
|
"creature": "Creature",
|
||||||
|
"community": "Community"
|
||||||
|
},
|
||||||
"base_values": "Base Values",
|
"base_values": "Base Values",
|
||||||
"computed_values": "Computed Values",
|
"computed_values": "Computed Values",
|
||||||
"cost": "Cost",
|
"cost": "Cost",
|
||||||
@@ -441,6 +458,91 @@
|
|||||||
"effects.passive": "Passive",
|
"effects.passive": "Passive",
|
||||||
"effects.temporary": "Temporary"
|
"effects.temporary": "Temporary"
|
||||||
},
|
},
|
||||||
|
"COMMUNITY": {
|
||||||
|
"tabs": {
|
||||||
|
"identity": "Identity",
|
||||||
|
"domains": "Domains",
|
||||||
|
"resources": "Resources"
|
||||||
|
},
|
||||||
|
"identity": "Identity",
|
||||||
|
"name_placeholder": "Community name",
|
||||||
|
"choose_totem": "Choose totem",
|
||||||
|
"origin": "Origin",
|
||||||
|
"theme": "Theme",
|
||||||
|
"age_label": "Community age",
|
||||||
|
"age": {
|
||||||
|
"recent": "A few days",
|
||||||
|
"established": "A few months",
|
||||||
|
"old": "A few years"
|
||||||
|
},
|
||||||
|
"instincts": "Instincts",
|
||||||
|
"prohibits": "Prohibitions",
|
||||||
|
"notes": "Notes",
|
||||||
|
"location": "Location",
|
||||||
|
"sector": "Sector",
|
||||||
|
"placeType": "Place type",
|
||||||
|
"landmarks": "Landmarks",
|
||||||
|
"territory": "Territory",
|
||||||
|
"history": "History",
|
||||||
|
"founding": "Founding",
|
||||||
|
"events": "Key events",
|
||||||
|
"history_relations": "Relations",
|
||||||
|
"objectives": "Objectives",
|
||||||
|
"objective_major": "Major objective",
|
||||||
|
"objectives_minor": "Minor objectives",
|
||||||
|
"add_objective": "Add objective",
|
||||||
|
"size_title": "Size & Population",
|
||||||
|
"size_label": "Size",
|
||||||
|
"sizeLevels": {
|
||||||
|
"1": "Size 1",
|
||||||
|
"2": "Size 2",
|
||||||
|
"3": "Size 3"
|
||||||
|
},
|
||||||
|
"population": "Population",
|
||||||
|
"population_range": "Recommended population",
|
||||||
|
"figures": "Figures",
|
||||||
|
"companies": "Companies",
|
||||||
|
"domains": {
|
||||||
|
"resources": "Resources",
|
||||||
|
"security": "Security",
|
||||||
|
"dynamism": "Dynamism",
|
||||||
|
"relations": "Relations"
|
||||||
|
},
|
||||||
|
"sections": {
|
||||||
|
"vivre": "Food & Water",
|
||||||
|
"supplies": "Supplies",
|
||||||
|
"defense": "Defense",
|
||||||
|
"care": "Care",
|
||||||
|
"cohesion": "Cohesion",
|
||||||
|
"productivity": "Productivity",
|
||||||
|
"human": "Human",
|
||||||
|
"ecology": "Ecology"
|
||||||
|
},
|
||||||
|
"states": {
|
||||||
|
"crisis": "Crisis",
|
||||||
|
"low": "Low",
|
||||||
|
"stable": "Stable",
|
||||||
|
"opulent": "Opulent"
|
||||||
|
},
|
||||||
|
"reserves": "Reserves",
|
||||||
|
"group_reserve": "Group reserve",
|
||||||
|
"material_dice": "Material dice",
|
||||||
|
"experience_dice": "Experience dice",
|
||||||
|
"morale": "Morale",
|
||||||
|
"morale_value": "Value",
|
||||||
|
"morale_state": "State",
|
||||||
|
"morale_levels": {
|
||||||
|
"high": "High",
|
||||||
|
"normal": "Normal",
|
||||||
|
"low": "Low",
|
||||||
|
"crisis": "Crisis"
|
||||||
|
},
|
||||||
|
"morale_blocked": "All four Domains are Low: the Morale bonus is inactive.",
|
||||||
|
"habitants_title": "Inhabitants",
|
||||||
|
"habitants_coming": "Figures and Companies management comes in a future version.",
|
||||||
|
"linked_group": "Linked group",
|
||||||
|
"profile_hint": "Community profile"
|
||||||
|
},
|
||||||
"ITEMS": {
|
"ITEMS": {
|
||||||
"item": "Item",
|
"item": "Item",
|
||||||
"items": "Items",
|
"items": "Items",
|
||||||
|
|||||||
+97
-1
@@ -255,6 +255,15 @@
|
|||||||
"range": "Portée",
|
"range": "Portée",
|
||||||
"ranges": "Portées",
|
"ranges": "Portées",
|
||||||
"mobility": "Mobilité",
|
"mobility": "Mobilité",
|
||||||
|
"vehicle_specs": "Caractéristiques du véhicule",
|
||||||
|
"kind": "Type",
|
||||||
|
"kind_vehicle": "Véhicule",
|
||||||
|
"kind_mount": "Monture",
|
||||||
|
"distance": "Distance",
|
||||||
|
"speed": "Vitesse",
|
||||||
|
"speed_duration_ph": "durée de pointe (ex: 10 min)",
|
||||||
|
"effort_reserve": "Réserve d'Effort",
|
||||||
|
"maintenance": "Entretien",
|
||||||
"rarity": "Rareté",
|
"rarity": "Rareté",
|
||||||
"rarity_sm": "Rar.",
|
"rarity_sm": "Rar.",
|
||||||
"reliability": "Fiabilité",
|
"reliability": "Fiabilité",
|
||||||
@@ -395,6 +404,7 @@
|
|||||||
"type_character": "Personnage",
|
"type_character": "Personnage",
|
||||||
"type_npc": "PNJ",
|
"type_npc": "PNJ",
|
||||||
"type_creature": "Créature",
|
"type_creature": "Créature",
|
||||||
|
"type_community": "Communauté",
|
||||||
"type": "Type",
|
"type": "Type",
|
||||||
"group_members": "Membres",
|
"group_members": "Membres",
|
||||||
"encounters": "Rencontres",
|
"encounters": "Rencontres",
|
||||||
@@ -440,7 +450,8 @@
|
|||||||
"character": "Personnage",
|
"character": "Personnage",
|
||||||
"npc": "PNJ",
|
"npc": "PNJ",
|
||||||
"group": "Groupe",
|
"group": "Groupe",
|
||||||
"creature": "Créature"
|
"creature": "Créature",
|
||||||
|
"community": "Communauté"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"UI": {
|
"UI": {
|
||||||
@@ -458,6 +469,91 @@
|
|||||||
"inactive": "Effets inactifs"
|
"inactive": "Effets inactifs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"COMMUNITY": {
|
||||||
|
"tabs": {
|
||||||
|
"identity": "Identité",
|
||||||
|
"domains": "Domaines",
|
||||||
|
"resources": "Ressources"
|
||||||
|
},
|
||||||
|
"identity": "Identité",
|
||||||
|
"name_placeholder": "Nom de la Communauté",
|
||||||
|
"choose_totem": "Choisir le totem",
|
||||||
|
"origin": "Origine",
|
||||||
|
"theme": "Thème",
|
||||||
|
"age_label": "Âge de la Communauté",
|
||||||
|
"age": {
|
||||||
|
"recent": "Quelques jours",
|
||||||
|
"established": "Quelques mois",
|
||||||
|
"old": "Quelques années"
|
||||||
|
},
|
||||||
|
"instincts": "Instincts",
|
||||||
|
"prohibits": "Interdits",
|
||||||
|
"notes": "Notes",
|
||||||
|
"location": "Localisation",
|
||||||
|
"sector": "Secteur",
|
||||||
|
"placeType": "Type de lieu",
|
||||||
|
"landmarks": "Éléments marquants",
|
||||||
|
"territory": "Territoire",
|
||||||
|
"history": "Histoire",
|
||||||
|
"founding": "Fondation",
|
||||||
|
"events": "Événements marquants",
|
||||||
|
"history_relations": "Relations",
|
||||||
|
"objectives": "Objectifs",
|
||||||
|
"objective_major": "Objectif majeur",
|
||||||
|
"objectives_minor": "Objectifs mineurs",
|
||||||
|
"add_objective": "Ajouter un objectif",
|
||||||
|
"size_title": "Taille & Effectif",
|
||||||
|
"size_label": "Taille",
|
||||||
|
"sizeLevels": {
|
||||||
|
"1": "Taille 1",
|
||||||
|
"2": "Taille 2",
|
||||||
|
"3": "Taille 3"
|
||||||
|
},
|
||||||
|
"population": "Effectif",
|
||||||
|
"population_range": "Population recommandée",
|
||||||
|
"figures": "Figures",
|
||||||
|
"companies": "Compagnies",
|
||||||
|
"domains": {
|
||||||
|
"resources": "Ressources",
|
||||||
|
"security": "Sécurité",
|
||||||
|
"dynamism": "Dynamisme",
|
||||||
|
"relations": "Rapports"
|
||||||
|
},
|
||||||
|
"sections": {
|
||||||
|
"vivre": "Vivres",
|
||||||
|
"supplies": "Fournitures",
|
||||||
|
"defense": "Défense",
|
||||||
|
"care": "Soins",
|
||||||
|
"cohesion": "Cohésion",
|
||||||
|
"productivity": "Productivité",
|
||||||
|
"human": "Humain",
|
||||||
|
"ecology": "Écologie"
|
||||||
|
},
|
||||||
|
"states": {
|
||||||
|
"crisis": "Crise",
|
||||||
|
"low": "Bas",
|
||||||
|
"stable": "Stable",
|
||||||
|
"opulent": "Opulent"
|
||||||
|
},
|
||||||
|
"reserves": "Réserves",
|
||||||
|
"group_reserve": "Réserve de Groupe",
|
||||||
|
"material_dice": "Dés de Matériel",
|
||||||
|
"experience_dice": "Dés d'Expérience",
|
||||||
|
"morale": "Moral",
|
||||||
|
"morale_value": "Valeur",
|
||||||
|
"morale_state": "État",
|
||||||
|
"morale_levels": {
|
||||||
|
"high": "Haut",
|
||||||
|
"normal": "Normal",
|
||||||
|
"low": "Bas",
|
||||||
|
"crisis": "Crise"
|
||||||
|
},
|
||||||
|
"morale_blocked": "Les quatre Domaines sont Bas : le Bonus de Moral est inactif.",
|
||||||
|
"habitants_title": "Habitants",
|
||||||
|
"habitants_coming": "La gestion des Figures et des Compagnies arrive dans une prochaine version.",
|
||||||
|
"linked_group": "Groupe rattaché",
|
||||||
|
"profile_hint": "Profil de la Communauté"
|
||||||
|
},
|
||||||
"ITEMS": {
|
"ITEMS": {
|
||||||
"item": "Objet",
|
"item": "Objet",
|
||||||
"items": "Objets",
|
"items": "Objets",
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
@import "../variables";
|
||||||
|
@import "../utilities";
|
||||||
|
|
||||||
|
.system-vermine2047 .vermine2047.actor.community {
|
||||||
|
.char-header {
|
||||||
|
.background-image(url("@{ui-path}/barre_haut.webp"), no-repeat, 100% 100%, right top);
|
||||||
|
max-height: 130px;
|
||||||
|
|
||||||
|
.community-portrait {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.char-name,
|
||||||
|
.char-vermine2047 {
|
||||||
|
border-bottom: none;
|
||||||
|
line-height: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.char-vermine2047 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile,
|
||||||
|
.origin,
|
||||||
|
.level,
|
||||||
|
.population {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level input,
|
||||||
|
.population input {
|
||||||
|
width: 60px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.community-section {
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid @color-border-dark-4;
|
||||||
|
background: fade(@color-chitin-dark, 20%);
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-family: "DistressBlack", sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: @font-size-13;
|
||||||
|
color: @theme-color-dark;
|
||||||
|
margin: 0 0 8px;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.community-linked-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 6px 8px;
|
||||||
|
border: 1px dashed @color-hemolymph;
|
||||||
|
background: fade(@color-hemolymph, 8%);
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-family: "DistressBlack", sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: @font-size-11;
|
||||||
|
color: @color-amber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.community-size-info {
|
||||||
|
margin: 6px 0 0;
|
||||||
|
font-size: @font-size-11;
|
||||||
|
color: @color-text-light-0;
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
|
||||||
|
.community-warning {
|
||||||
|
margin: 6px 0 0;
|
||||||
|
padding: 4px 8px;
|
||||||
|
font-size: @font-size-11;
|
||||||
|
font-weight: 700;
|
||||||
|
color: @color-hemolymph;
|
||||||
|
background: fade(@color-hemolymph, 12%);
|
||||||
|
border: 1px solid @color-hemolymph;
|
||||||
|
}
|
||||||
|
|
||||||
|
.community-hint {
|
||||||
|
margin: 0;
|
||||||
|
font-size: @font-size-11;
|
||||||
|
font-style: italic;
|
||||||
|
color: @color-text-light-0;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jauges de Domaines
|
||||||
|
.gauge {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
padding: 6px;
|
||||||
|
border: 1px solid @color-border-dark-4;
|
||||||
|
border-left: 4px solid @color-border-dark-4;
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-family: "DistressBlack", sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: @font-size-11;
|
||||||
|
color: @color-amber;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
width: 48px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gauge-value {
|
||||||
|
font-family: "DistressBlack", sans-serif;
|
||||||
|
font-size: @font-size-16;
|
||||||
|
color: @color-text-light-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gauge-state {
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
font-size: @font-size-11;
|
||||||
|
font-weight: 700;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.crisis { border-left-color: @color-hemolymph; .gauge-state { color: @color-hemolymph; } }
|
||||||
|
&.low { border-left-color: @color-amber; .gauge-state { color: @color-amber; } }
|
||||||
|
&.stable { border-left-color: @color-acid-green; .gauge-state { color: @color-acid-green; } }
|
||||||
|
&.opulent { border-left-color: @theme-color-accent; .gauge-state { color: @theme-color-accent; } }
|
||||||
|
}
|
||||||
|
|
||||||
|
.morale-level {
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
font-size: @font-size-12;
|
||||||
|
font-weight: 700;
|
||||||
|
|
||||||
|
&.high { color: @color-acid-green; }
|
||||||
|
&.normal { color: @color-text-light-0; }
|
||||||
|
&.low { color: @color-amber; }
|
||||||
|
&.crisis { color: @color-hemolymph; }
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-4
@@ -126,7 +126,8 @@ ul.unstyled {
|
|||||||
// La fiche de groupe contient beaucoup de zones (membres, objectifs, totem…) :
|
// La fiche de groupe contient beaucoup de zones (membres, objectifs, totem…) :
|
||||||
// dès que le contenu dépasse la hauteur de la fenêtre, on autorise le défilement
|
// dès que le contenu dépasse la hauteur de la fenêtre, on autorise le défilement
|
||||||
// pour ne pas perdre l'accès aux zones du bas.
|
// pour ne pas perdre l'accès aux zones du bas.
|
||||||
.application.sheet.vermine2047.group .window-content {
|
.application.sheet.vermine2047.group .window-content,
|
||||||
|
.application.sheet.vermine2047.community .window-content {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1027,11 +1028,12 @@ ol.chat-log {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Padding supplémentaire pour les fiches groupe, npc et créature
|
// Padding supplémentaire pour les fiches groupe, npc, créature et communauté
|
||||||
.system-vermine2047 {
|
.system-vermine2047 {
|
||||||
.group-content,
|
.group-content,
|
||||||
.npc-content,
|
.npc-content,
|
||||||
.creature-content {
|
.creature-content,
|
||||||
|
.community-content {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1119,7 +1121,7 @@ ol.chat-log {
|
|||||||
label {
|
label {
|
||||||
font-family: "DistressBlack", sans-serif;
|
font-family: "DistressBlack", sans-serif;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: @font-size-10;
|
font-size: @font-size-11;
|
||||||
color: @color-amber;
|
color: @color-amber;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
@import "actor/npc";
|
@import "actor/npc";
|
||||||
@import "actor/group";
|
@import "actor/group";
|
||||||
@import "actor/creature";
|
@import "actor/creature";
|
||||||
|
@import "actor/community";
|
||||||
|
|
||||||
// 6. Styles des items
|
// 6. Styles des items
|
||||||
@import "items";
|
@import "items";
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export { default as VermineCharacterSheetV2 } from "./character-sheet.mjs"
|
|||||||
export { default as VermineNpcSheetV2 } from "./npc-sheet.mjs"
|
export { default as VermineNpcSheetV2 } from "./npc-sheet.mjs"
|
||||||
export { default as VermineGroupSheetV2 } from "./group-sheet.mjs"
|
export { default as VermineGroupSheetV2 } from "./group-sheet.mjs"
|
||||||
export { default as VermineCreatureSheetV2 } from "./creature-sheet.mjs"
|
export { default as VermineCreatureSheetV2 } from "./creature-sheet.mjs"
|
||||||
|
export { default as VermineCommunitySheetV2 } from "./community-sheet.mjs"
|
||||||
export {
|
export {
|
||||||
VermineItemSheetV2,
|
VermineItemSheetV2,
|
||||||
VermineWeaponSheetV2,
|
VermineWeaponSheetV2,
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
import VermineBaseActorSheet from "./base-actor-sheet.mjs"
|
||||||
|
|
||||||
|
export default class VermineCommunitySheetV2 extends VermineBaseActorSheet {
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["community"],
|
||||||
|
position: { width: 760, height: 640 },
|
||||||
|
window: { contentClasses: ["community-content"] },
|
||||||
|
actions: {
|
||||||
|
addObjective: VermineCommunitySheetV2.#onAddObjective,
|
||||||
|
deleteObjective: VermineCommunitySheetV2.#onDeleteObjective
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/vermine2047/templates/actor/appv2/community-main.hbs", scrollable: [""] },
|
||||||
|
tabs: { template: "templates/generic/tab-navigation.hbs" },
|
||||||
|
identity: { template: "systems/vermine2047/templates/actor/appv2/community-identity.hbs", scrollable: [""] },
|
||||||
|
domains: { template: "systems/vermine2047/templates/actor/appv2/community-domains.hbs", scrollable: [""] },
|
||||||
|
resources: { template: "systems/vermine2047/templates/actor/appv2/community-resources.hbs", scrollable: [""] }
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { sheet: "identity" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
identity: { id: "identity", group: "sheet", icon: "fas fa-info-circle", label: "COMMUNITY.tabs.identity" },
|
||||||
|
domains: { id: "domains", group: "sheet", icon: "fas fa-chart-simple", label: "COMMUNITY.tabs.domains" },
|
||||||
|
resources: { id: "resources", group: "sheet", icon: "fas fa-boxes-stacked", label: "COMMUNITY.tabs.resources" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
// Groupe de personnages rattaché
|
||||||
|
context.resolvedGroup = null
|
||||||
|
if (this.document.system.groupId) {
|
||||||
|
const g = game.actors.get(this.document.system.groupId)
|
||||||
|
if (g) context.resolvedGroup = { id: g.id, name: g.name }
|
||||||
|
}
|
||||||
|
// Enrichissement HTML des champs longs (même logique que la fiche PNJ)
|
||||||
|
const enrich = async (path) => {
|
||||||
|
const val = foundry.utils.getProperty(this.document.system, path)
|
||||||
|
return val ? await foundry.applications.ux.TextEditor.implementation.enrichHTML(val, { async: true }) : ""
|
||||||
|
}
|
||||||
|
context.enrichedNotes = await enrich("identity.notes")
|
||||||
|
context.enrichedLandmarks = await enrich("location.landmarks")
|
||||||
|
context.enrichedTerritory = await enrich("location.territory")
|
||||||
|
context.enrichedEvents = await enrich("history.events")
|
||||||
|
context.enrichedRelations = await enrich("history.relations")
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
async _preparePartContext(partId, context) {
|
||||||
|
const doc = this.document
|
||||||
|
switch (partId) {
|
||||||
|
case "main": break
|
||||||
|
case "identity":
|
||||||
|
context.tab = context.tabs.identity
|
||||||
|
context.ageOptions = Object.entries(CONFIG.VERMINE.communityAges).map(([key, label]) => ({ key, label: game.i18n.localize(label) }))
|
||||||
|
break
|
||||||
|
case "domains":
|
||||||
|
context.tab = context.tabs.domains
|
||||||
|
context.sizeOptions = CONFIG.VERMINE.communitySizeLevels
|
||||||
|
context.sizeLabel = doc.system.size?.value ? game.i18n.localize(CONFIG.VERMINE.communitySizeLevels[doc.system.size.value]?.label ?? "") : ""
|
||||||
|
context.sizeInfo = doc.system.size?.value ? CONFIG.VERMINE.communitySizeLevels[doc.system.size.value] : null
|
||||||
|
// Préparer les 4 Domaines avec leurs 2 sections (jauges) et leur état
|
||||||
|
context.domains = []
|
||||||
|
for (const [dkey, dcfg] of Object.entries(CONFIG.VERMINE.communityDomains)) {
|
||||||
|
const domain = doc.system.domains?.[dkey]
|
||||||
|
context.domains.push({
|
||||||
|
key: dkey,
|
||||||
|
label: game.i18n.localize(dcfg.label),
|
||||||
|
sections: Object.entries(dcfg.sections).map(([skey, label]) => {
|
||||||
|
const gauge = domain?.[skey] ?? { value: 0 }
|
||||||
|
const state = gauge.state || "crisis"
|
||||||
|
return {
|
||||||
|
domainKey: dkey,
|
||||||
|
key: skey,
|
||||||
|
label: game.i18n.localize(label),
|
||||||
|
gauge,
|
||||||
|
state,
|
||||||
|
stateLabel: game.i18n.localize(CONFIG.VERMINE.communityGaugeStates[state]?.label ?? "COMMUNITY.states.crisis")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "resources":
|
||||||
|
context.tab = context.tabs.resources
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
changeTab(tab, group, options = {}) {
|
||||||
|
super.changeTab(tab, group, options)
|
||||||
|
if (group === "sheet") {
|
||||||
|
const main = this.element?.querySelector('[data-group="sheet"][data-tab="main"]')
|
||||||
|
if (main) main.classList.add("active")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onDeleteObjective(event, target) {
|
||||||
|
const index = parseInt(target.dataset.index)
|
||||||
|
if (isNaN(index)) return
|
||||||
|
const objectives = foundry.utils.duplicate(this.document.system.objectives || { major: "", minor: [] })
|
||||||
|
objectives.minor.splice(index, 1)
|
||||||
|
this.document.update({ "system.objectives": objectives })
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onAddObjective(event, target) {
|
||||||
|
const objectives = foundry.utils.duplicate(this.document.system.objectives || { major: "", minor: [] })
|
||||||
|
objectives.minor.push("")
|
||||||
|
this.document.update({ "system.objectives": objectives })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ export { default as VermineCharacterData } from "./character.mjs"
|
|||||||
export { default as VermineNpcData } from "./npc.mjs"
|
export { default as VermineNpcData } from "./npc.mjs"
|
||||||
export { default as VermineGroupData } from "./group.mjs"
|
export { default as VermineGroupData } from "./group.mjs"
|
||||||
export { default as VermineCreatureData } from "./creature.mjs"
|
export { default as VermineCreatureData } from "./creature.mjs"
|
||||||
|
export { default as VermineCommunityData } from "./community.mjs"
|
||||||
export { default as VermineItemData } from "./item.mjs"
|
export { default as VermineItemData } from "./item.mjs"
|
||||||
export { default as VermineWeaponData } from "./weapon.mjs"
|
export { default as VermineWeaponData } from "./weapon.mjs"
|
||||||
export { default as VermineDefenseData } from "./defense.mjs"
|
export { default as VermineDefenseData } from "./defense.mjs"
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
/**
|
||||||
|
* DataModel pour les acteurs de type "community" (Communauté).
|
||||||
|
* La Communauté est l'extension sédentarisée d'un Groupe : elle englobe le
|
||||||
|
* Groupe de personnages, des Figures et des Habitants répartis en Compagnies.
|
||||||
|
* Le socle couvre l'identité, la géographie, l'histoire, les objectifs, la
|
||||||
|
* taille/l'effectif, les quatre Domaines (8 jauges), le Moral et les réserves.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
attributeSchema,
|
||||||
|
levelSchema,
|
||||||
|
combatStatusSchema
|
||||||
|
} from "./_shared.mjs"
|
||||||
|
|
||||||
|
export default class VermineCommunityData extends foundry.abstract.TypeDataModel {
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static LOCALIZATION_PREFIXES = ["VERMINE.community"]
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields
|
||||||
|
const reqInt = { required: true, nullable: false, integer: true }
|
||||||
|
const gauge = () => attributeSchema(0, 0, 10)
|
||||||
|
|
||||||
|
return {
|
||||||
|
// Statut de combat (base, peu utilisé pour une Communauté)
|
||||||
|
combatStatus: combatStatusSchema("9"),
|
||||||
|
|
||||||
|
// Identité
|
||||||
|
identity: new fields.SchemaField({
|
||||||
|
totem: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
profile: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
origin: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
theme: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
instincts: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
prohibits: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
// Âge de la Communauté : recent | established | old
|
||||||
|
age: new fields.StringField({ required: true, nullable: false, initial: "recent" }),
|
||||||
|
notes: new fields.HTMLField({ required: true, initial: "", textSearch: true })
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Géographie / localisation
|
||||||
|
location: new fields.SchemaField({
|
||||||
|
sector: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
placeType: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
landmarks: new fields.HTMLField({ required: true, initial: "", textSearch: true }),
|
||||||
|
territory: new fields.HTMLField({ required: true, initial: "", textSearch: true })
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Histoire
|
||||||
|
history: new fields.SchemaField({
|
||||||
|
founding: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
events: new fields.HTMLField({ required: true, initial: "", textSearch: true }),
|
||||||
|
relations: new fields.HTMLField({ required: true, initial: "", textSearch: true })
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Objectifs : un majeur + des mineurs
|
||||||
|
objectives: new fields.SchemaField({
|
||||||
|
major: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
minor: new fields.ArrayField(new fields.StringField({ required: true, nullable: false, initial: "" }))
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Taille (1-3) et effectif
|
||||||
|
size: attributeSchema(1, 1, 3),
|
||||||
|
population: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
||||||
|
|
||||||
|
// Domaines : 4 Domaines × 2 sections (jauges en Dés)
|
||||||
|
domains: new fields.SchemaField({
|
||||||
|
resources: new fields.SchemaField({
|
||||||
|
vivre: gauge(),
|
||||||
|
supplies: gauge()
|
||||||
|
}),
|
||||||
|
security: new fields.SchemaField({
|
||||||
|
defense: gauge(),
|
||||||
|
care: gauge()
|
||||||
|
}),
|
||||||
|
dynamism: new fields.SchemaField({
|
||||||
|
cohesion: gauge(),
|
||||||
|
productivity: gauge()
|
||||||
|
}),
|
||||||
|
relations: new fields.SchemaField({
|
||||||
|
human: gauge(),
|
||||||
|
ecology: gauge()
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Moral (comme le Groupe) : value 0-7, level dérivé
|
||||||
|
morale: new fields.SchemaField({
|
||||||
|
level: new fields.StringField({ required: true, nullable: false, initial: "normal" }),
|
||||||
|
value: new fields.NumberField({ ...reqInt, initial: 7, min: 0, max: 7 }),
|
||||||
|
min: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
||||||
|
max: new fields.NumberField({ ...reqInt, initial: 7, min: 0 })
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Réserve de Groupe
|
||||||
|
reserve: attributeSchema(0, 0, 10),
|
||||||
|
|
||||||
|
// Dés collectifs de la Communauté
|
||||||
|
material: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
||||||
|
experience: new fields.SchemaField({
|
||||||
|
dice: new fields.NumberField({ ...reqInt, initial: 0, min: 0 })
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Niveau de la Communauté (pour l'expérience des habitants)
|
||||||
|
level: levelSchema(1, 1, 10),
|
||||||
|
|
||||||
|
// Groupe de personnages rattaché (id d'acteur)
|
||||||
|
groupId: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
|
||||||
|
// Habitants (phase 2) : Figures et Compagnies
|
||||||
|
figures: new fields.ArrayField(new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
role: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
totem: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
specialty: new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
score: new fields.NumberField({ ...reqInt, initial: 3, min: 0, max: 10 })
|
||||||
|
})
|
||||||
|
})),
|
||||||
|
companies: new fields.ArrayField(new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
specialty: new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
score: new fields.NumberField({ ...reqInt, initial: 3, min: 0, max: 10 })
|
||||||
|
}),
|
||||||
|
level: levelSchema(1, 1, 4),
|
||||||
|
members: new fields.NumberField({ ...reqInt, initial: 1, min: 0 }),
|
||||||
|
figureName: new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
prepareDerivedData() {
|
||||||
|
super.prepareDerivedData()
|
||||||
|
|
||||||
|
// 1. État (Crise/Bas/Stable/Opulent) de chaque jauge de Domaine
|
||||||
|
this._computeGaugeStates()
|
||||||
|
|
||||||
|
// 2. Les quatre Domaines sont-ils Bas ? (Moral inactif)
|
||||||
|
this._computeAllDomainsLow()
|
||||||
|
|
||||||
|
// 3. Mettre à jour le niveau de Moral selon la valeur
|
||||||
|
this._updateMorale()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* État d'une jauge selon sa valeur en Dés.
|
||||||
|
* Crise 0D / Bas 1-2D / Stable 3-5D / Opulent 6D+.
|
||||||
|
* @param {number} value
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
static gaugeState(value) {
|
||||||
|
const v = parseInt(value, 10) || 0
|
||||||
|
if (v >= 6) return "opulent"
|
||||||
|
if (v >= 3) return "stable"
|
||||||
|
if (v >= 1) return "low"
|
||||||
|
return "crisis"
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeGaugeStates() {
|
||||||
|
for (const domain of Object.values(this.domains)) {
|
||||||
|
for (const gauge of Object.values(domain)) {
|
||||||
|
gauge.state = VermineCommunityData.gaugeState(gauge.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un Domaine est "Bas" lorsque ses deux sections sont à 2D ou moins.
|
||||||
|
* Si les quatre Domaines sont Bas, le Bonus de Moral est inactif.
|
||||||
|
*/
|
||||||
|
_computeAllDomainsLow() {
|
||||||
|
const domainLow = (domain) => Object.values(domain).every(g => (parseInt(g.value, 10) || 0) <= 2)
|
||||||
|
this.allDomainsLow = Object.values(this.domains).every(domainLow)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Met à jour le niveau de Moral en fonction de la valeur de dés.
|
||||||
|
* Règles : 7D = Haut, 6-3D = Normal, 2-1D = Bas, 0D = Crise.
|
||||||
|
*/
|
||||||
|
_updateMorale() {
|
||||||
|
const moraleValue = parseInt(this.morale?.value, 10) || 0
|
||||||
|
if (this.morale.level && this.morale.level !== "normal") return
|
||||||
|
if (moraleValue >= 7) {
|
||||||
|
this.morale.level = "high"
|
||||||
|
} else if (moraleValue >= 3) {
|
||||||
|
this.morale.level = "normal"
|
||||||
|
} else if (moraleValue >= 1) {
|
||||||
|
this.morale.level = "low"
|
||||||
|
} else {
|
||||||
|
this.morale.level = "crisis"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -469,3 +469,54 @@ VERMINE.totemEffects = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Communauté — Domaines et sections (jauges).
|
||||||
|
*/
|
||||||
|
VERMINE.communityDomains = {
|
||||||
|
resources: {
|
||||||
|
label: "COMMUNITY.domains.resources",
|
||||||
|
sections: { vivre: "COMMUNITY.sections.vivre", supplies: "COMMUNITY.sections.supplies" }
|
||||||
|
},
|
||||||
|
security: {
|
||||||
|
label: "COMMUNITY.domains.security",
|
||||||
|
sections: { defense: "COMMUNITY.sections.defense", care: "COMMUNITY.sections.care" }
|
||||||
|
},
|
||||||
|
dynamism: {
|
||||||
|
label: "COMMUNITY.domains.dynamism",
|
||||||
|
sections: { cohesion: "COMMUNITY.sections.cohesion", productivity: "COMMUNITY.sections.productivity" }
|
||||||
|
},
|
||||||
|
relations: {
|
||||||
|
label: "COMMUNITY.domains.relations",
|
||||||
|
sections: { human: "COMMUNITY.sections.human", ecology: "COMMUNITY.sections.ecology" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Communauté — Tailles (effectif, Figures, Compagnies recommandés).
|
||||||
|
*/
|
||||||
|
VERMINE.communitySizeLevels = {
|
||||||
|
1: { label: "COMMUNITY.sizeLevels.1", population: "7-50", figures: 3, companies: 5 },
|
||||||
|
2: { label: "COMMUNITY.sizeLevels.2", population: "51-75", figures: 5, companies: 7 },
|
||||||
|
3: { label: "COMMUNITY.sizeLevels.3", population: "100+", figures: 7, companies: 9 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Communauté — États d'une jauge de Domaine.
|
||||||
|
* Crise 0D / Bas 1-2D / Stable 3-5D / Opulent 6D+.
|
||||||
|
*/
|
||||||
|
VERMINE.communityGaugeStates = {
|
||||||
|
crisis: { label: "COMMUNITY.states.crisis" },
|
||||||
|
low: { label: "COMMUNITY.states.low" },
|
||||||
|
stable: { label: "COMMUNITY.states.stable" },
|
||||||
|
opulent: { label: "COMMUNITY.states.opulent" }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Communauté — Âge (notion de temps).
|
||||||
|
*/
|
||||||
|
VERMINE.communityAges = {
|
||||||
|
recent: "COMMUNITY.age.recent",
|
||||||
|
established: "COMMUNITY.age.established",
|
||||||
|
old: "COMMUNITY.age.old"
|
||||||
|
}
|
||||||
|
|||||||
+16
-1
@@ -37,6 +37,14 @@ Hooks.once('init', async function () {
|
|||||||
CONFIG.Actor.dataModels.npc = models.VermineNpcData;
|
CONFIG.Actor.dataModels.npc = models.VermineNpcData;
|
||||||
CONFIG.Actor.dataModels.group = models.VermineGroupData;
|
CONFIG.Actor.dataModels.group = models.VermineGroupData;
|
||||||
CONFIG.Actor.dataModels.creature = models.VermineCreatureData;
|
CONFIG.Actor.dataModels.creature = models.VermineCreatureData;
|
||||||
|
CONFIG.Actor.dataModels.community = models.VermineCommunityData;
|
||||||
|
|
||||||
|
// Libellé du type "community" (TYPES.Actor.* du core ne le connaît pas)
|
||||||
|
CONFIG.Actor.typeLabels ??= {};
|
||||||
|
CONFIG.Actor.typeLabels.community = "VERMINE.type_community";
|
||||||
|
Hooks.once('i18nInit', () => {
|
||||||
|
CONFIG.Actor.typeLabels.community = "VERMINE.type_community";
|
||||||
|
});
|
||||||
|
|
||||||
CONFIG.Item.dataModels.item = models.VermineItemData;
|
CONFIG.Item.dataModels.item = models.VermineItemData;
|
||||||
CONFIG.Item.dataModels.weapon = models.VermineWeaponData;
|
CONFIG.Item.dataModels.weapon = models.VermineWeaponData;
|
||||||
@@ -89,6 +97,9 @@ Hooks.once('init', async function () {
|
|||||||
foundry.documents.collections.Actors.registerSheet("vermine2047", sheets.VermineGroupSheetV2, {
|
foundry.documents.collections.Actors.registerSheet("vermine2047", sheets.VermineGroupSheetV2, {
|
||||||
types: ["group"], makeDefault: true, label: "VERMINE.Sheet.group"
|
types: ["group"], makeDefault: true, label: "VERMINE.Sheet.group"
|
||||||
})
|
})
|
||||||
|
foundry.documents.collections.Actors.registerSheet("vermine2047", sheets.VermineCommunitySheetV2, {
|
||||||
|
types: ["community"], makeDefault: true, label: "VERMINE.Sheet.community"
|
||||||
|
})
|
||||||
|
|
||||||
// Item sheets — un par type
|
// Item sheets — un par type
|
||||||
foundry.documents.collections.Items.registerSheet("vermine2047", sheets.VermineItemSheetV2, {
|
foundry.documents.collections.Items.registerSheet("vermine2047", sheets.VermineItemSheetV2, {
|
||||||
@@ -193,7 +204,11 @@ Hooks.once('init', async function () {
|
|||||||
"systems/vermine2047/templates/actor/appv2/creature-info.hbs",
|
"systems/vermine2047/templates/actor/appv2/creature-info.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/creature-stats.hbs",
|
"systems/vermine2047/templates/actor/appv2/creature-stats.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/creature-combat.hbs",
|
"systems/vermine2047/templates/actor/appv2/creature-combat.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/creature-effects.hbs"
|
"systems/vermine2047/templates/actor/appv2/creature-effects.hbs",
|
||||||
|
"systems/vermine2047/templates/actor/appv2/community-main.hbs",
|
||||||
|
"systems/vermine2047/templates/actor/appv2/community-identity.hbs",
|
||||||
|
"systems/vermine2047/templates/actor/appv2/community-domains.hbs",
|
||||||
|
"systems/vermine2047/templates/actor/appv2/community-resources.hbs"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
+2
-1
@@ -34,7 +34,8 @@
|
|||||||
"character": { "htmlFields": ["equipment.description", "identity.biography", "identity.relations"] },
|
"character": { "htmlFields": ["equipment.description", "identity.biography", "identity.relations"] },
|
||||||
"npc": { "htmlFields": ["equipment.description", "identity.notes"] },
|
"npc": { "htmlFields": ["equipment.description", "identity.notes"] },
|
||||||
"group": { "htmlFields": ["equipment.description", "identity.notes"] },
|
"group": { "htmlFields": ["equipment.description", "identity.notes"] },
|
||||||
"creature": { "htmlFields": ["equipment.description", "identity.notes", "identity.biography"] }
|
"creature": { "htmlFields": ["equipment.description", "identity.notes", "identity.biography"] },
|
||||||
|
"community": { "htmlFields": ["identity.notes", "location.landmarks", "location.territory", "history.events", "history.relations"] }
|
||||||
},
|
},
|
||||||
"Item": {
|
"Item": {
|
||||||
"item": { "htmlFields": ["description"] },
|
"item": { "htmlFields": ["description"] },
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<div class="tab domains sheet-part {{#if @root.tabs.domains.active}}active{{/if}}" data-group="sheet" data-tab="domains">
|
||||||
|
<section class="community-section">
|
||||||
|
<h3>{{ localize 'COMMUNITY.size_title' }}</h3>
|
||||||
|
<div class="flexrow community-size">
|
||||||
|
<div class="form-group" style="flex: 1;">
|
||||||
|
<label for="system.size.value">{{ localize 'COMMUNITY.size_label' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<select name="system.size.value" data-dtype="Number">
|
||||||
|
{{#each sizeOptions as |cfg level|}}
|
||||||
|
<option value="{{ level }}" {{#ife @root.system.size.value level}}selected{{/ife}}>{{ localize cfg.label }}</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
{{else}}
|
||||||
|
<span>{{ sizeLabel }}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style="flex: 1;">
|
||||||
|
<label for="system.population">{{ localize 'COMMUNITY.population' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="number" name="system.population" value="{{system.population}}" data-dtype="Number" min="0" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.population}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{#if sizeInfo}}
|
||||||
|
<p class="community-size-info">
|
||||||
|
{{ localize 'COMMUNITY.population_range' }}: <strong>{{ sizeInfo.population }}</strong> ·
|
||||||
|
{{ localize 'COMMUNITY.figures' }}: <strong>{{ sizeInfo.figures }}+</strong> ·
|
||||||
|
{{ localize 'COMMUNITY.companies' }}: <strong>{{ sizeInfo.companies }}+</strong>
|
||||||
|
</p>
|
||||||
|
{{/if}}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{{#each domains}}
|
||||||
|
<section class="community-section">
|
||||||
|
<h3>{{ this.label }}</h3>
|
||||||
|
<div class="grid grid-2col">
|
||||||
|
{{#each this.sections}}
|
||||||
|
<div class="gauge {{ this.state }}">
|
||||||
|
<label for="system.domains.{{ this.domainKey }}.{{ this.key }}.value">{{ this.label }}</label>
|
||||||
|
{{#if @root.isEditMode}}
|
||||||
|
<input type="number" name="system.domains.{{ this.domainKey }}.{{ this.key }}.value"
|
||||||
|
value="{{ this.gauge.value }}" data-dtype="Number" min="0" />
|
||||||
|
{{else}}
|
||||||
|
<span class="gauge-value">{{ this.gauge.value }}D</span>
|
||||||
|
{{/if}}
|
||||||
|
<span class="gauge-state {{ this.state }}">{{ this.stateLabel }}</span>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
<div class="tab identity sheet-part {{#if @root.tabs.identity.active}}active{{/if}}" data-group="sheet" data-tab="identity">
|
||||||
|
<section class="community-section">
|
||||||
|
<h3>{{ localize 'COMMUNITY.identity' }}</h3>
|
||||||
|
<div class="grid grid-2col">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.identity.origin">{{ localize 'COMMUNITY.origin' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="text" name="system.identity.origin" value="{{system.identity.origin}}" data-dtype="String" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.identity.origin}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.identity.theme">{{ localize 'COMMUNITY.theme' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="text" name="system.identity.theme" value="{{system.identity.theme}}" data-dtype="String" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.identity.theme}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.identity.age">{{ localize 'COMMUNITY.age_label' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<select name="system.identity.age" data-dtype="String">
|
||||||
|
{{#each ageOptions}}
|
||||||
|
<option value="{{ this.key }}" {{#ife @root.system.identity.age this.key}}selected{{/ife}}>{{ this.label }}</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
{{else}}
|
||||||
|
<span>{{#each ageOptions}}{{#ife @root.system.identity.age this.key}}{{ this.label }}{{/ife}}{{/each}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>{{ localize 'COMMUNITY.instincts' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="text" name="system.identity.instincts" value="{{system.identity.instincts}}" data-dtype="String" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.identity.instincts}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>{{ localize 'COMMUNITY.prohibits' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="text" name="system.identity.prohibits" value="{{system.identity.prohibits}}" data-dtype="String" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.identity.prohibits}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.identity.notes">{{ localize 'COMMUNITY.notes' }}</label>
|
||||||
|
{{formInput systemFields.identity.fields.notes enriched=enrichedNotes value=system.identity.notes name="system.identity.notes" toggled=true}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="community-section">
|
||||||
|
<h3>{{ localize 'COMMUNITY.location' }}</h3>
|
||||||
|
<div class="grid grid-2col">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.location.sector">{{ localize 'COMMUNITY.sector' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="text" name="system.location.sector" value="{{system.location.sector}}" data-dtype="String" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.location.sector}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.location.placeType">{{ localize 'COMMUNITY.placeType' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="text" name="system.location.placeType" value="{{system.location.placeType}}" data-dtype="String" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.location.placeType}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.location.landmarks">{{ localize 'COMMUNITY.landmarks' }}</label>
|
||||||
|
{{formInput systemFields.location.fields.landmarks enriched=enrichedLandmarks value=system.location.landmarks name="system.location.landmarks" toggled=true}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.location.territory">{{ localize 'COMMUNITY.territory' }}</label>
|
||||||
|
{{formInput systemFields.location.fields.territory enriched=enrichedTerritory value=system.location.territory name="system.location.territory" toggled=true}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="community-section">
|
||||||
|
<h3>{{ localize 'COMMUNITY.history' }}</h3>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.history.founding">{{ localize 'COMMUNITY.founding' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="text" name="system.history.founding" value="{{system.history.founding}}" data-dtype="String" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.history.founding}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.history.events">{{ localize 'COMMUNITY.events' }}</label>
|
||||||
|
{{formInput systemFields.history.fields.events enriched=enrichedEvents value=system.history.events name="system.history.events" toggled=true}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.history.relations">{{ localize 'COMMUNITY.history_relations' }}</label>
|
||||||
|
{{formInput systemFields.history.fields.relations enriched=enrichedRelations value=system.history.relations name="system.history.relations" toggled=true}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="community-section">
|
||||||
|
<h3>{{ localize 'COMMUNITY.objectives' }}</h3>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.objectives.major">{{ localize 'COMMUNITY.objective_major' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="text" name="system.objectives.major" value="{{system.objectives.major}}" data-dtype="String" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.objectives.major}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>{{ localize 'COMMUNITY.objectives_minor' }}</label>
|
||||||
|
<ol class="items-list">
|
||||||
|
{{#each system.objectives.minor as |obj index|}}
|
||||||
|
<li class="item flexrow" data-index="{{index}}">
|
||||||
|
{{#if @root.isEditMode}}
|
||||||
|
<input type="text" name="system.objectives.minor.{{index}}" value="{{obj}}" data-dtype="String" style="flex: 1;" />
|
||||||
|
<a data-action="deleteObjective" data-index="{{index}}" title="{{ localize 'VERMINE.delete' }}"><i class="fas fa-trash"></i></a>
|
||||||
|
{{else}}
|
||||||
|
<span style="flex: 1;">{{obj}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<li class="item flexrow">
|
||||||
|
<a data-action="addObjective" title="{{ localize 'VERMINE.add' }}"><i class="fas fa-plus"></i> {{ localize 'COMMUNITY.add_objective' }}</a>
|
||||||
|
</li>
|
||||||
|
{{/if}}
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
<div class="tab main sheet-part" data-group="sheet" data-tab="main">
|
||||||
|
{{!-- Toggle Edit/Play --}}
|
||||||
|
<div class="sheet-header-toggle">
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<button type="button" data-action="toggleSheet">{{localize "VERMINE.playMode"}}</button>
|
||||||
|
{{else}}
|
||||||
|
<button type="button" data-action="toggleSheet">{{localize "VERMINE.editMode"}}</button>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- HEADER --}}
|
||||||
|
<header class="char-header grid grid-12col w-full">
|
||||||
|
<div class="grid-span-2 community-portrait">
|
||||||
|
<img class="profile-img" src="{{actor.img}}" data-action="editImage" data-edit="img" width="110"
|
||||||
|
height="110" title="{{actor.name}}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section class="char-details grid-span-6">
|
||||||
|
<h1 class="char-name flexrow flex-group-left w-full">
|
||||||
|
<label>{{ localize 'IDENTITY.name' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input name="name" type="text" value="{{actor.name}}" placeholder="{{ localize 'COMMUNITY.name_placeholder' }}" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{actor.name}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</h1>
|
||||||
|
<div class="profile flexrow flex-group-center">
|
||||||
|
<label>{{ localize 'IDENTITY.profile' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input name="system.identity.profile" type="text" value="{{system.identity.profile}}" data-dtype="String" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{#if system.identity.profile}}{{system.identity.profile}}{{else}}{{ localize 'COMMUNITY.profile_hint' }}{{/if}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="origin flexrow flex-group-center">
|
||||||
|
<label>{{ localize 'COMMUNITY.origin' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input name="system.identity.origin" type="text" value="{{system.identity.origin}}" data-dtype="String" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.identity.origin}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="char-level grid-span-4">
|
||||||
|
<h1 class="char-vermine2047 flexrow flex-group-left w-full">
|
||||||
|
{{#if (eq system.identity.totem "")}}
|
||||||
|
<a data-action="chooseTotem" class="chooseTotem">{{ localize 'COMMUNITY.choose_totem' }}…</a>
|
||||||
|
{{ else }}
|
||||||
|
<a data-action="chooseTotem" class="chooseTotem">{{ smarttl "TOTEMS" system.identity.totem }}</a>
|
||||||
|
{{/if}}
|
||||||
|
</h1>
|
||||||
|
<div class="level flexrow flex-group-center">
|
||||||
|
<label>{{ localize 'VERMINE.level' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input name="system.level.value" type="number" value="{{system.level.value}}" data-dtype="Number" min="{{system.level.min}}" max="{{system.level.max}}" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.level.value}}</span>
|
||||||
|
{{/if}}
|
||||||
|
<span>/ {{system.level.max}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="population flexrow flex-group-center">
|
||||||
|
<label>{{ localize 'COMMUNITY.population' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input name="system.population" type="number" value="{{system.population}}" data-dtype="Number" min="0" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.population}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{{#if resolvedGroup}}
|
||||||
|
<div class="community-linked-group">
|
||||||
|
<span class="label">{{ localize 'COMMUNITY.linked_group' }}:</span>
|
||||||
|
<span class="value">{{ resolvedGroup.name }}</span>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<div class="tab resources sheet-part {{#if @root.tabs.resources.active}}active{{/if}}" data-group="sheet" data-tab="resources">
|
||||||
|
<section class="community-section">
|
||||||
|
<h3>{{ localize 'COMMUNITY.reserves' }}</h3>
|
||||||
|
<div class="grid grid-3col">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.reserve.value">{{ localize 'COMMUNITY.group_reserve' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="number" name="system.reserve.value" value="{{system.reserve.value}}" data-dtype="Number" min="0" max="{{system.reserve.max}}" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.reserve.value}} / {{system.reserve.max}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.material">{{ localize 'COMMUNITY.material_dice' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="number" name="system.material" value="{{system.material}}" data-dtype="Number" min="0" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.material}}D</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.experience.dice">{{ localize 'COMMUNITY.experience_dice' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="number" name="system.experience.dice" value="{{system.experience.dice}}" data-dtype="Number" min="0" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.experience.dice}}D</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="community-section">
|
||||||
|
<h3>{{ localize 'COMMUNITY.morale' }}</h3>
|
||||||
|
<div class="flexrow">
|
||||||
|
<div class="form-group" style="flex: 1;">
|
||||||
|
<label for="system.morale.value">{{ localize 'COMMUNITY.morale_value' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="number" name="system.morale.value" value="{{system.morale.value}}" data-dtype="Number" min="0" max="7" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.morale.value}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style="flex: 1;">
|
||||||
|
<label>{{ localize 'COMMUNITY.morale_state' }}</label>
|
||||||
|
<span class="morale-level {{ system.morale.level }}">{{ localize (concat 'COMMUNITY.morale_levels.' system.morale.level) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{#if system.allDomainsLow}}
|
||||||
|
<p class="community-warning">{{ localize 'COMMUNITY.morale_blocked' }}</p>
|
||||||
|
{{/if}}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="community-section">
|
||||||
|
<h3>{{ localize 'COMMUNITY.habitants_title' }}</h3>
|
||||||
|
<p class="community-hint">{{ localize 'COMMUNITY.habitants_coming' }}</p>
|
||||||
|
{{#if resolvedGroup}}
|
||||||
|
<p class="community-linked-group">
|
||||||
|
<span class="label">{{ localize 'COMMUNITY.linked_group' }}:</span>
|
||||||
|
<span class="value">{{ resolvedGroup.name }}</span>
|
||||||
|
</p>
|
||||||
|
{{/if}}
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user