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:
@@ -5,11 +5,11 @@ export { default as VermineNpcSheetV2 } from "./npc-sheet.mjs"
|
||||
export { default as VermineGroupSheetV2 } from "./group-sheet.mjs"
|
||||
export { default as VermineCreatureSheetV2 } from "./creature-sheet.mjs"
|
||||
export { default as VermineCommunitySheetV2 } from "./community-sheet.mjs"
|
||||
export { default as VermineVehicleSheetV2 } from "./vehicle-sheet.mjs"
|
||||
export {
|
||||
VermineItemSheetV2,
|
||||
VermineWeaponSheetV2,
|
||||
VermineDefenseSheetV2,
|
||||
VermineVehicleSheetV2,
|
||||
VermineAbilitySheetV2,
|
||||
VermineSpecialtySheetV2,
|
||||
VermineBackgroundSheetV2,
|
||||
|
||||
@@ -32,6 +32,9 @@ export default class VermineBaseActorSheet extends HandlebarsApplicationMixin(fo
|
||||
delete: VermineBaseActorSheet.#onItemDelete,
|
||||
toggleEquip: VermineBaseActorSheet.#onToggleEquip,
|
||||
create: VermineBaseActorSheet.#onItemCreate,
|
||||
createVehicle: VermineBaseActorSheet.#onCreateVehicle,
|
||||
editVehicle: VermineBaseActorSheet.#onEditVehicle,
|
||||
deleteVehicle: VermineBaseActorSheet.#onDeleteVehicle,
|
||||
roll: VermineBaseActorSheet.#onRollItem,
|
||||
attack: VermineBaseActorSheet.#onAttack,
|
||||
clickRadio: VermineBaseActorSheet.#onClickRadioHexa,
|
||||
@@ -229,11 +232,46 @@ export default class VermineBaseActorSheet extends HandlebarsApplicationMixin(fo
|
||||
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) {
|
||||
const id = target.closest("[data-item-id]")?.dataset?.itemId
|
||||
if (!id) return
|
||||
const item = this.document.items.get(id)
|
||||
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) {
|
||||
const { default: RollDialog } = await import("../../system/dialogs/rollDialog.mjs")
|
||||
const dialog = await RollDialog.create({
|
||||
|
||||
@@ -71,7 +71,7 @@ export default class VermineCharacterSheetV2 extends VermineBaseActorSheet {
|
||||
context.gear = doc.itemTypes.item
|
||||
context.weapons = doc.itemTypes.weapon
|
||||
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
|
||||
case "stories":
|
||||
context.tab = context.tabs.stories
|
||||
|
||||
@@ -80,10 +80,11 @@ export default class VermineGroupSheetV2 extends VermineBaseActorSheet {
|
||||
context.gear = doc.itemTypes.item
|
||||
context.weapons = doc.itemTypes.weapon
|
||||
context.defenses = doc.itemTypes.defense
|
||||
context.vehicles = this.#getOwnedVehicles()
|
||||
break
|
||||
case "road":
|
||||
context.tab = context.tabs.road
|
||||
context.vehicles = doc.itemTypes.vehicle
|
||||
context.vehicles = this.#getOwnedVehicles()
|
||||
break
|
||||
case "reserve":
|
||||
context.tab = context.tabs.reserve
|
||||
@@ -92,6 +93,11 @@ export default class VermineGroupSheetV2 extends VermineBaseActorSheet {
|
||||
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
|
||||
static async #onChooseTotem(event, target) {
|
||||
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: [""] } }
|
||||
}
|
||||
|
||||
// ── 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é ──────────────────────────────────────────────────────────
|
||||
export class VermineAbilitySheetV2 extends VermineBaseItemSheet {
|
||||
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 {
|
||||
|
||||
// La fiche PNJ s'ouvre en mode édition : caractéristiques, compétences et
|
||||
// niveaux se règlent dès l'ouverture (le mode jeu reste accessible via le toggle).
|
||||
// La fiche PNJ s'ouvre en mode édition : profil et niveaux (Menace,
|
||||
// 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
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
@@ -15,22 +16,18 @@ export default class VermineNpcSheetV2 extends VermineBaseActorSheet {
|
||||
static PARTS = {
|
||||
main: { template: "systems/vermine2047/templates/actor/appv2/npc-main.hbs", scrollable: [""] },
|
||||
tabs: { template: "templates/generic/tab-navigation.hbs" },
|
||||
characteristics: { template: "systems/vermine2047/templates/actor/appv2/npc-characteristics.hbs", scrollable: [""] },
|
||||
skills: { template: "systems/vermine2047/templates/actor/appv2/npc-skills.hbs", scrollable: [""] },
|
||||
traits: { template: "systems/vermine2047/templates/actor/appv2/npc-traits.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: [""] },
|
||||
notes: { template: "systems/vermine2047/templates/actor/appv2/npc-notes.hbs", scrollable: [""] }
|
||||
}
|
||||
|
||||
tabGroups = { sheet: "characteristics" }
|
||||
tabGroups = { sheet: "traits" }
|
||||
|
||||
#getTabs() {
|
||||
const tabs = {
|
||||
characteristics: { id: "characteristics", group: "sheet", icon: "fas fa-dice", label: "VERMINE.abilities" },
|
||||
skills: { id: "skills", group: "sheet", icon: "fas fa-brain", label: "VERMINE.skills" },
|
||||
traits: { id: "traits", group: "sheet", icon: "fas fa-dice", label: "VERMINE.traits" },
|
||||
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" },
|
||||
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.originOptions = CONFIG.VERMINE.origins
|
||||
break
|
||||
case "characteristics":
|
||||
context.tab = context.tabs.characteristics
|
||||
break
|
||||
case "skills":
|
||||
context.tab = context.tabs.skills
|
||||
case "traits":
|
||||
context.tab = context.tabs.traits
|
||||
break
|
||||
case "equipment":
|
||||
context.tab = context.tabs.equipment
|
||||
context.weapons = doc.itemTypes.weapon
|
||||
context.defenses = doc.itemTypes.defense
|
||||
break
|
||||
case "threat":
|
||||
context.tab = context.tabs.threat
|
||||
break
|
||||
case "combat":
|
||||
context.tab = context.tabs.combat
|
||||
context.equippedWeapons = doc.itemTypes.weapon.filter(i => i.system.equipped)
|
||||
@@ -84,4 +75,27 @@ export default class VermineNpcSheetV2 extends VermineBaseActorSheet {
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user