Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad4daf0b00 | ||
|
|
c96e8d69d7 | ||
|
|
282fb2794a | ||
|
|
46b9512256 | ||
|
|
8316112741 | ||
|
|
75f39551f8 | ||
|
|
ef76ae1116 |
+2
-1
@@ -34,7 +34,8 @@ module.exports = {
|
||||
Dialog: 'readonly',
|
||||
foundry: 'readonly',
|
||||
Handlebars: 'readonly',
|
||||
renderTemplate: 'readonly'
|
||||
renderTemplate: 'readonly',
|
||||
fromUuid: 'readonly'
|
||||
},
|
||||
rules: {
|
||||
// Possible Problems
|
||||
|
||||
@@ -376,6 +376,13 @@
|
||||
"evolution_dice": "Evolution dice",
|
||||
"open_experience_phase": "Experience phase",
|
||||
"open_learning": "Learning",
|
||||
"validate_phase": "Validate phase",
|
||||
"validate_phase_done": "Experience phase validated: learning limits reset.",
|
||||
"error_not_editable": "You do not have permission to modify this element.",
|
||||
"vehicle_assign": "Attach vehicle",
|
||||
"vehicle_assign_confirm": "This vehicle already belongs to \"{group}\". Attach it to this group?",
|
||||
"vehicle_assign_failed": "Could not attach this vehicle to the group.",
|
||||
"vehicle_import_failed": "Could not import this vehicle from the compendium.",
|
||||
"learning_limits": "Learning limits (per phase)",
|
||||
"learned_skill": "Skill",
|
||||
"learned_specialty": "Specialty",
|
||||
|
||||
@@ -359,6 +359,13 @@
|
||||
"evolution_dice": "Dés d'Évolution",
|
||||
"open_experience_phase": "Phase d'Expérience",
|
||||
"open_learning": "Apprentissage",
|
||||
"validate_phase": "Valider la phase",
|
||||
"validate_phase_done": "Phase d'Expérience validée : limites d'apprentissage réinitialisées.",
|
||||
"error_not_editable": "Vous n'avez pas la permission de modifier cet élément.",
|
||||
"vehicle_assign": "Attacher le véhicule",
|
||||
"vehicle_assign_confirm": "Ce véhicule appartient déjà à « {group} ». L'attacher à ce Groupe ?",
|
||||
"vehicle_assign_failed": "Impossible d'attacher ce véhicule au Groupe.",
|
||||
"vehicle_import_failed": "Impossible d'importer ce véhicule depuis le compendium.",
|
||||
"learning_limits": "Limites d'apprentissage (par phase)",
|
||||
"learned_skill": "Compétence",
|
||||
"learned_specialty": "Spécialité",
|
||||
|
||||
@@ -368,6 +368,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Fiche de Groupe : mêmes dés de Réserve cliquables (AppV2).
|
||||
&.group div.hexa {
|
||||
.hexa-style();
|
||||
.transition();
|
||||
margin: 0.2rem;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
.hexa-style(rgba(255, 255, 255, 0.425), rgba(0, 0, 0, 0.288));
|
||||
}
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.checked {
|
||||
.hexa-style(rgb(0, 0, 0), rgba(0, 0, 0, 0.288));
|
||||
&:hover { .hexa-style(rgb(43, 43, 43), rgba(0, 0, 0, 0.288)); }
|
||||
}
|
||||
}
|
||||
|
||||
.sheet-header-toggle {
|
||||
text-align: right;
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
font-family: "DistressBlack", sans-serif;
|
||||
text-transform: uppercase;
|
||||
font-size: @font-size-12;
|
||||
color: @color-amber;
|
||||
// Brun foncé lisible sur le fond beige de la fiche (le jaune était illisible).
|
||||
color: @color-chitin-dark;
|
||||
margin: 8px 0 4px;
|
||||
text-align: left;
|
||||
border-bottom: none;
|
||||
|
||||
@@ -18,6 +18,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle « Chaman » de l'onglet Totem : ne pas étirer sur toute la largeur.
|
||||
.chaman-toggle {
|
||||
width: fit-content;
|
||||
margin: 0.5rem auto;
|
||||
gap: 0.5rem;
|
||||
|
||||
label {
|
||||
font-family: "DistressBlack", sans-serif;
|
||||
text-transform: uppercase;
|
||||
font-size: @font-size-12;
|
||||
color: @theme-color-dark;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
div.minor-totems {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -311,6 +311,11 @@ export default class VermineBaseActorSheet extends HandlebarsApplicationMixin(fo
|
||||
static #onClickRadioHexa(event, target) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
// Évite une erreur de permission pour un utilisateur non éditeur.
|
||||
if (!this.isEditable) {
|
||||
ui.notifications.warn(game.i18n.localize("VERMINE.error_not_editable"))
|
||||
return
|
||||
}
|
||||
const input = target
|
||||
const update = {}
|
||||
let current = this.document
|
||||
|
||||
@@ -9,7 +9,8 @@ export default class VermineCharacterSheetV2 extends VermineBaseActorSheet {
|
||||
actions: {
|
||||
addSpecialty: VermineCharacterSheetV2.#onAddSpecialty,
|
||||
openExperiencePhase: VermineCharacterSheetV2.#onOpenExperiencePhase,
|
||||
openLearning: VermineCharacterSheetV2.#onOpenLearning
|
||||
openLearning: VermineCharacterSheetV2.#onOpenLearning,
|
||||
validatePhase: VermineCharacterSheetV2.#onValidatePhase
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,4 +126,11 @@ export default class VermineCharacterSheetV2 extends VermineBaseActorSheet {
|
||||
const dialog = await LearningDialog.create({ actorId: this.document.id })
|
||||
if (dialog) dialog.render(true)
|
||||
}
|
||||
|
||||
/** Valide la phase d'Expérience courante et réinitialise les limites. */
|
||||
static async #onValidatePhase() {
|
||||
const { VermineExperience } = await import("../../system/experience.mjs")
|
||||
await VermineExperience.resetPhaseLimits(this.document)
|
||||
ui.notifications.info(game.i18n.localize("VERMINE.validate_phase_done"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ export default class VermineGroupSheetV2 extends VermineBaseActorSheet {
|
||||
addObjective: VermineGroupSheetV2.#onAddObjective,
|
||||
createTotemAbility: VermineGroupSheetV2.#onCreateTotemAbility,
|
||||
openLearning: VermineGroupSheetV2.#onOpenLearning,
|
||||
openExperiencePhase: VermineGroupSheetV2.#onOpenExperiencePhase
|
||||
openExperiencePhase: VermineGroupSheetV2.#onOpenExperiencePhase,
|
||||
validatePhase: VermineGroupSheetV2.#onValidatePhase
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +110,50 @@ export default class VermineGroupSheetV2 extends VermineBaseActorSheet {
|
||||
return game.actors.filter(a => a.type === "vehicle" && a.system.ownerId === this.document.id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Dépôt d'un acteur Véhicule sur la fiche : lie le véhicule au Groupe
|
||||
* (system.ownerId) au lieu de le dupliquer, puis affiche la liste.
|
||||
* Gère les dépôts depuis un compendium (copie importée dans le monde)
|
||||
* et demande confirmation si le véhicule appartient déjà à un autre Groupe.
|
||||
* @override
|
||||
*/
|
||||
async _onDropActor(event, data) {
|
||||
let actor = data instanceof foundry.abstract.Document ? data : await fromUuid(data.uuid)
|
||||
if (actor?.type !== "vehicle") {
|
||||
return super._onDropActor?.(event, data)
|
||||
}
|
||||
// Véhicule issu d'un compendium : importer une copie dans le monde.
|
||||
if (actor.compendium) {
|
||||
try {
|
||||
const copy = await game.actors.importFromCompendium(actor.compendium, actor._id, { renderSheet: false })
|
||||
if (!copy) return
|
||||
actor = copy
|
||||
} catch {
|
||||
ui.notifications.warn(game.i18n.localize("VERMINE.vehicle_import_failed"))
|
||||
return
|
||||
}
|
||||
}
|
||||
// Véhicule déjà rattaché à un autre Groupe : confirmation avant transfert.
|
||||
const currentOwner = actor.system?.ownerId
|
||||
if (currentOwner && currentOwner !== this.document.id) {
|
||||
const other = game.actors.get(currentOwner)
|
||||
const content = game.i18n.localize("VERMINE.vehicle_assign_confirm").replace("{group}", other?.name ?? currentOwner)
|
||||
const confirmed = await Dialog.confirm({
|
||||
title: game.i18n.localize("VERMINE.vehicle_assign"),
|
||||
content,
|
||||
defaultYes: false
|
||||
})
|
||||
if (!confirmed) return
|
||||
}
|
||||
try {
|
||||
await actor.update({ "system.ownerId": this.document.id })
|
||||
} catch {
|
||||
ui.notifications.warn(game.i18n.localize("VERMINE.vehicle_assign_failed"))
|
||||
return
|
||||
}
|
||||
this.render()
|
||||
}
|
||||
|
||||
// Actions : délégation aux applications AppV1 existantes pour TotemPicker/ActorPicker
|
||||
static async #onChooseTotem(event, target) {
|
||||
const { TotemPicker } = await import("../../system/applications.mjs")
|
||||
@@ -172,4 +217,11 @@ export default class VermineGroupSheetV2 extends VermineBaseActorSheet {
|
||||
const dialog = await GroupLearningDialog.create({ actorId: this.document.id })
|
||||
if (dialog) dialog.render(true)
|
||||
}
|
||||
|
||||
/** Valide la phase d'Expérience courante du Groupe et réinitialise les limites. */
|
||||
static async #onValidatePhase() {
|
||||
const { VermineExperience } = await import("../../system/experience.mjs")
|
||||
await VermineExperience.resetPhaseLimits(this.document)
|
||||
ui.notifications.info(game.i18n.localize("VERMINE.validate_phase_done"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +182,9 @@ export default class LearningDialog extends HandlebarsApplicationMixin(foundry.a
|
||||
}
|
||||
|
||||
#getSpecialtyName() {
|
||||
return this.#el.querySelector("#specialty-name")?.value?.trim() || game.i18n.localize("ITEMS.new_specialty");
|
||||
// Le dialogue peut avoir été fermé pendant le jet (this.#el null).
|
||||
const el = this.#el?.querySelector("#specialty-name");
|
||||
return el?.value?.trim() || game.i18n.localize("ITEMS.new_specialty");
|
||||
}
|
||||
|
||||
#compute() {
|
||||
|
||||
@@ -213,4 +213,24 @@ export class VermineExperience {
|
||||
const preferred = actor.system?.skill_categories?.preferred
|
||||
return Boolean(category && preferred && category === preferred)
|
||||
}
|
||||
|
||||
/**
|
||||
* Réinitialise les limites d'apprentissage (learned.*) de la phase
|
||||
* courante, pour un personnage ou un Groupe, sans toucher au compteur
|
||||
* de phase (avancé uniquement par le dialogue d'attribution du MJ).
|
||||
* @param {foundry.abstract.Document} actor personnage ou Groupe
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async resetPhaseLimits(actor) {
|
||||
const ex = actor.system?.experience
|
||||
if (!ex) return
|
||||
const update = {}
|
||||
if (ex.learned && typeof ex.learned === "object") {
|
||||
for (const key of Object.keys(ex.learned)) {
|
||||
if (key === "phase") continue
|
||||
update[`system.experience.learned.${key}`] = false
|
||||
}
|
||||
}
|
||||
if (Object.keys(update).length) await actor.update(update)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
<button type="button" data-action="openLearning">
|
||||
<i class="fas fa-graduation-cap"></i> {{ localize 'VERMINE.open_learning' }}
|
||||
</button>
|
||||
<button type="button" data-action="validatePhase">
|
||||
<i class="fas fa-check"></i> {{ localize 'VERMINE.validate_phase' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<section class="exp-rewards">
|
||||
|
||||
@@ -1,45 +1,50 @@
|
||||
<div class="tab gear sheet-part {{#if @root.tabs.gear.active}}active{{/if}}" data-group="sheet" data-tab="gear">
|
||||
<div class="grid grid-2col">
|
||||
<div>
|
||||
<ol class="items-list">
|
||||
<li class="item flexrow items-header">
|
||||
<div class="item-name" style="flex:4;">{{ localize 'IDENTITY.name'}}</div>
|
||||
<div class="item-quantity">{{ localize 'VERMINE.qty'}}</div>
|
||||
<div class="item-weight">{{ localize 'VERMINE.weight'}}</div>
|
||||
<div class="weapons">
|
||||
<h4>{{localize 'ITEMS.weapons'}}</h4>
|
||||
{{> "systems/vermine2047/templates/actor/parts/actor-weapons.hbs"}}
|
||||
</div>
|
||||
<div class="protections">
|
||||
<h4>{{localize 'ITEMS.defenses'}}</h4>
|
||||
{{> "systems/vermine2047/templates/actor/parts/actor-defenses.hbs"}}
|
||||
</div>
|
||||
<div class="objects">
|
||||
<h4>{{localize 'ITEMS.items'}}</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-quantity">{{ localize 'VERMINE.qty'}}</div>
|
||||
<div class="item-weight">{{ localize 'VERMINE.weight'}}</div>
|
||||
<div class="item-controls">
|
||||
{{#if isEditMode}}
|
||||
<a class="item-control item-create" data-action="create" data-type="item" title="Create item"><i class="fas fa-plus"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</li>
|
||||
{{#each gear as |item id|}}
|
||||
<li class="item flexrow flex-group-center" data-item-id="{{item._id}}">
|
||||
<div class="item-name" style="flex:4;">
|
||||
<div class="item-image">
|
||||
<a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" data-roll-type="item"><img src="{{item.img}}" title="{{item.name}}" width="24" height="24"/></a>
|
||||
</div>
|
||||
<a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">{{item.name}}</a>
|
||||
</div>
|
||||
<div><a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">{{item.system.quantity}}</a></div>
|
||||
<div><a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">{{item.system.weight}}</a></div>
|
||||
<div class="item-controls">
|
||||
{{#if isEditMode}}
|
||||
<a class="item-control item-create" data-action="create" data-type="item" title="Create item"><i class="fas fa-plus"></i></a>
|
||||
{{#if @root.isEditMode}}
|
||||
<a class="item-control item-delete" data-action="delete" data-item-id="{{item._id}}" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</li>
|
||||
{{#each gear as |item id|}}
|
||||
<li class="item flexrow flex-group-center" data-item-id="{{item._id}}">
|
||||
<div class="item-name" style="flex:4;">
|
||||
<div class="item-image">
|
||||
<a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" data-roll-type="item"><img src="{{item.img}}" title="{{item.name}}" width="24" height="24"/></a>
|
||||
</div>
|
||||
<a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">{{item.name}}</a>
|
||||
</div>
|
||||
<div><a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">{{item.system.quantity}}</a></div>
|
||||
<div><a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">{{item.system.weight}}</a></div>
|
||||
<div class="item-controls">
|
||||
{{#if @root.isEditMode}}
|
||||
<a class="item-control item-delete" data-action="delete" data-item-id="{{item._id}}" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
</div>
|
||||
<div>
|
||||
<h4>{{ localize 'IDENTITY.notes'}}</h4>
|
||||
{{formInput systemFields.equipment.fields.description enriched=enrichedEquipmentNotes value=system.equipment.description name="system.equipment.description" toggled=true}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</ol>
|
||||
</div>
|
||||
<div class="vehicles">
|
||||
<h4>{{localize 'ITEMS.vehicles'}}</h4>
|
||||
{{> "systems/vermine2047/templates/actor/group/group-vehicles.hbs"}}
|
||||
</div>
|
||||
<div class="equipment-notes">
|
||||
<h4>{{ localize 'IDENTITY.notes'}}</h4>
|
||||
{{formInput systemFields.equipment.fields.description enriched=enrichedEquipmentNotes value=system.equipment.description name="system.equipment.description" toggled=true}}
|
||||
</div>
|
||||
<h4>{{localize 'ITEMS.weapons'}}</h4>
|
||||
{{> "systems/vermine2047/templates/actor/parts/actor-weapons.hbs"}}
|
||||
<h4>{{localize 'ITEMS.defenses'}}</h4>
|
||||
{{> "systems/vermine2047/templates/actor/parts/actor-defenses.hbs"}}
|
||||
<h4>{{localize 'ITEMS.vehicles'}}</h4>
|
||||
{{> "systems/vermine2047/templates/actor/group/group-vehicles.hbs"}}
|
||||
</div>
|
||||
|
||||
@@ -13,6 +13,13 @@
|
||||
{{/if}}
|
||||
<span>/ {{system.reserve.max}}D</span>
|
||||
</div>
|
||||
<div class="reserve-dice flexrow">
|
||||
{{#repeat system.reserve.max 1 "d"}}
|
||||
<div class="hexa {{#iflteq @d @root.system.reserve.value}}checked{{/iflteq}}">
|
||||
<input type="radio" data-dtype="Number" name="system.reserve.value" value="{{@d}}" data-action="clickRadio" />
|
||||
</div>
|
||||
{{/repeat}}
|
||||
</div>
|
||||
<div class="morale-control flexrow flex-group-center">
|
||||
<label>{{ localize 'VERMINE.morale' }}:</label>
|
||||
{{#if isEditMode}}
|
||||
@@ -46,6 +53,7 @@
|
||||
<div class="group-experience-actions flexrow flex-group-center">
|
||||
<button type="button" data-action="openLearning"><i class="fas fa-graduation-cap"></i> {{ localize 'VERMINE.open_learning' }}</button>
|
||||
<button type="button" data-action="openExperiencePhase"><i class="fas fa-star"></i> {{ localize 'VERMINE.experience_phase' }}</button>
|
||||
<button type="button" data-action="validatePhase"><i class="fas fa-check"></i> {{ localize 'VERMINE.validate_phase' }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user