feat: fiche PNJ (profil + niveaux) et passage du véhicule en acteur
Release Creation / build (release) Failing after 1m17s
Release Creation / build (release) Failing after 1m17s
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
+9
-2
@@ -16,7 +16,7 @@
|
|||||||
"TYPES.Item.item": "Item",
|
"TYPES.Item.item": "Item",
|
||||||
"TYPES.Item.weapon": "Weapon",
|
"TYPES.Item.weapon": "Weapon",
|
||||||
"TYPES.Item.defense": "Defense",
|
"TYPES.Item.defense": "Defense",
|
||||||
"TYPES.Item.vehicle": "Vehicle",
|
"TYPES.Actor.vehicle": "Vehicle",
|
||||||
"TYPES.Item.ability": "Ability",
|
"TYPES.Item.ability": "Ability",
|
||||||
"TYPES.Item.specialty": "Specialty",
|
"TYPES.Item.specialty": "Specialty",
|
||||||
"TYPES.Item.background": "Background",
|
"TYPES.Item.background": "Background",
|
||||||
@@ -145,6 +145,8 @@
|
|||||||
},
|
},
|
||||||
"pool": "Reserve",
|
"pool": "Reserve",
|
||||||
"pools": "Reserves",
|
"pools": "Reserves",
|
||||||
|
"dice_pool": "Dice pool",
|
||||||
|
"auto_successes": "automatic successes",
|
||||||
"self_control": "Self-control",
|
"self_control": "Self-control",
|
||||||
"effort": "Effort",
|
"effort": "Effort",
|
||||||
"equip": "Equip",
|
"equip": "Equip",
|
||||||
@@ -174,6 +176,7 @@
|
|||||||
"range": "Range",
|
"range": "Range",
|
||||||
"ranges": "Ranges",
|
"ranges": "Ranges",
|
||||||
"mobility": "Mobility",
|
"mobility": "Mobility",
|
||||||
|
"vehicle": "Vehicle",
|
||||||
"vehicle_specs": "Vehicle specifications",
|
"vehicle_specs": "Vehicle specifications",
|
||||||
"kind": "Kind",
|
"kind": "Kind",
|
||||||
"kind_vehicle": "Vehicle",
|
"kind_vehicle": "Vehicle",
|
||||||
@@ -183,6 +186,8 @@
|
|||||||
"speed_duration_ph": "top speed duration (e.g. 10 min)",
|
"speed_duration_ph": "top speed duration (e.g. 10 min)",
|
||||||
"effort_reserve": "Effort reserve",
|
"effort_reserve": "Effort reserve",
|
||||||
"maintenance": "Maintenance",
|
"maintenance": "Maintenance",
|
||||||
|
"owner": "Owner",
|
||||||
|
"no_vehicles": "No vehicles",
|
||||||
"rarity": "Rarity",
|
"rarity": "Rarity",
|
||||||
"rarity_sm": "Rar.",
|
"rarity_sm": "Rar.",
|
||||||
"reliability": "Reliability",
|
"reliability": "Reliability",
|
||||||
@@ -214,6 +219,7 @@
|
|||||||
"type_npc": "NPC",
|
"type_npc": "NPC",
|
||||||
"type_creature": "Creature",
|
"type_creature": "Creature",
|
||||||
"type_community": "Community",
|
"type_community": "Community",
|
||||||
|
"type_vehicle": "Vehicle",
|
||||||
"type": "Type",
|
"type": "Type",
|
||||||
"group_members": "Members",
|
"group_members": "Members",
|
||||||
"encounters": "Encounters",
|
"encounters": "Encounters",
|
||||||
@@ -394,7 +400,8 @@
|
|||||||
"npc": "NPC",
|
"npc": "NPC",
|
||||||
"group": "Group",
|
"group": "Group",
|
||||||
"creature": "Creature",
|
"creature": "Creature",
|
||||||
"community": "Community"
|
"community": "Community",
|
||||||
|
"vehicle": "Vehicle"
|
||||||
},
|
},
|
||||||
"base_values": "Base Values",
|
"base_values": "Base Values",
|
||||||
"computed_values": "Computed Values",
|
"computed_values": "Computed Values",
|
||||||
|
|||||||
+9
-2
@@ -8,7 +8,7 @@
|
|||||||
"TYPES.Item.item": "Objet",
|
"TYPES.Item.item": "Objet",
|
||||||
"TYPES.Item.weapon": "Arme",
|
"TYPES.Item.weapon": "Arme",
|
||||||
"TYPES.Item.defense": "Protection",
|
"TYPES.Item.defense": "Protection",
|
||||||
"TYPES.Item.vehicle": "Véhicule",
|
"TYPES.Actor.vehicle": "Véhicule",
|
||||||
"TYPES.Item.ability": "Capacité",
|
"TYPES.Item.ability": "Capacité",
|
||||||
"TYPES.Item.specialty": "Spécialité",
|
"TYPES.Item.specialty": "Spécialité",
|
||||||
"TYPES.Item.background": "Historique",
|
"TYPES.Item.background": "Historique",
|
||||||
@@ -152,6 +152,8 @@
|
|||||||
"pool": "Réserve",
|
"pool": "Réserve",
|
||||||
"pools": "Réserves",
|
"pools": "Réserves",
|
||||||
"reserves": "Réserves",
|
"reserves": "Réserves",
|
||||||
|
"dice_pool": "Pool de dés",
|
||||||
|
"auto_successes": "réussites automatiques",
|
||||||
"self_control": "Sang-Froid",
|
"self_control": "Sang-Froid",
|
||||||
"effort": "Effort",
|
"effort": "Effort",
|
||||||
"equip": "Équiper",
|
"equip": "Équiper",
|
||||||
@@ -255,6 +257,7 @@
|
|||||||
"range": "Portée",
|
"range": "Portée",
|
||||||
"ranges": "Portées",
|
"ranges": "Portées",
|
||||||
"mobility": "Mobilité",
|
"mobility": "Mobilité",
|
||||||
|
"vehicle": "Véhicule",
|
||||||
"vehicle_specs": "Caractéristiques du véhicule",
|
"vehicle_specs": "Caractéristiques du véhicule",
|
||||||
"kind": "Type",
|
"kind": "Type",
|
||||||
"kind_vehicle": "Véhicule",
|
"kind_vehicle": "Véhicule",
|
||||||
@@ -264,6 +267,8 @@
|
|||||||
"speed_duration_ph": "durée de pointe (ex: 10 min)",
|
"speed_duration_ph": "durée de pointe (ex: 10 min)",
|
||||||
"effort_reserve": "Réserve d'Effort",
|
"effort_reserve": "Réserve d'Effort",
|
||||||
"maintenance": "Entretien",
|
"maintenance": "Entretien",
|
||||||
|
"owner": "Propriétaire",
|
||||||
|
"no_vehicles": "Aucun véhicule",
|
||||||
"rarity": "Rareté",
|
"rarity": "Rareté",
|
||||||
"rarity_sm": "Rar.",
|
"rarity_sm": "Rar.",
|
||||||
"reliability": "Fiabilité",
|
"reliability": "Fiabilité",
|
||||||
@@ -405,6 +410,7 @@
|
|||||||
"type_npc": "PNJ",
|
"type_npc": "PNJ",
|
||||||
"type_creature": "Créature",
|
"type_creature": "Créature",
|
||||||
"type_community": "Communauté",
|
"type_community": "Communauté",
|
||||||
|
"type_vehicle": "Véhicule",
|
||||||
"type": "Type",
|
"type": "Type",
|
||||||
"group_members": "Membres",
|
"group_members": "Membres",
|
||||||
"encounters": "Rencontres",
|
"encounters": "Rencontres",
|
||||||
@@ -451,7 +457,8 @@
|
|||||||
"npc": "PNJ",
|
"npc": "PNJ",
|
||||||
"group": "Groupe",
|
"group": "Groupe",
|
||||||
"creature": "Créature",
|
"creature": "Créature",
|
||||||
"community": "Communauté"
|
"community": "Communauté",
|
||||||
|
"vehicle": "Véhicule"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"UI": {
|
"UI": {
|
||||||
|
|||||||
+65
-94
@@ -30,77 +30,70 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.skills-container {
|
.npc-trait-list {
|
||||||
display: flex;
|
li {
|
||||||
flex-direction: column;
|
display: flex;
|
||||||
gap: 15px;
|
align-items: center;
|
||||||
}
|
gap: 6px;
|
||||||
|
padding: 4px 0;
|
||||||
.skill-category {
|
border-bottom: 1px solid @color-border-dark-3;
|
||||||
.card-style();
|
|
||||||
padding: 10px;
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font-family: "DistressBlack", sans-serif;
|
|
||||||
font-size: @font-size-14;
|
|
||||||
text-transform: uppercase;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
background: 50% 0% / cover no-repeat url("@{ui-path}/scotch.webp");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.skill-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 5px;
|
|
||||||
border-bottom: 1px solid @color-border-dark-3;
|
|
||||||
|
|
||||||
&:last-child { border-bottom: none; }
|
|
||||||
|
|
||||||
label {
|
|
||||||
flex: 1;
|
|
||||||
font-size: @font-size-12;
|
font-size: @font-size-12;
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
&:last-child { border-bottom: none; }
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
strong { flex: 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.trait-value {
|
||||||
|
min-width: 30px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.npc-roll-btn {
|
||||||
|
color: @color-text-light-primary;
|
||||||
|
opacity: 0.7;
|
||||||
|
transition: opacity 0.15s ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: 0 0 10px @theme-color-highlight inset;
|
opacity: 1;
|
||||||
|
color: @color-text-light-1;
|
||||||
|
text-shadow: 0 0 6px @theme-color-highlight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.skill-control {
|
.npc-wounds {
|
||||||
display: flex;
|
flex-wrap: wrap;
|
||||||
align-items: center;
|
|
||||||
gap: 5px;
|
.wound-cat {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wound-boxes {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 2px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 8px;
|
||||||
|
color: @color-border-dark-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.skill-value {
|
.npc-free-skills {
|
||||||
min-width: 25px;
|
margin-top: 15px;
|
||||||
text-align: center;
|
.form-group-style();
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rarity-badge {
|
label {
|
||||||
display: inline-block;
|
font-size: @font-size-12;
|
||||||
padding: 1px 4px;
|
font-weight: bold;
|
||||||
border-radius: 3px;
|
white-space: nowrap;
|
||||||
font-size: 10px;
|
}
|
||||||
font-weight: bold;
|
|
||||||
margin-left: 5px;
|
|
||||||
|
|
||||||
&.rarity-0 { .rarity-badge(@rarity-0-bg, @rarity-0-text); }
|
|
||||||
&.rarity-1 { .rarity-badge(@rarity-1-bg, @rarity-1-text); }
|
|
||||||
&.rarity-2 { .rarity-badge(@rarity-2-bg, @rarity-2-text); }
|
|
||||||
&.rarity-3 { .rarity-badge(@rarity-3-bg, @rarity-3-text); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.skill-category-selector {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
.card-style();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.wounds-card {
|
.wounds-card {
|
||||||
@@ -133,39 +126,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ability-section {
|
|
||||||
.card-style();
|
|
||||||
}
|
|
||||||
|
|
||||||
.ability-category-header {
|
|
||||||
font-family: "DistressBlack", sans-serif;
|
|
||||||
font-size: @font-size-14;
|
|
||||||
text-transform: uppercase;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
border-bottom: 1px solid @color-border-dark-3;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ability-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 5px 0;
|
|
||||||
|
|
||||||
label {
|
|
||||||
flex: 1;
|
|
||||||
font-size: @font-size-12;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ability-control {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab {
|
.tab {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@@ -213,6 +173,17 @@
|
|||||||
padding: 3px 5px;
|
padding: 3px 5px;
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
font-size: @font-size-12;
|
||||||
|
padding: 3px 5px;
|
||||||
|
min-width: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.npc-profile-grid {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor {
|
.editor {
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
@import "../variables";
|
||||||
|
@import "../utilities";
|
||||||
|
|
||||||
|
.system-vermine2047 .vermine2047.actor.vehicle {
|
||||||
|
display: grid !important;
|
||||||
|
grid-template-columns: 1fr !important;
|
||||||
|
grid-template-rows: auto 1fr auto !important;
|
||||||
|
|
||||||
|
> header.window-header {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> section.window-content {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div.window-resize-handle {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-content {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto auto 1fr;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
> .tab.main {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 1;
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 8px;
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
> nav.tabs {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .tab:not(.main) {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 3;
|
||||||
|
display: none;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet-header {
|
||||||
|
.background-image(url("@{ui-path}/barre_haut.webp"), no-repeat, 100% 100%, right top);
|
||||||
|
padding: 10px;
|
||||||
|
max-height: 130px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-fields { flex: 1; }
|
||||||
|
|
||||||
|
.resource {
|
||||||
|
.card-style();
|
||||||
|
}
|
||||||
|
|
||||||
|
.resource-label {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 8px;
|
||||||
|
min-width: 60px;
|
||||||
|
font-size: @font-size-12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resource-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
select {
|
||||||
|
margin-right: 8px;
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
width: 60px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.charname {
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
font-size: @font-size-18;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vehicle-owner {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vehicle-section {
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid @color-border-dark-4;
|
||||||
|
background: fade(@color-chitin-dark, 20%);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resource-label {
|
||||||
|
display: block;
|
||||||
|
margin: 0 0 4px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit {
|
||||||
|
font-size: @font-size-11;
|
||||||
|
color: @color-text-light-0;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maintenance {
|
||||||
|
margin-top: 8px;
|
||||||
|
|
||||||
|
.flexrow label {
|
||||||
|
gap: 4px;
|
||||||
|
margin-right: 12px;
|
||||||
|
font-size: @font-size-12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
label {
|
||||||
|
font-family: "DistressBlack", sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: @font-size-11;
|
||||||
|
color: @color-amber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
@import "actor/group";
|
@import "actor/group";
|
||||||
@import "actor/creature";
|
@import "actor/creature";
|
||||||
@import "actor/community";
|
@import "actor/community";
|
||||||
|
@import "actor/vehicle";
|
||||||
|
|
||||||
// 6. Styles des items
|
// 6. Styles des items
|
||||||
@import "items";
|
@import "items";
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ 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 { default as VermineCommunitySheetV2 } from "./community-sheet.mjs"
|
||||||
|
export { default as VermineVehicleSheetV2 } from "./vehicle-sheet.mjs"
|
||||||
export {
|
export {
|
||||||
VermineItemSheetV2,
|
VermineItemSheetV2,
|
||||||
VermineWeaponSheetV2,
|
VermineWeaponSheetV2,
|
||||||
VermineDefenseSheetV2,
|
VermineDefenseSheetV2,
|
||||||
VermineVehicleSheetV2,
|
|
||||||
VermineAbilitySheetV2,
|
VermineAbilitySheetV2,
|
||||||
VermineSpecialtySheetV2,
|
VermineSpecialtySheetV2,
|
||||||
VermineBackgroundSheetV2,
|
VermineBackgroundSheetV2,
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ export default class VermineBaseActorSheet extends HandlebarsApplicationMixin(fo
|
|||||||
delete: VermineBaseActorSheet.#onItemDelete,
|
delete: VermineBaseActorSheet.#onItemDelete,
|
||||||
toggleEquip: VermineBaseActorSheet.#onToggleEquip,
|
toggleEquip: VermineBaseActorSheet.#onToggleEquip,
|
||||||
create: VermineBaseActorSheet.#onItemCreate,
|
create: VermineBaseActorSheet.#onItemCreate,
|
||||||
|
createVehicle: VermineBaseActorSheet.#onCreateVehicle,
|
||||||
|
editVehicle: VermineBaseActorSheet.#onEditVehicle,
|
||||||
|
deleteVehicle: VermineBaseActorSheet.#onDeleteVehicle,
|
||||||
roll: VermineBaseActorSheet.#onRollItem,
|
roll: VermineBaseActorSheet.#onRollItem,
|
||||||
attack: VermineBaseActorSheet.#onAttack,
|
attack: VermineBaseActorSheet.#onAttack,
|
||||||
clickRadio: VermineBaseActorSheet.#onClickRadioHexa,
|
clickRadio: VermineBaseActorSheet.#onClickRadioHexa,
|
||||||
@@ -229,11 +232,46 @@ export default class VermineBaseActorSheet extends HandlebarsApplicationMixin(fo
|
|||||||
await this.document.createEmbeddedDocuments("Item", [{ name, type }])
|
await this.document.createEmbeddedDocuments("Item", [{ name, type }])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Véhicules (acteurs) ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
/** Crée un acteur "vehicle" rattaché à cet acteur (groupe ou personnage). */
|
||||||
|
static async #onCreateVehicle(event, target) {
|
||||||
|
const name = game.i18n.localize("ITEMS.new_vehicle")
|
||||||
|
const vehicle = await Actor.create({
|
||||||
|
name,
|
||||||
|
type: "vehicle",
|
||||||
|
system: { ownerId: this.document.id },
|
||||||
|
// Le véhicule est un bien partagé : reprendre la propriété du propriétaire
|
||||||
|
ownership: foundry.utils.deepClone(this.document.ownership)
|
||||||
|
})
|
||||||
|
vehicle?.sheet.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
static async #onEditVehicle(event, target) {
|
||||||
|
const id = target.closest("[data-vehicle-id]")?.dataset?.vehicleId
|
||||||
|
const vehicle = game.actors.get(id)
|
||||||
|
vehicle?.sheet.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
static async #onDeleteVehicle(event, target) {
|
||||||
|
const id = target.closest("[data-vehicle-id]")?.dataset?.vehicleId
|
||||||
|
const vehicle = game.actors.get(id)
|
||||||
|
await vehicle?.deleteDialog()
|
||||||
|
}
|
||||||
|
|
||||||
static async #onRollItem(event, target) {
|
static async #onRollItem(event, target) {
|
||||||
const id = target.closest("[data-item-id]")?.dataset?.itemId
|
const id = target.closest("[data-item-id]")?.dataset?.itemId
|
||||||
if (!id) return
|
if (!id) return
|
||||||
const item = this.document.items.get(id)
|
const item = this.document.items.get(id)
|
||||||
if (!item) return
|
if (!item) return
|
||||||
|
// Armes : PNJ → dialogue de combat (valeur d'Attaque) ; personnage →
|
||||||
|
// dialogue de compétence. Les PNJ n'ont ni caractéristiques ni compétences.
|
||||||
|
if (item.type === "weapon" && this.document.type === 'npc') {
|
||||||
|
const { default: CombatDialog } = await import("../../system/dialogs/combatDialog.mjs")
|
||||||
|
const dialog = await CombatDialog.create({ actorId: this.document.id, weapon: item })
|
||||||
|
if (dialog) dialog.render(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
if (item.type === "weapon" && this.document.system.abilities && this.document.system.skills) {
|
if (item.type === "weapon" && this.document.system.abilities && this.document.system.skills) {
|
||||||
const { default: RollDialog } = await import("../../system/dialogs/rollDialog.mjs")
|
const { default: RollDialog } = await import("../../system/dialogs/rollDialog.mjs")
|
||||||
const dialog = await RollDialog.create({
|
const dialog = await RollDialog.create({
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export default class VermineCharacterSheetV2 extends VermineBaseActorSheet {
|
|||||||
context.gear = doc.itemTypes.item
|
context.gear = doc.itemTypes.item
|
||||||
context.weapons = doc.itemTypes.weapon
|
context.weapons = doc.itemTypes.weapon
|
||||||
context.defenses = doc.itemTypes.defense
|
context.defenses = doc.itemTypes.defense
|
||||||
context.vehicles = doc.itemTypes.vehicle
|
context.vehicles = game.actors.filter(a => a.type === "vehicle" && a.system.ownerId === doc.id)
|
||||||
break
|
break
|
||||||
case "stories":
|
case "stories":
|
||||||
context.tab = context.tabs.stories
|
context.tab = context.tabs.stories
|
||||||
|
|||||||
@@ -80,10 +80,11 @@ export default class VermineGroupSheetV2 extends VermineBaseActorSheet {
|
|||||||
context.gear = doc.itemTypes.item
|
context.gear = doc.itemTypes.item
|
||||||
context.weapons = doc.itemTypes.weapon
|
context.weapons = doc.itemTypes.weapon
|
||||||
context.defenses = doc.itemTypes.defense
|
context.defenses = doc.itemTypes.defense
|
||||||
|
context.vehicles = this.#getOwnedVehicles()
|
||||||
break
|
break
|
||||||
case "road":
|
case "road":
|
||||||
context.tab = context.tabs.road
|
context.tab = context.tabs.road
|
||||||
context.vehicles = doc.itemTypes.vehicle
|
context.vehicles = this.#getOwnedVehicles()
|
||||||
break
|
break
|
||||||
case "reserve":
|
case "reserve":
|
||||||
context.tab = context.tabs.reserve
|
context.tab = context.tabs.reserve
|
||||||
@@ -92,6 +93,11 @@ export default class VermineGroupSheetV2 extends VermineBaseActorSheet {
|
|||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Véhicules (acteurs) appartenant à ce groupe via system.ownerId. */
|
||||||
|
#getOwnedVehicles() {
|
||||||
|
return game.actors.filter(a => a.type === "vehicle" && a.system.ownerId === this.document.id)
|
||||||
|
}
|
||||||
|
|
||||||
// Actions : délégation aux applications AppV1 existantes pour TotemPicker/ActorPicker
|
// Actions : délégation aux applications AppV1 existantes pour TotemPicker/ActorPicker
|
||||||
static async #onChooseTotem(event, target) {
|
static async #onChooseTotem(event, target) {
|
||||||
const { TotemPicker } = await import("../../system/applications.mjs")
|
const { TotemPicker } = await import("../../system/applications.mjs")
|
||||||
|
|||||||
@@ -18,34 +18,6 @@ export class VermineDefenseSheetV2 extends VermineBaseItemSheet {
|
|||||||
static PARTS = { main: { template: "systems/vermine2047/templates/item/item-defense-sheet.hbs", scrollable: [""] } }
|
static PARTS = { main: { template: "systems/vermine2047/templates/item/item-defense-sheet.hbs", scrollable: [""] } }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Véhicule ──────────────────────────────────────────────────────────
|
|
||||||
export class VermineVehicleSheetV2 extends VermineBaseItemSheet {
|
|
||||||
static DEFAULT_OPTIONS = { classes: ["vehicle"], position: { width: 520 } }
|
|
||||||
static PARTS = { main: { template: "systems/vermine2047/templates/item/item-vehicle-sheet.hbs", scrollable: [""] } }
|
|
||||||
|
|
||||||
async _prepareContext() {
|
|
||||||
const context = await super._prepareContext()
|
|
||||||
// Compétences d'Entretien possibles (mécanique, technologie, artisanat, animalisme…)
|
|
||||||
const maintenanceKeys = ["mecanical", "technology", "crafting", "animalism", "environment", "wildlife", "flora", "repulsion", "toxics"]
|
|
||||||
const current = this.document.system.maintenance || []
|
|
||||||
context.maintenanceSkills = maintenanceKeys.map(key => ({
|
|
||||||
key,
|
|
||||||
label: game.i18n.localize("SKILLS." + key + ".name"),
|
|
||||||
checked: current.includes(key)
|
|
||||||
}))
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @override - nettoie le tableau d'Entretien (retire les cases non cochées). */
|
|
||||||
_prepareSubmitData(event, form, formData, updateData) {
|
|
||||||
const result = super._prepareSubmitData(event, form, formData, updateData)
|
|
||||||
if (Array.isArray(result?.system?.maintenance)) {
|
|
||||||
result.system.maintenance = result.system.maintenance.filter(v => typeof v === "string" && v.trim() !== "")
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Capacité ──────────────────────────────────────────────────────────
|
// ── Capacité ──────────────────────────────────────────────────────────
|
||||||
export class VermineAbilitySheetV2 extends VermineBaseItemSheet {
|
export class VermineAbilitySheetV2 extends VermineBaseItemSheet {
|
||||||
static DEFAULT_OPTIONS = { classes: ["ability"], position: { width: 560 } }
|
static DEFAULT_OPTIONS = { classes: ["ability"], position: { width: 560 } }
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ import VermineBaseActorSheet from "./base-actor-sheet.mjs"
|
|||||||
|
|
||||||
export default class VermineNpcSheetV2 extends VermineBaseActorSheet {
|
export default class VermineNpcSheetV2 extends VermineBaseActorSheet {
|
||||||
|
|
||||||
// La fiche PNJ s'ouvre en mode édition : caractéristiques, compétences et
|
// La fiche PNJ s'ouvre en mode édition : profil et niveaux (Menace,
|
||||||
// niveaux se règlent dès l'ouverture (le mode jeu reste accessible via le toggle).
|
// Expérience, Rôle) se règlent dès l'ouverture (le mode jeu reste accessible
|
||||||
|
// via le toggle).
|
||||||
_sheetMode = this.constructor.SHEET_MODES.EDIT
|
_sheetMode = this.constructor.SHEET_MODES.EDIT
|
||||||
|
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
@@ -15,22 +16,18 @@ export default class VermineNpcSheetV2 extends VermineBaseActorSheet {
|
|||||||
static PARTS = {
|
static PARTS = {
|
||||||
main: { template: "systems/vermine2047/templates/actor/appv2/npc-main.hbs", scrollable: [""] },
|
main: { template: "systems/vermine2047/templates/actor/appv2/npc-main.hbs", scrollable: [""] },
|
||||||
tabs: { template: "templates/generic/tab-navigation.hbs" },
|
tabs: { template: "templates/generic/tab-navigation.hbs" },
|
||||||
characteristics: { template: "systems/vermine2047/templates/actor/appv2/npc-characteristics.hbs", scrollable: [""] },
|
traits: { template: "systems/vermine2047/templates/actor/appv2/npc-traits.hbs", scrollable: [""] },
|
||||||
skills: { template: "systems/vermine2047/templates/actor/appv2/npc-skills.hbs", scrollable: [""] },
|
|
||||||
equipment: { template: "systems/vermine2047/templates/actor/appv2/npc-equipment.hbs", scrollable: [""] },
|
equipment: { template: "systems/vermine2047/templates/actor/appv2/npc-equipment.hbs", scrollable: [""] },
|
||||||
threat: { template: "systems/vermine2047/templates/actor/appv2/npc-threat.hbs", scrollable: [""] },
|
|
||||||
combat: { template: "systems/vermine2047/templates/actor/appv2/npc-combat.hbs", scrollable: [""] },
|
combat: { template: "systems/vermine2047/templates/actor/appv2/npc-combat.hbs", scrollable: [""] },
|
||||||
notes: { template: "systems/vermine2047/templates/actor/appv2/npc-notes.hbs", scrollable: [""] }
|
notes: { template: "systems/vermine2047/templates/actor/appv2/npc-notes.hbs", scrollable: [""] }
|
||||||
}
|
}
|
||||||
|
|
||||||
tabGroups = { sheet: "characteristics" }
|
tabGroups = { sheet: "traits" }
|
||||||
|
|
||||||
#getTabs() {
|
#getTabs() {
|
||||||
const tabs = {
|
const tabs = {
|
||||||
characteristics: { id: "characteristics", group: "sheet", icon: "fas fa-dice", label: "VERMINE.abilities" },
|
traits: { id: "traits", group: "sheet", icon: "fas fa-dice", label: "VERMINE.traits" },
|
||||||
skills: { id: "skills", group: "sheet", icon: "fas fa-brain", label: "VERMINE.skills" },
|
|
||||||
equipment: { id: "equipment", group: "sheet", icon: "fas fa-hammer", label: "VERMINE.tabs.equipment" },
|
equipment: { id: "equipment", group: "sheet", icon: "fas fa-hammer", label: "VERMINE.tabs.equipment" },
|
||||||
threat: { id: "threat", group: "sheet", icon: "fas fa-exclamation-triangle", label: "ADVERSITY.threat" },
|
|
||||||
combat: { id: "combat", group: "sheet", icon: "fas fa-sword", label: "VERMINE.combat" },
|
combat: { id: "combat", group: "sheet", icon: "fas fa-sword", label: "VERMINE.combat" },
|
||||||
notes: { id: "notes", group: "sheet", icon: "fas fa-sticky-note", label: "IDENTITY.notes" }
|
notes: { id: "notes", group: "sheet", icon: "fas fa-sticky-note", label: "IDENTITY.notes" }
|
||||||
}
|
}
|
||||||
@@ -57,20 +54,14 @@ export default class VermineNpcSheetV2 extends VermineBaseActorSheet {
|
|||||||
context.totemOptions = CONFIG.VERMINE.totems
|
context.totemOptions = CONFIG.VERMINE.totems
|
||||||
context.originOptions = CONFIG.VERMINE.origins
|
context.originOptions = CONFIG.VERMINE.origins
|
||||||
break
|
break
|
||||||
case "characteristics":
|
case "traits":
|
||||||
context.tab = context.tabs.characteristics
|
context.tab = context.tabs.traits
|
||||||
break
|
|
||||||
case "skills":
|
|
||||||
context.tab = context.tabs.skills
|
|
||||||
break
|
break
|
||||||
case "equipment":
|
case "equipment":
|
||||||
context.tab = context.tabs.equipment
|
context.tab = context.tabs.equipment
|
||||||
context.weapons = doc.itemTypes.weapon
|
context.weapons = doc.itemTypes.weapon
|
||||||
context.defenses = doc.itemTypes.defense
|
context.defenses = doc.itemTypes.defense
|
||||||
break
|
break
|
||||||
case "threat":
|
|
||||||
context.tab = context.tabs.threat
|
|
||||||
break
|
|
||||||
case "combat":
|
case "combat":
|
||||||
context.tab = context.tabs.combat
|
context.tab = context.tabs.combat
|
||||||
context.equippedWeapons = doc.itemTypes.weapon.filter(i => i.system.equipped)
|
context.equippedWeapons = doc.itemTypes.weapon.filter(i => i.system.equipped)
|
||||||
@@ -84,4 +75,27 @@ export default class VermineNpcSheetV2 extends VermineBaseActorSheet {
|
|||||||
}
|
}
|
||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @override - Le PNJ n'a ni caractéristiques ni compétences : les jets
|
||||||
|
* rapides utilisent la valeur d'Attaque (dialogue de combat) ou les valeurs
|
||||||
|
* dérivées Action / Spécialité / Réaction (dialogue PNJ simplifié). */
|
||||||
|
async _onRoll(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
const el = event.currentTarget
|
||||||
|
const type = el.dataset.type
|
||||||
|
if (!type) return
|
||||||
|
if (type === "attack") {
|
||||||
|
const { default: CombatDialog } = await import("../../system/dialogs/combatDialog.mjs")
|
||||||
|
const dialog = await CombatDialog.create({ actorId: this.document.id })
|
||||||
|
if (dialog) dialog.render(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (["action", "specialty", "reaction"].includes(type)) {
|
||||||
|
const { default: NpcRollDialog } = await import("../../system/dialogs/npcRollDialog.mjs")
|
||||||
|
const dialog = await NpcRollDialog.create({ actorId: this.document.id, rolltype: type })
|
||||||
|
if (dialog) dialog.render(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return super._onRoll(event)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import VermineBaseActorSheet from "./base-actor-sheet.mjs"
|
||||||
|
|
||||||
|
export default class VermineVehicleSheetV2 extends VermineBaseActorSheet {
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["vehicle"],
|
||||||
|
position: { width: 640, height: 580 },
|
||||||
|
window: { contentClasses: ["vehicle-content"] }
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/vermine2047/templates/actor/appv2/vehicle-main.hbs", scrollable: [""] },
|
||||||
|
tabs: { template: "templates/generic/tab-navigation.hbs" },
|
||||||
|
specs: { template: "systems/vermine2047/templates/actor/appv2/vehicle-specs.hbs", scrollable: [""] }
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { sheet: "specs" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
specs: { id: "specs", group: "sheet", icon: "fas fa-car-side", label: "VERMINE.vehicle_specs" }
|
||||||
|
}
|
||||||
|
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()
|
||||||
|
// Compétences d'Entretien possibles (mécanique, technologie, artisanat, animalisme…)
|
||||||
|
const maintenanceKeys = ["mecanical", "technology", "crafting", "animalism", "environment", "wildlife", "flora", "repulsion", "toxics"]
|
||||||
|
const current = this.document.system.maintenance || []
|
||||||
|
context.maintenanceSkills = maintenanceKeys.map(key => ({
|
||||||
|
key,
|
||||||
|
label: game.i18n.localize("SKILLS." + key + ".name"),
|
||||||
|
checked: current.includes(key)
|
||||||
|
}))
|
||||||
|
// Propriétaire (groupe ou personnage) résolu
|
||||||
|
context.resolvedOwner = null
|
||||||
|
if (this.document.system.ownerId) {
|
||||||
|
const owner = game.actors.get(this.document.system.ownerId)
|
||||||
|
if (owner) context.resolvedOwner = { id: owner.id, name: owner.name }
|
||||||
|
}
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
async _preparePartContext(partId, context) {
|
||||||
|
switch (partId) {
|
||||||
|
case "main": break
|
||||||
|
case "specs":
|
||||||
|
context.tab = context.tabs.specs
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override - nettoie le tableau d'Entretien (retire les cases non cochées). */
|
||||||
|
_prepareSubmitData(event, form, formData, updateData) {
|
||||||
|
const result = super._prepareSubmitData(event, form, formData, updateData)
|
||||||
|
if (Array.isArray(result?.system?.maintenance)) {
|
||||||
|
result.system.maintenance = result.system.maintenance.filter(v => typeof v === "string" && v.trim() !== "")
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
+75
-62
@@ -2,17 +2,22 @@
|
|||||||
* DataModel pour les acteurs de type "npc" (PNJ).
|
* DataModel pour les acteurs de type "npc" (PNJ).
|
||||||
* Étend foundry.abstract.TypeDataModel.
|
* Étend foundry.abstract.TypeDataModel.
|
||||||
*
|
*
|
||||||
* Note : le champ libre de compétences (texte descriptif) est nommé "freeSkills"
|
* Conforme aux règles des PNJ (regles/regles_pnj.txt) : un PNJ n'a ni
|
||||||
* pour éviter le conflit avec le SchemaField "skills" qui contient les 30 compétences.
|
* caractéristiques chiffrées, ni réserves détaillées, ni liste de compétences.
|
||||||
|
* Il est défini uniquement par son Profil (identité) et trois critères :
|
||||||
|
* Menace, Expérience et Rôle. Toutes les valeurs utiles en jeu sont dérivées
|
||||||
|
* des tableaux de référence (CONFIG.VERMINE.npc*Levels) et exposées dans
|
||||||
|
* "system.computed".
|
||||||
|
*
|
||||||
|
* Note : le champ libre de description des Spécialités est nommé "freeSkills"
|
||||||
|
* pour éviter le conflit avec le champ "skills" que le template.json historique
|
||||||
|
* définissait comme texte libre pour les PNJ.
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
woundSchema,
|
woundSchema,
|
||||||
combatStatusSchema,
|
combatStatusSchema,
|
||||||
equipmentSchema,
|
equipmentSchema,
|
||||||
attributeSchema,
|
attributeSchema
|
||||||
abilitiesSchema,
|
|
||||||
skillCategoriesSchema,
|
|
||||||
skillsSchema
|
|
||||||
} from "./_shared.mjs"
|
} from "./_shared.mjs"
|
||||||
|
|
||||||
export default class VermineNpcData extends foundry.abstract.TypeDataModel {
|
export default class VermineNpcData extends foundry.abstract.TypeDataModel {
|
||||||
@@ -23,8 +28,7 @@ export default class VermineNpcData extends foundry.abstract.TypeDataModel {
|
|||||||
/**
|
/**
|
||||||
* Migration des données avant traitement par le schéma.
|
* Migration des données avant traitement par le schéma.
|
||||||
* Avant DataModel, template.json définissait "skills" comme un champ texte libre
|
* Avant DataModel, template.json définissait "skills" comme un champ texte libre
|
||||||
* pour les PNJ. Le DataModel réserve "skills" pour les 30 compétences individuelles
|
* pour les PNJ. Le DataModel utilise "freeSkills" pour cette description.
|
||||||
* (SchemaField) et utilise "freeSkills" pour le texte libre.
|
|
||||||
* @param {Object} source Données brutes avant validation du schéma
|
* @param {Object} source Données brutes avant validation du schéma
|
||||||
* @returns {Object} Données migrées
|
* @returns {Object} Données migrées
|
||||||
*/
|
*/
|
||||||
@@ -48,9 +52,10 @@ export default class VermineNpcData extends foundry.abstract.TypeDataModel {
|
|||||||
// Statut de combat (base, difficulté par défaut 9 pour PNJ)
|
// Statut de combat (base, difficulté par défaut 9 pour PNJ)
|
||||||
combatStatus: combatStatusSchema("9"),
|
combatStatus: combatStatusSchema("9"),
|
||||||
|
|
||||||
// Identité
|
// Identité (Profil du PNJ)
|
||||||
identity: new fields.SchemaField({
|
identity: new fields.SchemaField({
|
||||||
name: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
name: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
age: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
profile: 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: "" }),
|
origin: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
totem: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
totem: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
@@ -58,30 +63,29 @@ export default class VermineNpcData extends foundry.abstract.TypeDataModel {
|
|||||||
notes: new fields.HTMLField({ required: true, initial: "" })
|
notes: new fields.HTMLField({ required: true, initial: "" })
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Attributs (XP, réputation, sang-froid, effort)
|
// Critères de définition du PNJ (Menace, Expérience, Rôle)
|
||||||
attributes: new fields.SchemaField({
|
|
||||||
xp: attributeSchema(0, 0, 10),
|
|
||||||
reputation: attributeSchema(0, 0, 10),
|
|
||||||
self_control: attributeSchema(0, 0, 5),
|
|
||||||
effort: attributeSchema(0, 0, 5)
|
|
||||||
}),
|
|
||||||
|
|
||||||
// Niveaux PNJ (menace, expérience, rôle)
|
|
||||||
threat: attributeSchema(1, 1, 4),
|
threat: attributeSchema(1, 1, 4),
|
||||||
experience: attributeSchema(1, 1, 4),
|
experience: attributeSchema(1, 1, 4),
|
||||||
role: attributeSchema(1, 1, 4),
|
role: attributeSchema(1, 1, 4),
|
||||||
|
|
||||||
// Compétences (les 30 compétences individuelles)
|
// Description libre des Spécialités (champ texte PNJ)
|
||||||
skills: skillsSchema(),
|
|
||||||
|
|
||||||
// Description libre des compétences (champ texte PNJ)
|
|
||||||
freeSkills: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
freeSkills: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
|
||||||
// Catégories de compétences
|
// Valeurs calculées (dérivées des niveaux de menace / expérience / rôle)
|
||||||
skill_categories: skillCategoriesSchema(),
|
computed: new fields.SchemaField({
|
||||||
|
attack: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||||
// Caractéristiques (8)
|
vigor: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||||
abilities: abilitiesSchema(),
|
action: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 3 }),
|
||||||
|
specialties: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 4 }),
|
||||||
|
rerolls: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||||
|
contact: new fields.StringField({ required: true, nullable: false, initial: "7" }),
|
||||||
|
reaction: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 3 }),
|
||||||
|
reactionBonus: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||||
|
pools: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||||
|
gear: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 9 }),
|
||||||
|
gearHindrance: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||||
|
protection: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 1 })
|
||||||
|
}),
|
||||||
|
|
||||||
// Équipement
|
// Équipement
|
||||||
equipment: equipmentSchema()
|
equipment: equipmentSchema()
|
||||||
@@ -92,58 +96,67 @@ export default class VermineNpcData extends foundry.abstract.TypeDataModel {
|
|||||||
prepareDerivedData() {
|
prepareDerivedData() {
|
||||||
super.prepareDerivedData()
|
super.prepareDerivedData()
|
||||||
|
|
||||||
// 1. Calculer les seuils de blessures selon le niveau de menace
|
// 1. Calculer les valeurs dérivées selon les niveaux de menace/expérience/rôle
|
||||||
|
this._setNpcComputedValues()
|
||||||
|
|
||||||
|
// 2. Calculer les seuils de blessures selon le niveau de menace
|
||||||
this._setNpcWoundThresholds()
|
this._setNpcWoundThresholds()
|
||||||
|
|
||||||
// 2. Calculer les réserves selon le niveau de rôle
|
// 3. Mettre à jour le statut de combat
|
||||||
this._setNpcAttributes()
|
|
||||||
|
|
||||||
// 3. Définir les libellés des caractéristiques
|
|
||||||
this._setAbilityLabels()
|
|
||||||
|
|
||||||
// 4. Mettre à jour le statut de combat
|
|
||||||
this._updateCombatStatus()
|
this._updateCombatStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calcule les seuils de blessures à partir du niveau de menace.
|
* Calcule les valeurs dérivées à partir des niveaux de Menace, Expérience
|
||||||
* Utilise CONFIG.VERMINE.npcThreatLevels.
|
* et Rôle. Utilise CONFIG.VERMINE.npcThreatLevels, .npcExperienceLevels
|
||||||
|
* et .npcRoleLevels.
|
||||||
|
*/
|
||||||
|
_setNpcComputedValues() {
|
||||||
|
const threatLevel = this.threat?.value || 1
|
||||||
|
const expLevel = this.experience?.value || 1
|
||||||
|
const roleLevel = this.role?.value || 1
|
||||||
|
|
||||||
|
const threatConfig = CONFIG.VERMINE.npcThreatLevels[threatLevel] || {}
|
||||||
|
const expConfig = CONFIG.VERMINE.npcExperienceLevels[expLevel] || {}
|
||||||
|
const roleConfig = CONFIG.VERMINE.npcRoleLevels[roleLevel] || {}
|
||||||
|
|
||||||
|
// Menace
|
||||||
|
this.computed.attack = threatConfig.attack || 0
|
||||||
|
this.computed.vigor = threatConfig.vigor || 0
|
||||||
|
|
||||||
|
// Expérience
|
||||||
|
this.computed.action = expConfig.action || 3
|
||||||
|
this.computed.specialties = expConfig.specialties || 4
|
||||||
|
this.computed.rerolls = expConfig.rerolls || 0
|
||||||
|
this.computed.contact = expConfig.contact || "7"
|
||||||
|
|
||||||
|
// Rôle
|
||||||
|
this.computed.reaction = roleConfig.reaction || 0
|
||||||
|
this.computed.reactionBonus = roleConfig.reaction_bonus || 0
|
||||||
|
this.computed.pools = roleConfig.pools || 0
|
||||||
|
this.computed.gear = roleConfig.gear || 9
|
||||||
|
this.computed.gearHindrance = roleConfig.gear_hindrance || 0
|
||||||
|
this.computed.protection = roleConfig.protection || 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calcule les seuils et le nombre de boîtes de blessures à partir du
|
||||||
|
* niveau de menace (tableau "Niveau de Menace"). Utilise
|
||||||
|
* CONFIG.VERMINE.npcThreatLevels.
|
||||||
*/
|
*/
|
||||||
_setNpcWoundThresholds() {
|
_setNpcWoundThresholds() {
|
||||||
const health = this.abilities?.health?.value || 1
|
|
||||||
const threatLevel = this.threat?.value || 1
|
const threatLevel = this.threat?.value || 1
|
||||||
const threatConfig = CONFIG.VERMINE.npcThreatLevels[threatLevel] || {}
|
const threatConfig = CONFIG.VERMINE.npcThreatLevels[threatLevel] || {}
|
||||||
|
|
||||||
this.minorWound.threshold = health
|
this.minorWound.threshold = threatConfig.minorThreshold ?? 1
|
||||||
this.majorWound.threshold = health + 3
|
this.majorWound.threshold = threatConfig.majorThreshold ?? 4
|
||||||
this.deadlyWound.threshold = Math.min(health + 7, 10)
|
this.deadlyWound.threshold = threatConfig.deadlyThreshold ?? 6
|
||||||
|
|
||||||
this.minorWound.max = threatConfig.minorWound || 1
|
this.minorWound.max = threatConfig.minorWound || 1
|
||||||
this.majorWound.max = threatConfig.majorWound || 1
|
this.majorWound.max = threatConfig.majorWound || 1
|
||||||
this.deadlyWound.max = threatConfig.deadlyWound || 1
|
this.deadlyWound.max = threatConfig.deadlyWound || 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Définit les attributs dérivés (effort, sang-froid) selon le niveau de rôle.
|
|
||||||
* Utilise CONFIG.VERMINE.npcRoleLevels.
|
|
||||||
*/
|
|
||||||
_setNpcAttributes() {
|
|
||||||
const roleLevel = this.role?.value || 1
|
|
||||||
const roleConfig = CONFIG.VERMINE.npcRoleLevels[roleLevel] || {}
|
|
||||||
|
|
||||||
this.attributes.effort.max = roleConfig.pools || 0
|
|
||||||
this.attributes.self_control.max = roleConfig.reaction_bonus || 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Définit les libellés localisés des caractéristiques.
|
|
||||||
*/
|
|
||||||
_setAbilityLabels() {
|
|
||||||
for (const [k, v] of Object.entries(this.abilities)) {
|
|
||||||
v.label = game.i18n.localize(CONFIG.VERMINE.abilities[k]) ?? k
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Met à jour le label du statut de combat en fonction de la difficulté.
|
* Met à jour le label du statut de combat en fonction de la difficulté.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+34
-10
@@ -1,43 +1,67 @@
|
|||||||
import { baseItemSchema } from "./_shared.mjs"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DataModel pour les items de type "vehicle" (véhicules et montures).
|
* DataModel pour les acteurs de type "vehicle" (véhicules et montures).
|
||||||
* Caractéristiques : Rareté, Fiabilité, Distance, Vitesse (croisière/pointe),
|
* Un véhicule est désormais un acteur (et non un objet) : il possède sa propre
|
||||||
* Entretien (compétences) et Réserve d'Effort (montures).
|
* fiche, peut être posé sur la scène comme un jeton et appartient à un groupe
|
||||||
* @augments {foundry.abstract.TypeDataModel}
|
* ou un personnage via `ownerId`.
|
||||||
|
*
|
||||||
|
* Caractéristiques (regles_vehicules.txt) : Rareté, Fiabilité (véhicules),
|
||||||
|
* Réserve d'Effort (montures), Distance, Vitesse (croisière/pointe) et Entretien.
|
||||||
|
* Pas de statistiques de combat (les règles ne définissent pas de points de vie).
|
||||||
*/
|
*/
|
||||||
|
import { raritySchema } from "./_shared.mjs"
|
||||||
|
|
||||||
export default class VermineVehicleData extends foundry.abstract.TypeDataModel {
|
export default class VermineVehicleData extends foundry.abstract.TypeDataModel {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static LOCALIZATION_PREFIXES = ["VERMINE.item.vehicle"]
|
static LOCALIZATION_PREFIXES = ["VERMINE.vehicle"]
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static defineSchema() {
|
static defineSchema() {
|
||||||
const fields = foundry.data.fields
|
const fields = foundry.data.fields
|
||||||
const reqInt = { required: true, nullable: false, integer: true }
|
const reqInt = { required: true, nullable: false, integer: true }
|
||||||
return {
|
return {
|
||||||
...baseItemSchema(),
|
// Identité
|
||||||
|
identity: new fields.SchemaField({
|
||||||
|
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: "" }),
|
||||||
|
notes: new fields.HTMLField({ required: true, initial: "", textSearch: true })
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Rareté (valeur 1-10 + handicap)
|
||||||
|
rarity: raritySchema(),
|
||||||
|
|
||||||
// Fiabilité étendue (1-10) pour les véhicules
|
// Fiabilité étendue (1-10) pour les véhicules
|
||||||
reliability: new fields.NumberField({ ...reqInt, initial: 5, min: 1, max: 10 }),
|
reliability: new fields.NumberField({ ...reqInt, initial: 5, min: 1, max: 10 }),
|
||||||
|
|
||||||
// Type : "vehicle" (véhicule) ou "mount" (monture)
|
// Type : "vehicle" (véhicule) ou "mount" (monture)
|
||||||
kind: new fields.StringField({ required: true, nullable: false, initial: "vehicle" }),
|
kind: new fields.StringField({ required: true, nullable: false, initial: "vehicle" }),
|
||||||
|
|
||||||
// Distance : km parcourus avec un "plein"
|
// Distance : km parcourus avec un "plein"
|
||||||
distance: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
distance: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
||||||
|
|
||||||
// Vitesse : croisière / pointe (durée de la pointe)
|
// Vitesse : croisière / pointe (durée de la pointe)
|
||||||
speed: new fields.SchemaField({
|
speed: new fields.SchemaField({
|
||||||
cruise: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
cruise: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
||||||
top: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
top: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
||||||
topDuration: new fields.StringField({ required: true, nullable: false, initial: "10 min" })
|
topDuration: new fields.StringField({ required: true, nullable: false, initial: "10 min" })
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Entretien : compétences nécessaires (clés de CONFIG.VERMINE.skills)
|
// Entretien : compétences nécessaires (clés de CONFIG.VERMINE.skills)
|
||||||
maintenance: new fields.ArrayField(new fields.StringField({ required: true, nullable: false, initial: "" })),
|
maintenance: new fields.ArrayField(new fields.StringField({ required: true, nullable: false, initial: "" })),
|
||||||
|
|
||||||
// Réserve d'Effort (montures)
|
// Réserve d'Effort (montures)
|
||||||
effortReserve: new fields.SchemaField({
|
effortReserve: new fields.SchemaField({
|
||||||
value: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
value: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
||||||
min: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
min: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
||||||
max: new fields.NumberField({ ...reqInt, initial: 0, min: 0 })
|
max: new fields.NumberField({ ...reqInt, initial: 0, min: 0 })
|
||||||
}),
|
}),
|
||||||
// Mobilité (héritée)
|
|
||||||
mobility: new fields.NumberField({ ...reqInt, initial: 3, min: 0 })
|
// Mobilité
|
||||||
|
mobility: new fields.NumberField({ ...reqInt, initial: 3, min: 0 }),
|
||||||
|
|
||||||
|
// Propriétaire (id d'acteur : groupe ou personnage)
|
||||||
|
ownerId: new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,10 +99,10 @@ VERMINE.totemDomains = {
|
|||||||
* NPC Threat Levels configuration
|
* NPC Threat Levels configuration
|
||||||
*/
|
*/
|
||||||
VERMINE.npcThreatLevels = {
|
VERMINE.npcThreatLevels = {
|
||||||
1: { "label": "THREAT_LEVELS.minor", "attack": 3, "vigor": 1, "minorWound": 1, "majorWound": 1, "deadlyWound": 1 },
|
1: { "label": "THREAT_LEVELS.minor", "attack": 3, "vigor": 1, "minorThreshold": 1, "majorThreshold": 4, "deadlyThreshold": 6, "minorWound": 1, "majorWound": 1, "deadlyWound": 1 },
|
||||||
2: { "label": "THREAT_LEVELS.serious", "attack": 4, "vigor": 2, "minorWound": 2, "majorWound": 1, "deadlyWound": 1 },
|
2: { "label": "THREAT_LEVELS.serious", "attack": 4, "vigor": 2, "minorThreshold": 2, "majorThreshold": 5, "deadlyThreshold": 8, "minorWound": 2, "majorWound": 1, "deadlyWound": 1 },
|
||||||
3: { "label": "THREAT_LEVELS.major", "attack": 5, "vigor": 3, "minorWound": 2, "majorWound": 1, "deadlyWound": 1 },
|
3: { "label": "THREAT_LEVELS.major", "attack": 5, "vigor": 3, "minorThreshold": 2, "majorThreshold": 5, "deadlyThreshold": 9, "minorWound": 2, "majorWound": 2, "deadlyWound": 1 },
|
||||||
4: { "label": "THREAT_LEVELS.deadly", "attack": 6, "vigor": 4, "minorWound": 2, "majorWound": 2, "deadlyWound": 2 }
|
4: { "label": "THREAT_LEVELS.deadly", "attack": 6, "vigor": 4, "minorThreshold": 3, "majorThreshold": 6, "deadlyThreshold": 9, "minorWound": 2, "majorWound": 2, "deadlyWound": 2 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,208 @@
|
|||||||
|
import { VermineUtils } from "../roll.mjs"
|
||||||
|
|
||||||
|
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialogue de jet simplifié pour les PNJ.
|
||||||
|
*
|
||||||
|
* Un PNJ n'a ni caractéristiques ni compétences : toutes ses actions sont
|
||||||
|
* résolues par une valeur unique dérivée de son Profil (Menace / Expérience /
|
||||||
|
* Rôle), exposée dans system.computed. Ce dialogue fixe le pool selon le type
|
||||||
|
* de jet (Action, Spécialité, Attaque ou Réaction) et n'offre que la difficulté,
|
||||||
|
* le handicap et les bonus simples.
|
||||||
|
*
|
||||||
|
* Utilisé par :
|
||||||
|
* - la fiche PNJ (boutons de jet rapide Action / Spécialité / Réaction) ;
|
||||||
|
* - la défense des PNJ dans les échanges de coups (mode verrouillé).
|
||||||
|
*/
|
||||||
|
export default class NpcRollDialog extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) {
|
||||||
|
|
||||||
|
#actor
|
||||||
|
|
||||||
|
get title() {
|
||||||
|
return game.i18n.localize("VERMINE.roll")
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["vermine-roll"],
|
||||||
|
tag: "form",
|
||||||
|
window: {
|
||||||
|
icon: "fas fa-dice-d10",
|
||||||
|
resizable: false
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
width: 520,
|
||||||
|
height: 600
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
roll: NpcRollDialog.#onRoll,
|
||||||
|
cancel: NpcRollDialog.#onCancel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/vermine2047/templates/dialogs/npc-roll-dialog.hbs" }
|
||||||
|
}
|
||||||
|
|
||||||
|
static async create(data = {}) {
|
||||||
|
const actor = data.actor instanceof Actor ? data.actor : await game.actors.get(data.actorId)
|
||||||
|
if (!actor) {
|
||||||
|
ui.notifications.warn(game.i18n.localize("VERMINE.error_no_actor_selected"))
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return new NpcRollDialog({
|
||||||
|
actor,
|
||||||
|
rolltype: data.rolltype ?? "action",
|
||||||
|
locks: data.locks ?? null,
|
||||||
|
defense: data.defense ?? null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(options = {}) {
|
||||||
|
super(options)
|
||||||
|
this.#actor = options.actor
|
||||||
|
this.rolltype = options.rolltype ?? "action"
|
||||||
|
this.locks = options.locks ?? null
|
||||||
|
this.defense = options.defense ?? null
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Getters ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
get computed() { return this.#actor.system?.computed || {} }
|
||||||
|
|
||||||
|
/** Pool de dés selon le type de jet. */
|
||||||
|
get pool() {
|
||||||
|
const c = this.computed
|
||||||
|
switch (this.rolltype) {
|
||||||
|
case "specialty": return c.specialties || 0
|
||||||
|
case "attack": return c.attack || 0
|
||||||
|
case "reaction": return c.reaction || 0
|
||||||
|
default: return c.action || 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Réussites automatiques (bonus de Réaction du rôle). */
|
||||||
|
get freeSuccesses() {
|
||||||
|
return this.rolltype === "reaction" ? (this.computed.reactionBonus || 0) : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Relances : utilisables uniquement sur les attaques ou les Spécialités. */
|
||||||
|
get rerolls() {
|
||||||
|
if (this.rolltype !== "specialty" && this.rolltype !== "attack") return 0
|
||||||
|
return this.computed.rerolls || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
get label() {
|
||||||
|
const keys = {
|
||||||
|
action: "ADVERSITY.action",
|
||||||
|
specialty: "ADVERSITY.specialties",
|
||||||
|
attack: "ADVERSITY.attack",
|
||||||
|
reaction: "ADVERSITY.reaction"
|
||||||
|
}
|
||||||
|
return game.i18n.localize(keys[this.rolltype] || "VERMINE.roll")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Rendu ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const difficultyOptions = []
|
||||||
|
for (let d = 3; d <= 10; d++) {
|
||||||
|
difficultyOptions.push({ difficulty: d, label: String(d) })
|
||||||
|
}
|
||||||
|
let lockedDifficulty = null
|
||||||
|
let defaultDifficulty = 7
|
||||||
|
if (this.locks?.difficulty !== undefined && this.locks?.difficulty !== null) {
|
||||||
|
lockedDifficulty = parseInt(this.locks.difficulty, 10)
|
||||||
|
defaultDifficulty = lockedDifficulty
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
actor: this.#actor,
|
||||||
|
system: this.#actor.system,
|
||||||
|
config: CONFIG.VERMINE,
|
||||||
|
rollLabel: this.label,
|
||||||
|
rolltype: this.rolltype,
|
||||||
|
pool: this.pool,
|
||||||
|
freeSuccesses: this.freeSuccesses,
|
||||||
|
rerolls: this.rerolls,
|
||||||
|
isDefense: Boolean(this.defense),
|
||||||
|
lockedDifficulty,
|
||||||
|
difficultyOptions,
|
||||||
|
defaultDifficulty,
|
||||||
|
speakerId: this.#actor.id,
|
||||||
|
availableItems: this.#actor.items.filter(i => i.type === "item")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onRender(context, options) {
|
||||||
|
this.element.dataset.actorId = this.#actor.id
|
||||||
|
for (const inp of this.element.querySelectorAll("[data-roll]")) {
|
||||||
|
inp.addEventListener("change", this.#onInputChange.bind(this))
|
||||||
|
}
|
||||||
|
this.element.querySelector("#handicap")?.addEventListener("change", () => this.#updateUI())
|
||||||
|
this.#updateUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
get #el() { return this.element }
|
||||||
|
|
||||||
|
#getHandicap() {
|
||||||
|
const sel = this.#el.querySelector("#handicap")
|
||||||
|
return Math.max(0, (parseInt(sel?.value, 10) || 1) - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
#getDifficulty() {
|
||||||
|
const sel = this.#el.querySelector("#difficulty")
|
||||||
|
return parseInt(sel?.value, 10) || 7
|
||||||
|
}
|
||||||
|
|
||||||
|
#getHelped() { return this.#el.querySelector("#helped")?.checked ? 1 : 0 }
|
||||||
|
|
||||||
|
#getGroup() { return parseInt(this.#el.querySelector("#group")?.value, 10) || 0 }
|
||||||
|
|
||||||
|
getPoolBreakdown() {
|
||||||
|
const help = this.#getHelped()
|
||||||
|
const group = this.#getGroup()
|
||||||
|
return { pool: this.pool, help, group, total: this.pool + help + group }
|
||||||
|
}
|
||||||
|
|
||||||
|
#updateUI() {
|
||||||
|
const b = this.getPoolBreakdown()
|
||||||
|
const totalEl = this.#el.querySelector("#dice-pool-total")
|
||||||
|
if (totalEl) totalEl.textContent = `${b.total}D`
|
||||||
|
const bonusEl = this.#el.querySelector("#total-bonus")
|
||||||
|
if (bonusEl) bonusEl.textContent = b.help + b.group
|
||||||
|
const freeEl = this.#el.querySelector("#free-successes")
|
||||||
|
if (freeEl) freeEl.textContent = String(this.freeSuccesses)
|
||||||
|
}
|
||||||
|
|
||||||
|
#onInputChange() {
|
||||||
|
this.#updateUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Actions ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
static async #onCancel(event, target) {
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
static async #onRoll(event, target) {
|
||||||
|
const label = this.defense
|
||||||
|
? (this.defense.type === "parade"
|
||||||
|
? game.i18n.localize("VERMINE.defense_parade")
|
||||||
|
: game.i18n.localize("VERMINE.defense_esquive"))
|
||||||
|
: this.label
|
||||||
|
|
||||||
|
await VermineUtils.roll({
|
||||||
|
actor: this.#actor,
|
||||||
|
NoD: this.getPoolBreakdown().total,
|
||||||
|
Reroll: this.rerolls,
|
||||||
|
difficulty: this.#getDifficulty(),
|
||||||
|
handicap: this.#getHandicap(),
|
||||||
|
rollLabel: label,
|
||||||
|
bonusSuccesses: this.freeSuccesses,
|
||||||
|
poolBreakdown: this.getPoolBreakdown(),
|
||||||
|
messageFlags: this.defense ? { "vermine-defense": this.defense } : null
|
||||||
|
})
|
||||||
|
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -359,6 +359,28 @@ export class VermineExchange {
|
|||||||
ui.notifications.warn(game.i18n.localize('VERMINE.error_creature_no_defense'))
|
ui.notifications.warn(game.i18n.localize('VERMINE.error_creature_no_defense'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
const defense = {
|
||||||
|
exchangeId: exchange.id,
|
||||||
|
type,
|
||||||
|
actorId: actor.id,
|
||||||
|
actorUuid: actor.uuid,
|
||||||
|
actorName: actor.name,
|
||||||
|
difficulty: exchange.difficulty,
|
||||||
|
parryLevel: type === 'parade' ? this.#parryLevel(actor) : null
|
||||||
|
}
|
||||||
|
// PNJ : pas de caractéristiques/compétences — la défense utilise la valeur
|
||||||
|
// d'Action (Expérience), difficulté verrouillée.
|
||||||
|
if (actor.type === 'npc') {
|
||||||
|
const { default: NpcRollDialog } = await import('./dialogs/npcRollDialog.mjs')
|
||||||
|
const dialog = await NpcRollDialog.create({
|
||||||
|
actor,
|
||||||
|
rolltype: 'action',
|
||||||
|
locks: { difficulty: exchange.difficulty },
|
||||||
|
defense
|
||||||
|
})
|
||||||
|
if (dialog) dialog.render(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
const { default: RollDialog } = await import('./dialogs/rollDialog.mjs')
|
const { default: RollDialog } = await import('./dialogs/rollDialog.mjs')
|
||||||
const locks = this.#defenseLocks(actor, exchange, type)
|
const locks = this.#defenseLocks(actor, exchange, type)
|
||||||
const dialog = await RollDialog.create({
|
const dialog = await RollDialog.create({
|
||||||
@@ -366,15 +388,7 @@ export class VermineExchange {
|
|||||||
rolltype: 'skill',
|
rolltype: 'skill',
|
||||||
label: locks.skill,
|
label: locks.skill,
|
||||||
locks,
|
locks,
|
||||||
defense: {
|
defense
|
||||||
exchangeId: exchange.id,
|
|
||||||
type,
|
|
||||||
actorId: actor.id,
|
|
||||||
actorUuid: actor.uuid,
|
|
||||||
actorName: actor.name,
|
|
||||||
difficulty: exchange.difficulty,
|
|
||||||
parryLevel: type === 'parade' ? this.#parryLevel(actor) : null
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
if (dialog) dialog.render(true)
|
if (dialog) dialog.render(true)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-4
@@ -30,6 +30,7 @@ export class VermineUtils {
|
|||||||
skillLevel = null,
|
skillLevel = null,
|
||||||
hasSpecialty = false,
|
hasSpecialty = false,
|
||||||
handicap = 0,
|
handicap = 0,
|
||||||
|
bonusSuccesses = 0,
|
||||||
poolBreakdown = null,
|
poolBreakdown = null,
|
||||||
specialtyName = null,
|
specialtyName = null,
|
||||||
weapon = null,
|
weapon = null,
|
||||||
@@ -147,9 +148,9 @@ export class VermineUtils {
|
|||||||
totemBonuses: { ...totemBonus },
|
totemBonuses: { ...totemBonus },
|
||||||
baseNoD: NoD,
|
baseNoD: NoD,
|
||||||
rerolls: Reroll,
|
rerolls: Reroll,
|
||||||
selfControl: self_control
|
selfControl: self_control,
|
||||||
|
bonusSuccesses: bonusSuccesses
|
||||||
};
|
};
|
||||||
|
|
||||||
// Evaluate the roll
|
// Evaluate the roll
|
||||||
await roll.evaluate();
|
await roll.evaluate();
|
||||||
|
|
||||||
@@ -171,6 +172,7 @@ export class VermineUtils {
|
|||||||
skillLevel,
|
skillLevel,
|
||||||
hasSpecialty,
|
hasSpecialty,
|
||||||
handicap,
|
handicap,
|
||||||
|
bonusSuccesses,
|
||||||
poolBreakdown,
|
poolBreakdown,
|
||||||
specialtyName,
|
specialtyName,
|
||||||
weapon,
|
weapon,
|
||||||
@@ -321,6 +323,9 @@ export class VermineUtils {
|
|||||||
const isTotem = die.classList.contains('human') || die.classList.contains('adapted');
|
const isTotem = die.classList.contains('human') || die.classList.contains('adapted');
|
||||||
total += isTotem ? 2 : 1;
|
total += isTotem ? 2 : 1;
|
||||||
});
|
});
|
||||||
|
// Réussites automatiques (ex. bonus de Réaction) : ajoutées au total.
|
||||||
|
const freeSuccesses = parseInt(rollMessage.dataset?.freeSuccesses ?? '0', 10) || 0;
|
||||||
|
total += freeSuccesses;
|
||||||
totalEl.innerText = total;
|
totalEl.innerText = total;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,11 +493,13 @@ export class VermineUtils {
|
|||||||
}
|
}
|
||||||
// Verdict
|
// Verdict
|
||||||
const required = 1 + (param.handicap ?? 0);
|
const required = 1 + (param.handicap ?? 0);
|
||||||
const total = roll._total ?? 0;
|
const bonusSuccesses = param.bonusSuccesses ?? 0;
|
||||||
|
const total = (roll._total ?? 0) + bonusSuccesses;
|
||||||
const verdict = {
|
const verdict = {
|
||||||
success: total >= required,
|
success: total >= required,
|
||||||
total,
|
total,
|
||||||
required
|
required,
|
||||||
|
bonusSuccesses
|
||||||
};
|
};
|
||||||
|
|
||||||
const content = await foundry.applications.handlebars.renderTemplate("systems/vermine2047/templates/roll-message.hbs", { roll, param, diceStats, verdict });
|
const content = await foundry.applications.handlebars.renderTemplate("systems/vermine2047/templates/roll-message.hbs", { roll, param, diceStats, verdict });
|
||||||
|
|||||||
+12
-10
@@ -38,18 +38,20 @@ Hooks.once('init', async function () {
|
|||||||
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;
|
CONFIG.Actor.dataModels.community = models.VermineCommunityData;
|
||||||
|
CONFIG.Actor.dataModels.vehicle = models.VermineVehicleData;
|
||||||
|
|
||||||
// Libellé du type "community" (TYPES.Actor.* du core ne le connaît pas)
|
// Libellés des types "community"/"vehicle" (TYPES.Actor.* du core ne les connaît pas)
|
||||||
CONFIG.Actor.typeLabels ??= {};
|
CONFIG.Actor.typeLabels ??= {};
|
||||||
CONFIG.Actor.typeLabels.community = "VERMINE.type_community";
|
CONFIG.Actor.typeLabels.community = "VERMINE.type_community";
|
||||||
|
CONFIG.Actor.typeLabels.vehicle = "VERMINE.type_vehicle";
|
||||||
Hooks.once('i18nInit', () => {
|
Hooks.once('i18nInit', () => {
|
||||||
CONFIG.Actor.typeLabels.community = "VERMINE.type_community";
|
CONFIG.Actor.typeLabels.community = "VERMINE.type_community";
|
||||||
|
CONFIG.Actor.typeLabels.vehicle = "VERMINE.type_vehicle";
|
||||||
});
|
});
|
||||||
|
|
||||||
CONFIG.Item.dataModels.item = models.VermineItemData;
|
CONFIG.Item.dataModels.item = models.VermineItemData;
|
||||||
CONFIG.Item.dataModels.weapon = models.VermineWeaponData;
|
CONFIG.Item.dataModels.weapon = models.VermineWeaponData;
|
||||||
CONFIG.Item.dataModels.defense = models.VermineDefenseData;
|
CONFIG.Item.dataModels.defense = models.VermineDefenseData;
|
||||||
CONFIG.Item.dataModels.vehicle = models.VermineVehicleData;
|
|
||||||
CONFIG.Item.dataModels.ability = models.VermineAbilityData;
|
CONFIG.Item.dataModels.ability = models.VermineAbilityData;
|
||||||
CONFIG.Item.dataModels.specialty = models.VermineSpecialtyData;
|
CONFIG.Item.dataModels.specialty = models.VermineSpecialtyData;
|
||||||
CONFIG.Item.dataModels.background = models.VermineBackgroundData;
|
CONFIG.Item.dataModels.background = models.VermineBackgroundData;
|
||||||
@@ -80,7 +82,7 @@ Hooks.once('init', async function () {
|
|||||||
// Register sheet application classes (ApplicationV2)
|
// Register sheet application classes (ApplicationV2)
|
||||||
// Unregister core sheets
|
// Unregister core sheets
|
||||||
foundry.documents.collections.Actors.unregisterSheet("core", foundry.applications.sheets.ActorSheetV2, {
|
foundry.documents.collections.Actors.unregisterSheet("core", foundry.applications.sheets.ActorSheetV2, {
|
||||||
types: ["character", "npc", "group", "creature"]
|
types: ["character", "npc", "group", "creature", "community", "vehicle"]
|
||||||
})
|
})
|
||||||
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1?.sheets?.ItemSheet)
|
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1?.sheets?.ItemSheet)
|
||||||
|
|
||||||
@@ -100,6 +102,9 @@ Hooks.once('init', async function () {
|
|||||||
foundry.documents.collections.Actors.registerSheet("vermine2047", sheets.VermineCommunitySheetV2, {
|
foundry.documents.collections.Actors.registerSheet("vermine2047", sheets.VermineCommunitySheetV2, {
|
||||||
types: ["community"], makeDefault: true, label: "VERMINE.Sheet.community"
|
types: ["community"], makeDefault: true, label: "VERMINE.Sheet.community"
|
||||||
})
|
})
|
||||||
|
foundry.documents.collections.Actors.registerSheet("vermine2047", sheets.VermineVehicleSheetV2, {
|
||||||
|
types: ["vehicle"], makeDefault: true, label: "VERMINE.Sheet.vehicle"
|
||||||
|
})
|
||||||
|
|
||||||
// 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, {
|
||||||
@@ -111,9 +116,6 @@ Hooks.once('init', async function () {
|
|||||||
foundry.documents.collections.Items.registerSheet("vermine2047", sheets.VermineDefenseSheetV2, {
|
foundry.documents.collections.Items.registerSheet("vermine2047", sheets.VermineDefenseSheetV2, {
|
||||||
types: ["defense"], makeDefault: true
|
types: ["defense"], makeDefault: true
|
||||||
})
|
})
|
||||||
foundry.documents.collections.Items.registerSheet("vermine2047", sheets.VermineVehicleSheetV2, {
|
|
||||||
types: ["vehicle"], makeDefault: true
|
|
||||||
})
|
|
||||||
foundry.documents.collections.Items.registerSheet("vermine2047", sheets.VermineAbilitySheetV2, {
|
foundry.documents.collections.Items.registerSheet("vermine2047", sheets.VermineAbilitySheetV2, {
|
||||||
types: ["ability"], makeDefault: true
|
types: ["ability"], makeDefault: true
|
||||||
})
|
})
|
||||||
@@ -189,10 +191,8 @@ Hooks.once('init', async function () {
|
|||||||
"systems/vermine2047/templates/actor/appv2/character-stories.hbs",
|
"systems/vermine2047/templates/actor/appv2/character-stories.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/character-combat.hbs",
|
"systems/vermine2047/templates/actor/appv2/character-combat.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/npc-main.hbs",
|
"systems/vermine2047/templates/actor/appv2/npc-main.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/npc-characteristics.hbs",
|
"systems/vermine2047/templates/actor/appv2/npc-traits.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/npc-skills.hbs",
|
|
||||||
"systems/vermine2047/templates/actor/appv2/npc-equipment.hbs",
|
"systems/vermine2047/templates/actor/appv2/npc-equipment.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/npc-threat.hbs",
|
|
||||||
"systems/vermine2047/templates/actor/appv2/npc-combat.hbs",
|
"systems/vermine2047/templates/actor/appv2/npc-combat.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/npc-notes.hbs",
|
"systems/vermine2047/templates/actor/appv2/npc-notes.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/group-main.hbs",
|
"systems/vermine2047/templates/actor/appv2/group-main.hbs",
|
||||||
@@ -208,7 +208,9 @@ Hooks.once('init', async function () {
|
|||||||
"systems/vermine2047/templates/actor/appv2/community-main.hbs",
|
"systems/vermine2047/templates/actor/appv2/community-main.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/community-identity.hbs",
|
"systems/vermine2047/templates/actor/appv2/community-identity.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/community-domains.hbs",
|
"systems/vermine2047/templates/actor/appv2/community-domains.hbs",
|
||||||
"systems/vermine2047/templates/actor/appv2/community-resources.hbs"
|
"systems/vermine2047/templates/actor/appv2/community-resources.hbs",
|
||||||
|
"systems/vermine2047/templates/actor/appv2/vehicle-main.hbs",
|
||||||
|
"systems/vermine2047/templates/actor/appv2/vehicle-specs.hbs"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
+2
-2
@@ -35,13 +35,13 @@
|
|||||||
"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"] }
|
"community": { "htmlFields": ["identity.notes", "location.landmarks", "location.territory", "history.events", "history.relations"] },
|
||||||
|
"vehicle": { "htmlFields": ["identity.notes"] }
|
||||||
},
|
},
|
||||||
"Item": {
|
"Item": {
|
||||||
"item": { "htmlFields": ["description"] },
|
"item": { "htmlFields": ["description"] },
|
||||||
"weapon": { "htmlFields": ["description"] },
|
"weapon": { "htmlFields": ["description"] },
|
||||||
"defense": { "htmlFields": ["description"] },
|
"defense": { "htmlFields": ["description"] },
|
||||||
"vehicle": { "htmlFields": ["description"] },
|
|
||||||
"ability": { "htmlFields": ["description"] },
|
"ability": { "htmlFields": ["description"] },
|
||||||
"specialty": {},
|
"specialty": {},
|
||||||
"background": { "htmlFields": ["description"] },
|
"background": { "htmlFields": ["description"] },
|
||||||
|
|||||||
@@ -86,6 +86,47 @@
|
|||||||
{{/each}}
|
{{/each}}
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="vehicles">
|
||||||
|
<h4>{{localize 'ITEMS.vehicles'}}</h4>
|
||||||
|
<ol class="items-list">
|
||||||
|
<li class="item flexrow items-header">
|
||||||
|
<div class="item-name" style="flex:4;">{{ localize 'IDENTITY.name'}}</div>
|
||||||
|
<div class="item-mobility">{{ localize 'VERMINE.mobility'}}</div>
|
||||||
|
<div class="item-rarity">{{ localize 'VERMINE.rarity'}}</div>
|
||||||
|
<div class="item-reliability">{{ localize 'VERMINE.reliability'}}</div>
|
||||||
|
<div class="item-controls">
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<a class="item-control item-create" data-action="createVehicle" title="Create vehicle"><i class="fas fa-plus"></i></a>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{#each vehicles as |vehicle|}}
|
||||||
|
<li class="item flexrow flex-group-center" data-vehicle-id="{{vehicle.id}}">
|
||||||
|
<div class="item-name" style="flex:4;">
|
||||||
|
<div class="item-image">
|
||||||
|
<a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}"><img
|
||||||
|
src="{{vehicle.img}}" title="{{vehicle.name}}" width="24"
|
||||||
|
height="24" /></a>
|
||||||
|
</div>
|
||||||
|
<a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}" title="Edit Vehicle">{{vehicle.name}}</a>
|
||||||
|
</div>
|
||||||
|
<div><a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}" title="Edit Vehicle">{{vehicle.system.mobility}}</a></div>
|
||||||
|
<div><a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}" title="Edit Vehicle">{{vehicle.system.rarity.value}}</a></div>
|
||||||
|
<div><a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}" title="Edit Vehicle">{{vehicle.system.reliability}}</a></div>
|
||||||
|
<div class="item-controls">
|
||||||
|
{{#if @root.isEditMode}}
|
||||||
|
<a class="item-control item-delete" data-action="deleteVehicle" data-vehicle-id="{{vehicle.id}}" title="Delete Vehicle"><i
|
||||||
|
class="fas fa-trash"></i></a>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{else}}
|
||||||
|
<li class="item flexrow flex-group-center">
|
||||||
|
<span class="empty">{{ localize 'VERMINE.no_vehicles' }}</span>
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
<div class="equipment-notes">
|
<div class="equipment-notes">
|
||||||
<h4>{{ localize 'IDENTITY.notes'}}</h4>
|
<h4>{{ localize 'IDENTITY.notes'}}</h4>
|
||||||
{{formInput systemFields.equipment.fields.description enriched=enrichedEquipmentNotes value=system.equipment.description name="system.equipment.description" toggled=true}}
|
{{formInput systemFields.equipment.fields.description enriched=enrichedEquipmentNotes value=system.equipment.description name="system.equipment.description" toggled=true}}
|
||||||
|
|||||||
@@ -7,31 +7,34 @@
|
|||||||
<div class="item-reliability">{{ localize 'VERMINE.reliability'}}</div>
|
<div class="item-reliability">{{ localize 'VERMINE.reliability'}}</div>
|
||||||
<div class="item-controls">
|
<div class="item-controls">
|
||||||
{{#if isEditMode}}
|
{{#if isEditMode}}
|
||||||
<a class="item-control item-create" data-action="create" title="Create item"
|
<a class="item-control item-create" data-action="createVehicle" title="Create vehicle"><i class="fas fa-plus"></i></a>
|
||||||
data-type="vehicle"><i class="fas fa-plus"></i></a>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{{#each vehicles as |item id|}}
|
{{#each vehicles as |vehicle|}}
|
||||||
<li class="item flexrow flex-group-center" data-item-id="{{item._id}}">
|
<li class="item flexrow flex-group-center" data-vehicle-id="{{vehicle.id}}">
|
||||||
<div class="item-name" style="flex:4;">
|
<div class="item-name" style="flex:4;">
|
||||||
<div class="item-image">
|
<div class="item-image">
|
||||||
<a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" data-roll-type="item"><img
|
<a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}"><img
|
||||||
src="{{item.img}}" title="{{item.name}}" width="24"
|
src="{{vehicle.img}}" title="{{vehicle.name}}" width="24"
|
||||||
height="24" /></a>
|
height="24" /></a>
|
||||||
</div>
|
</div>
|
||||||
<a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">{{item.name}}</a>
|
<a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}" title="Edit Vehicle">{{vehicle.name}}</a>
|
||||||
</div>
|
</div>
|
||||||
<div><a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">{{item.system.mobility}}</a></div>
|
<div><a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}" title="Edit Vehicle">{{vehicle.system.mobility}}</a></div>
|
||||||
<div><a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">{{item.system.rarity.value}}</a></div>
|
<div><a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}" title="Edit Vehicle">{{vehicle.system.rarity.value}}</a></div>
|
||||||
<div><a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">{{item.system.reliability}}</a></div>
|
<div><a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}" title="Edit Vehicle">{{vehicle.system.reliability}}</a></div>
|
||||||
<div class="item-controls">
|
<div class="item-controls">
|
||||||
{{#if @root.isEditMode}}
|
{{#if @root.isEditMode}}
|
||||||
<a class="item-control item-delete" data-action="delete" data-item-id="{{item._id}}" title="Delete Item"><i
|
<a class="item-control item-delete" data-action="deleteVehicle" data-vehicle-id="{{vehicle.id}}" title="Delete Vehicle"><i
|
||||||
class="fas fa-trash"></i></a>
|
class="fas fa-trash"></i></a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
{{else}}
|
||||||
|
<li class="item flexrow flex-group-center">
|
||||||
|
<span class="empty">{{ localize 'VERMINE.no_vehicles' }}</span>
|
||||||
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,116 +0,0 @@
|
|||||||
<div class="tab characteristics sheet-part {{#if @root.tabs.characteristics.active}}active{{/if}}" data-group="sheet" data-tab="characteristics">
|
|
||||||
<h3>{{ localize 'VERMINE.abilities' }}</h3>
|
|
||||||
|
|
||||||
{{!-- Caracteristiques physiques --}}
|
|
||||||
<div class="ability-section">
|
|
||||||
<h4 class="ability-category-header">{{ localize 'VERMINE.ability_category.physical' }}</h4>
|
|
||||||
<div class="grid grid-2col">
|
|
||||||
<div class="ability-item">
|
|
||||||
<label for="system.abilities.vigor.value" class="resource-label rollable" data-type="ability" data-label="vigor">{{ localize 'ABILITIES.vigor.name' }}</label>
|
|
||||||
<div class="ability-control">
|
|
||||||
{{#if isEditMode}}
|
|
||||||
<input type="range" name="system.abilities.vigor.value" value="{{system.abilities.vigor.value}}" min="{{system.abilities.vigor.min}}" max="{{system.abilities.vigor.max}}" data-dtype="Number"/>
|
|
||||||
{{/if}}
|
|
||||||
<span class="ability-value">{{system.abilities.vigor.value}}D</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ability-item">
|
|
||||||
<label for="system.abilities.health.value" class="resource-label rollable" data-type="ability" data-label="health">{{ localize 'ABILITIES.health.name' }}</label>
|
|
||||||
<div class="ability-control">
|
|
||||||
{{#if isEditMode}}
|
|
||||||
<input type="range" name="system.abilities.health.value" value="{{system.abilities.health.value}}" min="{{system.abilities.health.min}}" max="{{system.abilities.health.max}}" data-dtype="Number"/>
|
|
||||||
{{/if}}
|
|
||||||
<span class="ability-value">{{system.abilities.health.value}}D</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{!-- Caracteristiques manuelles --}}
|
|
||||||
<div class="ability-section">
|
|
||||||
<h4 class="ability-category-header">{{ localize 'VERMINE.ability_category.manual' }}</h4>
|
|
||||||
<div class="grid grid-2col">
|
|
||||||
<div class="ability-item">
|
|
||||||
<label for="system.abilities.precision.value" class="resource-label rollable" data-type="ability" data-label="precision">{{ localize 'ABILITIES.precision.name' }}</label>
|
|
||||||
<div class="ability-control">
|
|
||||||
{{#if isEditMode}}
|
|
||||||
<input type="range" name="system.abilities.precision.value" value="{{system.abilities.precision.value}}" min="{{system.abilities.precision.min}}" max="{{system.abilities.precision.max}}" data-dtype="Number"/>
|
|
||||||
{{/if}}
|
|
||||||
<span class="ability-value">{{system.abilities.precision.value}}D</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ability-item">
|
|
||||||
<label for="system.abilities.reflexes.value" class="resource-label rollable" data-type="ability" data-label="reflexes">{{ localize 'ABILITIES.reflexes.name' }}</label>
|
|
||||||
<div class="ability-control">
|
|
||||||
{{#if isEditMode}}
|
|
||||||
<input type="range" name="system.abilities.reflexes.value" value="{{system.abilities.reflexes.value}}" min="{{system.abilities.reflexes.min}}" max="{{system.abilities.reflexes.max}}" data-dtype="Number"/>
|
|
||||||
{{/if}}
|
|
||||||
<span class="ability-value">{{system.abilities.reflexes.value}}D</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{!-- Caracteristiques mentales --}}
|
|
||||||
<div class="ability-section">
|
|
||||||
<h4 class="ability-category-header">{{ localize 'VERMINE.ability_category.mental' }}</h4>
|
|
||||||
<div class="grid grid-2col">
|
|
||||||
<div class="ability-item">
|
|
||||||
<label for="system.abilities.knowledge.value" class="resource-label rollable" data-type="ability" data-label="knowledge">{{ localize 'ABILITIES.knowledge.name' }}</label>
|
|
||||||
<div class="ability-control">
|
|
||||||
{{#if isEditMode}}
|
|
||||||
<input type="range" name="system.abilities.knowledge.value" value="{{system.abilities.knowledge.value}}" min="{{system.abilities.knowledge.min}}" max="{{system.abilities.knowledge.max}}" data-dtype="Number"/>
|
|
||||||
{{/if}}
|
|
||||||
<span class="ability-value">{{system.abilities.knowledge.value}}D</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ability-item">
|
|
||||||
<label for="system.abilities.perception.value" class="resource-label rollable" data-type="ability" data-label="perception">{{ localize 'ABILITIES.perception.name' }}</label>
|
|
||||||
<div class="ability-control">
|
|
||||||
{{#if isEditMode}}
|
|
||||||
<input type="range" name="system.abilities.perception.value" value="{{system.abilities.perception.value}}" min="{{system.abilities.perception.min}}" max="{{system.abilities.perception.max}}" data-dtype="Number"/>
|
|
||||||
{{/if}}
|
|
||||||
<span class="ability-value">{{system.abilities.perception.value}}D</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{!-- Caracteristiques sociales --}}
|
|
||||||
<div class="ability-section">
|
|
||||||
<h4 class="ability-category-header">{{ localize 'VERMINE.ability_category.social' }}</h4>
|
|
||||||
<div class="grid grid-2col">
|
|
||||||
<div class="ability-item">
|
|
||||||
<label for="system.abilities.will.value" class="resource-label rollable" data-type="ability" data-label="will">{{ localize 'ABILITIES.will.name' }}</label>
|
|
||||||
<div class="ability-control">
|
|
||||||
{{#if isEditMode}}
|
|
||||||
<input type="range" name="system.abilities.will.value" value="{{system.abilities.will.value}}" min="{{system.abilities.will.min}}" max="{{system.abilities.will.max}}" data-dtype="Number"/>
|
|
||||||
{{/if}}
|
|
||||||
<span class="ability-value">{{system.abilities.will.value}}D</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ability-item">
|
|
||||||
<label for="system.abilities.empathy.value" class="resource-label rollable" data-type="ability" data-label="empathy">{{ localize 'ABILITIES.empathy.name' }}</label>
|
|
||||||
<div class="ability-control">
|
|
||||||
{{#if isEditMode}}
|
|
||||||
<input type="range" name="system.abilities.empathy.value" value="{{system.abilities.empathy.value}}" min="{{system.abilities.empathy.min}}" max="{{system.abilities.empathy.max}}" data-dtype="Number"/>
|
|
||||||
{{/if}}
|
|
||||||
<span class="ability-value">{{system.abilities.empathy.value}}D</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{!-- Reserves --}}
|
|
||||||
<div class="ability-section">
|
|
||||||
<h4 class="ability-category-header">{{ localize 'VERMINE.reserves' }}</h4>
|
|
||||||
<div class="grid grid-2col">
|
|
||||||
<div class="ability-item">
|
|
||||||
<span>{{ localize 'VERMINE.effort' }} : {{system.attributes.effort.value}}/{{system.attributes.effort.max}}D</span>
|
|
||||||
</div>
|
|
||||||
<div class="ability-item">
|
|
||||||
<span>{{ localize 'VERMINE.self_control' }} : {{system.attributes.self_control.value}}/{{system.attributes.self_control.max}}D</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,56 +1,43 @@
|
|||||||
<div class="tab combat sheet-part {{#if @root.tabs.combat.active}}active{{/if}}" data-group="sheet" data-tab="combat">
|
<div class="tab combat sheet-part {{#if @root.tabs.combat.active}}active{{/if}}" data-group="sheet" data-tab="combat">
|
||||||
<div class="grid grid-2col">
|
|
||||||
<div>
|
|
||||||
<h4 class="align-center">{{ localize "VERMINE.self_control"}}</h4>
|
|
||||||
<p class="align-center">
|
|
||||||
{{#if isEditMode}}
|
|
||||||
<input type="number" name="system.attributes.self_control.value"
|
|
||||||
value="{{ system.attributes.self_control.value }}" data-dtype="Number"
|
|
||||||
min="{{ system.attributes.self_control.min }}"
|
|
||||||
max="{{ system.attributes.self_control.max }}" />
|
|
||||||
{{/if}}
|
|
||||||
{{ system.attributes.self_control.value }} / {{
|
|
||||||
system.attributes.self_control.max }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="align-center">{{ localize "VERMINE.effort"}}</h4>
|
|
||||||
<p class="align-center">
|
|
||||||
{{#if isEditMode}}
|
|
||||||
<input type="number" name="system.attributes.effort.value"
|
|
||||||
value="{{ system.attributes.effort.value }}" data-dtype="Number"
|
|
||||||
min="{{ system.attributes.effort.min }}"
|
|
||||||
max="{{ system.attributes.effort.max }}" />
|
|
||||||
{{/if}}
|
|
||||||
{{ system.attributes.effort.value }} / {{
|
|
||||||
system.attributes.effort.max }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{> "systems/vermine2047/templates/actor/parts/actor-equipped-gear.hbs"}}
|
{{> "systems/vermine2047/templates/actor/parts/actor-equipped-gear.hbs"}}
|
||||||
<h4 class="item-name effect-name flexrow">{{ localize
|
<h4 class="item-name effect-name flexrow">{{ localize "VERMINE.wounds.name"}}</h4>
|
||||||
"VERMINE.wounds.name"}}</h4>
|
|
||||||
<ul class="unstyled">
|
<ul class="unstyled">
|
||||||
<li class="row mdb">{{ localize 'VERMINE.wounds.light'}} ({{
|
<li class="row mdb">{{ localize 'VERMINE.wounds.light'}} ({{
|
||||||
system.minorWound.threshold }})
|
system.minorWound.threshold }})
|
||||||
{{#repeat system.minorWound.max }}
|
<div class="flexrow align-center">
|
||||||
<input type="radio" data-dtype="Number" name="system.minorWound.value"
|
{{#repeat system.minorWound.max 1 "minorwoundmax"}}
|
||||||
value="{{this}}" data-action="clickRadio" data-wound="minorWound"
|
<div class="hexa ability{{#iflteq @minorwoundmax @root.system.minorWound.value }} checked{{/iflteq}}">
|
||||||
{{#ife @root.system.minorWound.value this }}checked="checked"{{/ife}} />
|
<input type="radio" data-dtype="Number" name="system.minorWound.value"
|
||||||
{{/repeat}}</li>
|
value="{{@minorwoundmax}}" data-action="clickRadio" data-wound="minorWound"
|
||||||
|
class="{{#iflteq @minorwoundmax @root.system.minorWound.value }}checked{{/iflteq}}"
|
||||||
|
{{#ife @minorwoundmax @root.system.minorWound.value }}checked="checked"{{/ife}} />
|
||||||
|
</div>
|
||||||
|
{{/repeat}}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
<li class="row mdb">{{ localize 'VERMINE.wounds.heavy'}} ({{
|
<li class="row mdb">{{ localize 'VERMINE.wounds.heavy'}} ({{
|
||||||
system.majorWound.threshold }})
|
system.majorWound.threshold }})
|
||||||
{{#repeat system.majorWound.max }}
|
<div class="flexrow align-center">
|
||||||
<input type="radio" name="system.majorWound.value" value="{{this}}" data-action="clickRadio" data-wound="majorWound"
|
{{#repeat system.majorWound.max 1 "majorwoundmax"}}
|
||||||
{{#ife @root.system.majorWound.value this }}checked="checked"{{/ife}} />
|
<div class="hexa ability{{#iflteq @majorwoundmax @root.system.majorWound.value }} checked{{/iflteq}}">
|
||||||
{{/repeat}}
|
<input type="radio" name="system.majorWound.value" value="{{@majorwoundmax}}" data-action="clickRadio" data-wound="majorWound"
|
||||||
|
class="{{#iflteq @majorwoundmax @root.system.majorWound.value }}checked{{/iflteq}}"
|
||||||
|
{{#ife @majorwoundmax @root.system.majorWound.value }}checked="checked"{{/ife}} />
|
||||||
|
</div>
|
||||||
|
{{/repeat}}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="row mdb">{{ localize 'VERMINE.wounds.deadly'}} ({{
|
<li class="row mdb">{{ localize 'VERMINE.wounds.deadly'}} ({{
|
||||||
system.deadlyWound.threshold }})
|
system.deadlyWound.threshold }})
|
||||||
{{#repeat system.deadlyWound.max }}
|
<div class="flexrow align-center">
|
||||||
<input type="radio" name="system.deadlyWound.value" value="{{this}}" data-action="clickRadio" data-wound="deadlyWound"
|
{{#repeat system.deadlyWound.max 1 "deadlywoundmax"}}
|
||||||
{{#ife @root.system.deadlyWound.value this }}checked="checked"{{/ife}} />
|
<div class="hexa ability{{#iflteq @deadlywoundmax @root.system.deadlyWound.value }} checked{{/iflteq}}">
|
||||||
{{/repeat}}
|
<input type="radio" name="system.deadlyWound.value" value="{{@deadlywoundmax}}" data-action="clickRadio" data-wound="deadlyWound"
|
||||||
|
class="{{#iflteq @deadlywoundmax @root.system.deadlyWound.value }}checked{{/iflteq}}"
|
||||||
|
{{#ife @deadlywoundmax @root.system.deadlyWound.value }}checked="checked"{{/ife}} />
|
||||||
|
</div>
|
||||||
|
{{/repeat}}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h4 class="item-name effect-name flexrow">{{ localize "UI.effects.name"}}</h4>
|
<h4 class="item-name effect-name flexrow">{{ localize "UI.effects.name"}}</h4>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
{{!-- Niveaux de Menace, Experience, Role --}}
|
{{!-- Critères : Menace, Expérience, Rôle --}}
|
||||||
<div class="resources grid grid-3col">
|
<div class="resources grid grid-3col">
|
||||||
<div class="resource flex-group-center">
|
<div class="resource flex-group-center">
|
||||||
<label for="system.threat.value" class="resource-label">{{ localize 'ADVERSITY.threat' }}</label>
|
<label for="system.threat.value" class="resource-label">{{ localize 'ADVERSITY.threat' }}</label>
|
||||||
@@ -29,12 +29,12 @@
|
|||||||
<select name="system.threat.value" id="system.threat.value" data-dtype="Number">
|
<select name="system.threat.value" id="system.threat.value" data-dtype="Number">
|
||||||
{{#each npcThreatOptions}}
|
{{#each npcThreatOptions}}
|
||||||
<option value="{{@key}}" {{#ife @key @root.system.threat.value}}selected{{/ife}}>
|
<option value="{{@key}}" {{#ife @key @root.system.threat.value}}selected{{/ife}}>
|
||||||
{{localize label}} ({{@key}})
|
{{localize label}}
|
||||||
</option>
|
</option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</select>
|
</select>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span>{{system.threat.value}}</span>
|
<span>{{ system.threat.value }}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -46,12 +46,12 @@
|
|||||||
<select name="system.experience.value" id="system.experience.value" data-dtype="Number">
|
<select name="system.experience.value" id="system.experience.value" data-dtype="Number">
|
||||||
{{#each npcExperienceOptions}}
|
{{#each npcExperienceOptions}}
|
||||||
<option value="{{@key}}" {{#ife @key @root.system.experience.value}}selected{{/ife}}>
|
<option value="{{@key}}" {{#ife @key @root.system.experience.value}}selected{{/ife}}>
|
||||||
{{localize label}} ({{@key}})
|
{{localize label}}
|
||||||
</option>
|
</option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</select>
|
</select>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span>{{system.experience.value}}</span>
|
<span>{{ system.experience.value }}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -63,19 +63,39 @@
|
|||||||
<select name="system.role.value" id="system.role.value" data-dtype="Number">
|
<select name="system.role.value" id="system.role.value" data-dtype="Number">
|
||||||
{{#each npcRoleOptions}}
|
{{#each npcRoleOptions}}
|
||||||
<option value="{{@key}}" {{#ife @key @root.system.role.value}}selected{{/ife}}>
|
<option value="{{@key}}" {{#ife @key @root.system.role.value}}selected{{/ife}}>
|
||||||
{{localize label}} ({{@key}})
|
{{localize label}}
|
||||||
</option>
|
</option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</select>
|
</select>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span>{{system.role.value}}</span>
|
<span>{{ system.role.value }}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{!-- Totem et Origine --}}
|
{{!-- Profil : âge, activité, totem, origine --}}
|
||||||
<div class="resources grid grid-2col">
|
<div class="resources grid grid-4col npc-profile-grid">
|
||||||
|
<div class="resource flex-group-center">
|
||||||
|
<label for="system.identity.age" class="resource-label">{{ localize 'IDENTITY.age' }}</label>
|
||||||
|
<div class="resource-content">
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="text" name="system.identity.age" id="system.identity.age" value="{{system.identity.age}}" data-dtype="String"/>
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.identity.age}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="resource flex-group-center">
|
||||||
|
<label for="system.identity.profile" class="resource-label">{{ localize 'IDENTITY.profile' }}</label>
|
||||||
|
<div class="resource-content">
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="text" name="system.identity.profile" id="system.identity.profile" value="{{system.identity.profile}}" data-dtype="String" placeholder="{{ localize 'PROFILE' }}"/>
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.identity.profile}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="resource flex-group-center">
|
<div class="resource flex-group-center">
|
||||||
<label for="system.identity.totem" class="resource-label">{{ localize 'TOTEM' }}</label>
|
<label for="system.identity.totem" class="resource-label">{{ localize 'TOTEM' }}</label>
|
||||||
<div class="resource-content">
|
<div class="resource-content">
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
<div class="tab skills sheet-part {{#if @root.tabs.skills.active}}active{{/if}}" data-group="sheet" data-tab="skills">
|
|
||||||
<h3>{{ localize 'VERMINE.skills' }}</h3>
|
|
||||||
|
|
||||||
{{!-- Category Selector --}}
|
|
||||||
<div class="skill-category-selector">
|
|
||||||
<label>{{ localize 'VERMINE.preferred_category' }}:</label>
|
|
||||||
{{#if isEditMode}}
|
|
||||||
<select name="system.skill_categories.preferred" data-dtype="String">
|
|
||||||
<option value="">{{ localize 'NONE' }}</option>
|
|
||||||
{{#each system.skill_categories as |category key|}}
|
|
||||||
{{#ife key "preferred"}}{{else}}
|
|
||||||
<option value="{{key}}" {{#ife key ../system.skill_categories.preferred}}selected{{/ife}}>
|
|
||||||
{{localize category.label}}
|
|
||||||
</option>
|
|
||||||
{{/ife}}
|
|
||||||
{{/each}}
|
|
||||||
</select>
|
|
||||||
{{else}}
|
|
||||||
<span>{{system.skill_categories.preferred}}</span>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{!-- Skills Grid by Category --}}
|
|
||||||
<div class="skills-container">
|
|
||||||
{{#each config.skillCategories as |category key|}}
|
|
||||||
{{#ife key "preferred"}}{{else}}
|
|
||||||
{{> "systems/vermine2047/templates/actor/parts/npc-skill-category.hbs"
|
|
||||||
categoryKey=key
|
|
||||||
categoryLabel=(concat "VERMINE.skill_category." key)
|
|
||||||
skills=@root.system.skills
|
|
||||||
}}
|
|
||||||
{{/ife}}
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{!-- Free Skills text field --}}
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="system.freeSkills">{{ localize 'ADVERSITY.skills' }}</label>
|
|
||||||
{{#if isEditMode}}
|
|
||||||
<input type="text" name="system.freeSkills" value="{{system.freeSkills}}" data-dtype="String" placeholder="{{ localize 'ADVERSITY.skills_placeholder' }}"/>
|
|
||||||
{{else}}
|
|
||||||
<span>{{system.freeSkills}}</span>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
<div class="tab threat sheet-part {{#if @root.tabs.threat.active}}active{{/if}}" data-group="sheet" data-tab="threat">
|
|
||||||
<h3>{{ localize 'ADVERSITY.threat_details' }}</h3>
|
|
||||||
<div class="grid grid-3col">
|
|
||||||
{{!-- Menace --}}
|
|
||||||
<div class="card npc-card">
|
|
||||||
<h4 class="align-center"><i class="fas fa-exclamation-triangle"></i> {{ localize 'ADVERSITY.threat' }}</h4>
|
|
||||||
<ul class="unstyled">
|
|
||||||
<li>
|
|
||||||
<strong>{{ localize 'ADVERSITY.attack' }}:</strong>
|
|
||||||
{{ npcThreatLevel "attack" system.threat.value }}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>{{ localize 'ADVERSITY.vigor' }}:</strong>
|
|
||||||
{{ npcThreatLevel "vigor" system.threat.value }}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>{{ localize 'ADVERSITY.wounds' }}:</strong>
|
|
||||||
{{ npcThreatLevel "minorWound" system.threat.value }} /
|
|
||||||
{{ npcThreatLevel "majorWound" system.threat.value }} /
|
|
||||||
{{ npcThreatLevel "deadlyWound" system.threat.value }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{!-- Experience --}}
|
|
||||||
<div class="card npc-card">
|
|
||||||
<h4 class="align-center"><i class="fas fa-star"></i> {{ localize 'ADVERSITY.experience' }}</h4>
|
|
||||||
<ul class="unstyled">
|
|
||||||
<li>
|
|
||||||
<strong>{{ localize 'ADVERSITY.action' }}:</strong>
|
|
||||||
{{ npcExperienceLevel "action" system.experience.value }}D
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>{{ localize 'ADVERSITY.specialties' }}:</strong>
|
|
||||||
{{ npcExperienceLevel "specialties" system.experience.value }}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>{{ localize 'ADVERSITY.rerolls' }}:</strong>
|
|
||||||
{{ npcExperienceLevel "rerolls" system.experience.value }}D
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>{{ localize 'ADVERSITY.contact' }}:</strong>
|
|
||||||
{{ npcExperienceLevel "contact" system.experience.value }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{!-- Role --}}
|
|
||||||
<div class="card npc-card">
|
|
||||||
<h4 class="align-center"><i class="fas fa-users"></i> {{ localize 'ADVERSITY.role' }}</h4>
|
|
||||||
<ul class="unstyled">
|
|
||||||
<li>
|
|
||||||
<strong>{{ localize 'ADVERSITY.reaction' }}:</strong>
|
|
||||||
{{ npcRoleLevel "reaction" system.role.value }} + {{ npcRoleLevel "reaction_bonus" system.role.value }}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>{{ localize 'ADVERSITY.pools' }}:</strong>
|
|
||||||
{{ npcRoleLevel "pools" system.role.value }}D
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>{{ localize 'ADVERSITY.gear' }}:</strong>
|
|
||||||
{{ npcRoleLevel "gear" system.role.value }}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>{{ localize 'ADVERSITY.gear_hindrance' }}:</strong>
|
|
||||||
{{ npcRoleLevel "gear_hindrance" system.role.value }}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>{{ localize 'ADVERSITY.protection' }}:</strong>
|
|
||||||
{{ npcRoleLevel "protection" system.role.value }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<div class="tab traits sheet-part {{#if @root.tabs.traits.active}}active{{/if}}" data-group="sheet" data-tab="traits">
|
||||||
|
<h3>{{ localize 'VERMINE.traits' }}</h3>
|
||||||
|
<div class="grid grid-3col">
|
||||||
|
|
||||||
|
{{!-- Menace --}}
|
||||||
|
<div class="card npc-card">
|
||||||
|
<h4 class="align-center"><i class="fas fa-exclamation-triangle"></i> {{ localize 'ADVERSITY.threat' }}</h4>
|
||||||
|
<ul class="unstyled npc-trait-list">
|
||||||
|
<li>
|
||||||
|
<strong>{{ localize 'ADVERSITY.attack' }}:</strong>
|
||||||
|
<span class="trait-value">{{ system.computed.attack }}D</span>
|
||||||
|
<a class="rollable npc-roll-btn" data-type="attack" title="{{ localize 'VERMINE.roll' }}"><i class="fas fa-dice-d10"></i></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>{{ localize 'ADVERSITY.vigor' }}:</strong>
|
||||||
|
<span class="trait-value">{{ system.computed.vigor }}D</span>
|
||||||
|
</li>
|
||||||
|
<li class="npc-wounds">
|
||||||
|
<strong>{{ localize 'ADVERSITY.wounds' }}:</strong>
|
||||||
|
<span class="wound-cat"><span class="wound-boxes">{{#repeat system.minorWound.max}}<i class="fas fa-circle"></i>{{/repeat}}</span> {{ system.minorWound.threshold }}</span>
|
||||||
|
<span class="wound-cat"><span class="wound-boxes">{{#repeat system.majorWound.max}}<i class="fas fa-circle"></i>{{/repeat}}</span> {{ system.majorWound.threshold }}</span>
|
||||||
|
<span class="wound-cat"><span class="wound-boxes">{{#repeat system.deadlyWound.max}}<i class="fas fa-circle"></i>{{/repeat}}</span> {{ system.deadlyWound.threshold }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Expérience --}}
|
||||||
|
<div class="card npc-card">
|
||||||
|
<h4 class="align-center"><i class="fas fa-star"></i> {{ localize 'ADVERSITY.experience' }}</h4>
|
||||||
|
<ul class="unstyled npc-trait-list">
|
||||||
|
<li>
|
||||||
|
<strong>{{ localize 'ADVERSITY.action' }}:</strong>
|
||||||
|
<span class="trait-value">{{ system.computed.action }}D</span>
|
||||||
|
<a class="rollable npc-roll-btn" data-type="action" title="{{ localize 'VERMINE.roll' }}"><i class="fas fa-dice-d10"></i></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>{{ localize 'ADVERSITY.specialties' }}:</strong>
|
||||||
|
<span class="trait-value">{{ system.computed.specialties }}D</span>
|
||||||
|
<a class="rollable npc-roll-btn" data-type="specialty" title="{{ localize 'VERMINE.roll' }}"><i class="fas fa-dice-d10"></i></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>{{ localize 'ADVERSITY.rerolls' }}:</strong>
|
||||||
|
<span class="trait-value">{{ system.computed.rerolls }}D</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>{{ localize 'ADVERSITY.contact' }}:</strong>
|
||||||
|
<span class="trait-value">{{ system.computed.contact }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Rôle --}}
|
||||||
|
<div class="card npc-card">
|
||||||
|
<h4 class="align-center"><i class="fas fa-users"></i> {{ localize 'ADVERSITY.role' }}</h4>
|
||||||
|
<ul class="unstyled npc-trait-list">
|
||||||
|
<li>
|
||||||
|
<strong>{{ localize 'ADVERSITY.reaction' }}:</strong>
|
||||||
|
<span class="trait-value">{{ system.computed.reaction }}D{{#if system.computed.reactionBonus}} +{{ system.computed.reactionBonus }}{{/if}}</span>
|
||||||
|
<a class="rollable npc-roll-btn" data-type="reaction" title="{{ localize 'VERMINE.roll' }}"><i class="fas fa-dice-d10"></i></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>{{ localize 'ADVERSITY.pools' }}:</strong>
|
||||||
|
<span class="trait-value">{{ system.computed.pools }}D</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>{{ localize 'ADVERSITY.gear' }}:</strong>
|
||||||
|
<span class="trait-value">{{ system.computed.gear }}{{#if system.computed.gearHindrance}} ({{ system.computed.gearHindrance }}){{/if}}</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>{{ localize 'ADVERSITY.protection' }}:</strong>
|
||||||
|
<span class="trait-value">{{ system.computed.protection }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Spécialités (description libre) --}}
|
||||||
|
<div class="form-group npc-free-skills">
|
||||||
|
<label for="system.freeSkills">{{ localize 'ADVERSITY.skills' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="text" name="system.freeSkills" id="system.freeSkills" value="{{system.freeSkills}}" data-dtype="String" placeholder="{{ localize 'ADVERSITY.skills_placeholder' }}"/>
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.freeSkills}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
<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="sheet-header">
|
||||||
|
<img class="profile-img" src="{{actor.img}}" data-action="editImage" data-edit="img" title="{{actor.name}}"
|
||||||
|
height="100" width="100" />
|
||||||
|
<div class="header-fields">
|
||||||
|
<div class="resources grid grid-4col">
|
||||||
|
<h1 class="charname grid-span-2">
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input name="name" type="text" value="{{actor.name}}" placeholder="{{ localize 'VERMINE.vehicle' }}" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{actor.name}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</h1>
|
||||||
|
<div class="resource flex-group-center grid-span-1">
|
||||||
|
<label for="system.kind" class="resource-label">{{ localize 'VERMINE.kind' }}</label>
|
||||||
|
<div class="resource-content">
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<select name="system.kind" id="system.kind" data-dtype="String">
|
||||||
|
<option value="vehicle" {{#ife system.kind "vehicle"}}selected{{/ife}}>{{ localize "VERMINE.kind_vehicle" }}</option>
|
||||||
|
<option value="mount" {{#ife system.kind "mount"}}selected{{/ife}}>{{ localize "VERMINE.kind_mount" }}</option>
|
||||||
|
</select>
|
||||||
|
{{else}}
|
||||||
|
<span>{{#ife system.kind "mount"}}{{ localize "VERMINE.kind_mount" }}{{else}}{{ localize "VERMINE.kind_vehicle" }}{{/ife}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="resource flex-group-center grid-span-1">
|
||||||
|
<label for="system.reliability" class="resource-label">{{ localize 'VERMINE.reliability' }}</label>
|
||||||
|
<div class="resource-content">
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="number" name="system.reliability" id="system.reliability" value="{{system.reliability}}"
|
||||||
|
data-dtype="Number" min="1" max="10" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.reliability}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="resources grid grid-4col">
|
||||||
|
<div class="resource flex-group-center grid-span-1">
|
||||||
|
<label for="system.rarity.value" class="resource-label">{{ localize 'VERMINE.rarity' }}</label>
|
||||||
|
<div class="resource-content">
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="number" name="system.rarity.value" id="system.rarity.value" value="{{system.rarity.value}}"
|
||||||
|
data-dtype="Number" min="1" max="10" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.rarity.value}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="resource flex-group-center grid-span-1">
|
||||||
|
<label for="system.mobility" class="resource-label">{{ localize 'VERMINE.mobility' }}</label>
|
||||||
|
<div class="resource-content">
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="number" name="system.mobility" id="system.mobility" value="{{system.mobility}}"
|
||||||
|
data-dtype="Number" min="0" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.mobility}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="resource flex-group-center grid-span-2">
|
||||||
|
<label for="system.distance" class="resource-label">{{ localize 'VERMINE.distance' }}</label>
|
||||||
|
<div class="resource-content">
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="number" name="system.distance" id="system.distance" value="{{system.distance}}"
|
||||||
|
data-dtype="Number" min="0" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.distance}}</span>
|
||||||
|
{{/if}}
|
||||||
|
<span> km</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{{#if resolvedOwner}}
|
||||||
|
<div class="vehicle-owner">
|
||||||
|
<span class="label">{{ localize 'VERMINE.owner' }}:</span>
|
||||||
|
<span class="value">{{ resolvedOwner.name }}</span>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
<div class="tab specs sheet-part {{#if @root.tabs.specs.active}}active{{/if}}" data-group="sheet" data-tab="specs">
|
||||||
|
<section class="vehicle-section">
|
||||||
|
<h3>{{ localize 'VERMINE.vehicle_specs' }}</h3>
|
||||||
|
<div class="grid grid-2col">
|
||||||
|
<div class="resource align-center flexcol">
|
||||||
|
<label class="resource-label">{{ localize 'VERMINE.distance' }}</label>
|
||||||
|
<div class="flexrow align-center">
|
||||||
|
<div class="hexa"><input type="number" name="system.distance" value="{{system.distance}}" data-dtype="Number" /></div>
|
||||||
|
<span class="unit">km</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="resource align-center flexcol">
|
||||||
|
<label class="resource-label">{{ localize 'VERMINE.speed' }}</label>
|
||||||
|
<div class="flexrow align-center">
|
||||||
|
<div class="hexa"><input type="number" name="system.speed.cruise" value="{{system.speed.cruise}}" data-dtype="Number" /></div>
|
||||||
|
<span>/</span>
|
||||||
|
<div class="hexa"><input type="number" name="system.speed.top" value="{{system.speed.top}}" data-dtype="Number" /></div>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="system.speed.topDuration" value="{{system.speed.topDuration}}"
|
||||||
|
placeholder="{{ localize 'VERMINE.speed_duration_ph' }}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-2col">
|
||||||
|
<div class="resource align-center flexcol">
|
||||||
|
<label class="resource-label">{{ localize 'VERMINE.effort_reserve' }}</label>
|
||||||
|
<div class="flexrow align-center">
|
||||||
|
<div class="hexa"><input type="number" name="system.effortReserve.value" value="{{system.effortReserve.value}}" data-dtype="Number" /></div>
|
||||||
|
<span>/</span>
|
||||||
|
<div class="hexa"><input type="number" name="system.effortReserve.max" value="{{system.effortReserve.max}}" data-dtype="Number" /></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="resource align-center flexcol">
|
||||||
|
<label class="resource-label">{{ localize 'VERMINE.mobility' }}</label>
|
||||||
|
<div class="hexa"><input type="number" name="system.mobility" value="{{system.mobility}}" data-dtype="Number" /></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="maintenance">
|
||||||
|
<label class="resource-label">{{ localize 'VERMINE.maintenance' }}</label>
|
||||||
|
<div class="flexrow flex-wrap">
|
||||||
|
{{#each maintenanceSkills}}
|
||||||
|
<label class="flexrow align-center">
|
||||||
|
<input type="checkbox" name="system.maintenance" value="{{ this.key }}" {{#if this.checked}}checked{{/if}} />
|
||||||
|
<span>{{ this.label }}</span>
|
||||||
|
</label>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="vehicle-section">
|
||||||
|
<h3>{{ localize 'IDENTITY.profile' }}</h3>
|
||||||
|
<div class="grid grid-2col">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.identity.profile">{{ localize 'IDENTITY.profile' }}</label>
|
||||||
|
{{#if isEditMode}}
|
||||||
|
<input type="text" name="system.identity.profile" value="{{system.identity.profile}}" data-dtype="String" />
|
||||||
|
{{else}}
|
||||||
|
<span>{{system.identity.profile}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.identity.origin">{{ localize 'IDENTITY.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 'IDENTITY.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>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system.identity.notes">{{ localize 'IDENTITY.notes' }}</label>
|
||||||
|
{{formInput systemFields.identity.fields.notes enriched=enrichedNotes value=system.identity.notes name="system.identity.notes" toggled=true}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
@@ -5,27 +5,34 @@
|
|||||||
<div class="item-rarity">{{ localize 'VERMINE.rarity'}}</div>
|
<div class="item-rarity">{{ localize 'VERMINE.rarity'}}</div>
|
||||||
<div class="item-reliability">{{ localize 'VERMINE.reliability'}}</div>
|
<div class="item-reliability">{{ localize 'VERMINE.reliability'}}</div>
|
||||||
<div class="item-controls">
|
<div class="item-controls">
|
||||||
<a class="item-control item-create" title="Create item"
|
{{#if @root.isEditMode}}
|
||||||
data-type="vehicle" data-action="create"><i class="fas fa-plus"></i></a>
|
<a class="item-control item-create" data-action="createVehicle" title="Create vehicle"><i class="fas fa-plus"></i></a>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{{#each vehicles as |item id|}}
|
{{#each vehicles as |vehicle|}}
|
||||||
<li class="item flexrow flex-group-center" data-item-id="{{item._id}}">
|
<li class="item flexrow flex-group-center" data-vehicle-id="{{vehicle.id}}">
|
||||||
<div class="item-name" style="flex:4;">
|
<div class="item-name" style="flex:4;">
|
||||||
<div class="item-image">
|
<div class="item-image">
|
||||||
<a data-action="edit"><img
|
<a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}"><img
|
||||||
src="{{item.img}}" title="{{item.name}}" width="24"
|
src="{{vehicle.img}}" title="{{vehicle.name}}" width="24"
|
||||||
height="24" /></a>
|
height="24" /></a>
|
||||||
</div>
|
</div>
|
||||||
<a data-action="edit" title="Edit Item">{{item.name}}</a>
|
<a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}" title="Edit Vehicle">{{vehicle.name}}</a>
|
||||||
</div>
|
</div>
|
||||||
<div><a data-action="edit" title="Edit Item">{{item.system.mobility}}</a></div>
|
<div><a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}" title="Edit Vehicle">{{vehicle.system.mobility}}</a></div>
|
||||||
<div><a data-action="edit" title="Edit Item">{{item.system.rarity.value}}</a></div>
|
<div><a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}" title="Edit Vehicle">{{vehicle.system.rarity.value}}</a></div>
|
||||||
<div><a data-action="edit" title="Edit Item">{{item.system.reliability}}</a></div>
|
<div><a class="item-control item-edit" data-action="editVehicle" data-vehicle-id="{{vehicle.id}}" title="Edit Vehicle">{{vehicle.system.reliability}}</a></div>
|
||||||
<div class="item-controls">
|
<div class="item-controls">
|
||||||
<a data-action="delete" title="Delete Item"><i
|
{{#if @root.isEditMode}}
|
||||||
|
<a class="item-control item-delete" data-action="deleteVehicle" data-vehicle-id="{{vehicle.id}}" title="Delete Vehicle"><i
|
||||||
class="fas fa-trash"></i></a>
|
class="fas fa-trash"></i></a>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
{{else}}
|
||||||
|
<li class="item flexrow flex-group-center">
|
||||||
|
<span class="empty">{{ localize 'VERMINE.no_vehicles' }}</span>
|
||||||
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ol>
|
</ol>
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
<div class="roll-dialog-content">
|
||||||
|
<!-- HIDDEN DATA -->
|
||||||
|
<input type="hidden" name="speakerId" value="{{ speakerId }}" />
|
||||||
|
|
||||||
|
<h4 class="npc-roll-label">{{ rollLabel }}</h4>
|
||||||
|
|
||||||
|
<div class="npc-roll-pool">
|
||||||
|
<span class="label">{{localize 'VERMINE.dice_pool'}}:</span>
|
||||||
|
<span class="pool-value">{{ pool }}D</span>
|
||||||
|
{{#if freeSuccesses}}
|
||||||
|
<span class="free-successes-badge"><i class="fas fa-star"></i> +{{ freeSuccesses }} {{localize 'VERMINE.auto_successes'}}</span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if rerolls}}
|
||||||
|
<span class="rerolls-badge">{{localize 'ADVERSITY.rerolls'}}: {{ rerolls }}D</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dice-pool">
|
||||||
|
|
||||||
|
<!-- DIFFICULTY -->
|
||||||
|
<div class="flexcol difficulty-section">
|
||||||
|
<label class="label" for="difficulty">{{localize 'VERMINE.difficulty'}}</label>
|
||||||
|
<select
|
||||||
|
class="info-value"
|
||||||
|
data-roll="true"
|
||||||
|
data-dtype="String"
|
||||||
|
type="number"
|
||||||
|
name="difficulty"
|
||||||
|
id="difficulty"
|
||||||
|
min="3"
|
||||||
|
max="10"
|
||||||
|
{{#if lockedDifficulty}}disabled{{/if}}
|
||||||
|
>
|
||||||
|
{{#each difficultyOptions}}
|
||||||
|
<option value="{{ this.difficulty }}" {{#ife @root.defaultDifficulty this.difficulty}}selected{{/ife}}>
|
||||||
|
{{ this.label }} ({{ this.difficulty }})
|
||||||
|
</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- HANDICAP -->
|
||||||
|
<div class="flexcol handicap-section">
|
||||||
|
<label class="label" for="handicap">{{localize 'VERMINE.handicap'}}</label>
|
||||||
|
<select
|
||||||
|
class="info-value"
|
||||||
|
data-roll="true"
|
||||||
|
data-dtype="String"
|
||||||
|
type="number"
|
||||||
|
name="handicap"
|
||||||
|
id="handicap"
|
||||||
|
min="0"
|
||||||
|
max="2"
|
||||||
|
>
|
||||||
|
<option value="1" selected>{{localize 'VERMINE.none'}}</option>
|
||||||
|
<option value="2">(I)</option>
|
||||||
|
<option value="3">(II)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- BONUSES -->
|
||||||
|
<details class="bonuses-section">
|
||||||
|
<summary class="flexrow">
|
||||||
|
<span class="label">{{localize 'VERMINE.bonuses'}}</span>
|
||||||
|
<span class="bonus-count">+<span id="total-bonus">0</span>D</span>
|
||||||
|
</summary>
|
||||||
|
<div class="grid grid-2col bonus-grid">
|
||||||
|
|
||||||
|
<div class="flexrow bonus-item">
|
||||||
|
<input type="checkbox" data-roll="true" name="helped" id="helped" value="1" />
|
||||||
|
<label class="label" for="helped">{{localize 'VERMINE.help'}} (+1D)</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flexrow bonus-item">
|
||||||
|
<label class="label" for="group">{{localize 'VERMINE.group'}}</label>
|
||||||
|
<input type="number" data-roll="true" class="numeric-entry" style="text-align: center;"
|
||||||
|
name="group" id="group" min="0" max="5" value="0" />
|
||||||
|
<span>D</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<!-- TOTAL -->
|
||||||
|
<div class="flexrow total-section">
|
||||||
|
<label class="label">{{localize 'VERMINE.total'}}:</label>
|
||||||
|
<span id="dice-pool-total" class="total-value">0D</span>
|
||||||
|
{{#if freeSuccesses}}
|
||||||
|
<span class="totem-selector">
|
||||||
|
(+<span id="free-successes">{{ freeSuccesses }}</span> {{localize 'VERMINE.auto_successes'}})
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="sheet-footer flexrow">
|
||||||
|
<button type="button" data-action="cancel">
|
||||||
|
<i class="fas fa-times"></i> {{localize "VERMINE.cancel"}}
|
||||||
|
</button>
|
||||||
|
<button type="button" data-action="roll">
|
||||||
|
<i class="fas fa-dice-d10"></i> {{localize "VERMINE.roll"}}
|
||||||
|
</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
<form class="{{cssClass}}" autocomplete="off">
|
|
||||||
{{> "systems/vermine2047/templates/item/chatCards/parts/base.hbs"}}
|
|
||||||
|
|
||||||
{{!-- Vehicle specific content --}}
|
|
||||||
<div class="grid grid-2col">
|
|
||||||
{{#if item.system.mobility}}
|
|
||||||
<div class="resource flexrow">
|
|
||||||
<span class="resource-label">{{ localize 'VERMINE.mobility' }}:</span>
|
|
||||||
<span>{{item.system.mobility}}</span>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if item.system.quantity}}
|
|
||||||
<div class="resource flexrow">
|
|
||||||
<span class="resource-label">{{ localize 'VERMINE.qty' }}:</span>
|
|
||||||
<span>{{item.system.quantity}}</span>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if item.system.weight}}
|
|
||||||
<div class="resource flexrow">
|
|
||||||
<span class="resource-label">{{ localize 'VERMINE.weight' }}:</span>
|
|
||||||
<span>{{item.system.weight}}</span>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if item.system.rarity.value}}
|
|
||||||
<div class="resource flexrow">
|
|
||||||
<span class="resource-label">{{ localize 'VERMINE.rarity' }}:</span>
|
|
||||||
<span>
|
|
||||||
{{#repeat item.system.rarity.value 1 "i"}}
|
|
||||||
{{romanNumber i}}
|
|
||||||
{{/repeat}}
|
|
||||||
{{#ifgt item.system.rarity.handicap 0}}
|
|
||||||
({{romanNumber item.system.rarity.handicap}})
|
|
||||||
{{/ifgt}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if item.system.damages.value}}
|
|
||||||
<div class="resource flexrow">
|
|
||||||
<span class="resource-label">{{ localize 'VERMINE.damages' }}:</span>
|
|
||||||
<span class="damage-indicator">
|
|
||||||
{{getDamagesData item.system.damages "state"}}
|
|
||||||
{{#ifgt item.system.damages.value 1}}
|
|
||||||
({{item.system.damages.value}})
|
|
||||||
{{/ifgt}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if item.system.reliability}}
|
|
||||||
<div class="resource flexrow">
|
|
||||||
<span class="resource-label">{{ localize 'VERMINE.reliability' }}:</span>
|
|
||||||
<span>{{item.system.reliability}}</span>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if item.system.traits}}
|
|
||||||
<div class="resource flexcol">
|
|
||||||
<span class="resource-label">{{ localize 'VERMINE.traits' }}:</span>
|
|
||||||
<ul class="unstyled">
|
|
||||||
{{#each item.system.traits as |trait key|}}
|
|
||||||
{{#if trait}}
|
|
||||||
<li>
|
|
||||||
<strong>{{localize (lookup (lookup ../config.traits key) "name")}}</strong>:
|
|
||||||
{{localize (lookup (lookup ../config.traits key) "description")}}
|
|
||||||
</li>
|
|
||||||
{{/if}}
|
|
||||||
{{/each}}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if item.system.description}}
|
|
||||||
<div class="resource flexcol full-width">
|
|
||||||
<p>{{{item.system.description}}}</p>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
<div class="{{cssClass}}">
|
|
||||||
{{> "systems/vermine2047/templates/item/partials/header.hbs"}}
|
|
||||||
|
|
||||||
<section class="sheet-body">
|
|
||||||
{{> "systems/vermine2047/templates/item/partials/traits.hbs"}}
|
|
||||||
|
|
||||||
<section class="vehicle-fields">
|
|
||||||
<h3>{{ localize "VERMINE.vehicle_specs" }}</h3>
|
|
||||||
|
|
||||||
<div class="flexrow">
|
|
||||||
<div class="resource align-center flexcol">
|
|
||||||
<label class="resource-label">{{ localize "VERMINE.kind" }}</label>
|
|
||||||
<select name="system.kind" data-dtype="String">
|
|
||||||
<option value="vehicle" {{#ife system.kind "vehicle"}}selected{{/ife}}>{{ localize "VERMINE.kind_vehicle" }}</option>
|
|
||||||
<option value="mount" {{#ife system.kind "mount"}}selected{{/ife}}>{{ localize "VERMINE.kind_mount" }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="resource align-center flexcol">
|
|
||||||
<label class="resource-label">{{ localize "VERMINE.distance" }}</label>
|
|
||||||
<div class="hexa"><input type="number" name="system.distance" value="{{system.distance}}" data-dtype="Number" /></div>
|
|
||||||
<span class="unit">km</span>
|
|
||||||
</div>
|
|
||||||
<div class="resource align-center flexcol">
|
|
||||||
<label class="resource-label">{{ localize "VERMINE.speed" }}</label>
|
|
||||||
<div class="flexrow align-center">
|
|
||||||
<input type="number" name="system.speed.cruise" value="{{system.speed.cruise}}" data-dtype="Number" />
|
|
||||||
<span>/</span>
|
|
||||||
<input type="number" name="system.speed.top" value="{{system.speed.top}}" data-dtype="Number" />
|
|
||||||
</div>
|
|
||||||
<input type="text" name="system.speed.topDuration" value="{{system.speed.topDuration}}" placeholder="{{ localize 'VERMINE.speed_duration_ph' }}" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flexrow">
|
|
||||||
<div class="resource align-center flexcol">
|
|
||||||
<label class="resource-label">{{ localize "VERMINE.effort_reserve" }}</label>
|
|
||||||
<div class="flexrow align-center">
|
|
||||||
<div class="hexa"><input type="number" name="system.effortReserve.value" value="{{system.effortReserve.value}}" data-dtype="Number" /></div>
|
|
||||||
<span>/</span>
|
|
||||||
<div class="hexa"><input type="number" name="system.effortReserve.max" value="{{system.effortReserve.max}}" data-dtype="Number" /></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="resource align-center flexcol">
|
|
||||||
<label class="resource-label">{{ localize "VERMINE.mobility" }}</label>
|
|
||||||
<div class="hexa"><input type="number" name="system.mobility" value="{{system.mobility}}" data-dtype="Number" /></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="maintenance">
|
|
||||||
<label class="resource-label">{{ localize "VERMINE.maintenance" }}</label>
|
|
||||||
<div class="flexrow flex-wrap">
|
|
||||||
{{#each maintenanceSkills}}
|
|
||||||
<label class="flexrow align-center">
|
|
||||||
<input type="checkbox" name="system.maintenance" value="{{ this.key }}" {{#if this.checked}}checked{{/if}} />
|
|
||||||
<span>{{ this.label }}</span>
|
|
||||||
</label>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{{> "systems/vermine2047/templates/item/partials/physicalItems.hbs"}}
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="vermine-roll-message">
|
<div class="vermine-roll-message" data-free-successes="{{verdict.bonusSuccesses}}">
|
||||||
{{!-- Verdict --}}
|
{{!-- Verdict --}}
|
||||||
<div class="roll-verdict {{#if verdict.success}}success{{else}}failure{{/if}}">
|
<div class="roll-verdict {{#if verdict.success}}success{{else}}failure{{/if}}">
|
||||||
{{#if verdict.success}}
|
{{#if verdict.success}}
|
||||||
@@ -75,6 +75,12 @@
|
|||||||
<span class="context-value">+{{param.handicap}}</span>
|
<span class="context-value">+{{param.handicap}}</span>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{#if verdict.bonusSuccesses}}
|
||||||
|
<div class="context-item">
|
||||||
|
<span class="context-label">{{localize "VERMINE.auto_successes"}}</span>
|
||||||
|
<span class="context-value">+{{verdict.bonusSuccesses}}</span>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
{{#if param.specialtyName}}
|
{{#if param.specialtyName}}
|
||||||
<div class="context-item">
|
<div class="context-item">
|
||||||
<span class="context-label">{{localize "VERMINE.specialty"}}</span>
|
<span class="context-label">{{localize "VERMINE.specialty"}}</span>
|
||||||
@@ -208,7 +214,7 @@
|
|||||||
<div class="roll-total flexrow">
|
<div class="roll-total flexrow">
|
||||||
<div class="flexcol">
|
<div class="flexcol">
|
||||||
<h4>{{localize "VERMINE.success_count"}}:</h4>
|
<h4>{{localize "VERMINE.success_count"}}:</h4>
|
||||||
<span id="total">{{roll._total}}</span>
|
<span id="total">{{verdict.total}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flexcol">
|
<div class="flexcol">
|
||||||
<h4>{{localize "VERMINE.success_required"}}:</h4>
|
<h4>{{localize "VERMINE.success_required"}}:</h4>
|
||||||
|
|||||||
Reference in New Issue
Block a user