refacto: harmonisation du système avec les règles Hamalron JDR
Corrections majeures : - HamalronTirageTarot extends Roll (évaluation des jets fonctionnelle) - Correction du nom de classe Langue (HamalronFaction -> HamalronLangue) - Création du template tab-navigation.hbs manquant - Type acteur 'character' -> 'personnage' dans _preCreate Types d'items corrigés (anglais -> français) : - weapon -> arme, armor -> armure, equipment -> equipement - Suppression des types inexistants (deal, malefica, ritual, perk) Modèles : - cost -> cout (armure, equipement) - Tarot : default -> initial - Sortilege : LOCALIZATION_PREFIXES corrigé - Constantes CHOICE_ADVANTAGES_DISADVANTAGES et ATTACK_MODIFIERS ajoutées - ATTACK_MODIFIERS supprimé (plus utilisé) Templates alignés sur les modèles réels : - enemy-trait : suppression champs manquants (trauma, stats, domain...) - personnage-equipement : champs alignés sur arme/armure/equipement - personnage-sortileges : suppression domain/level/rituals - enemy-main : suppression stats et flavorText - base-actor : suppression mortality, toChat limité aux tarots Jets de compétence : - Égalité = réussite (>= au lieu de >, conforme aux règles p.155) - Comparaison robuste des cartes de succès (via String()) Le Mat : - Les autres joueurs peuvent renouveler leur main (règle p.151) findTarotItem : recherche dans game.items puis compendiums await manquants ajoutés sur saveDeckState() AGENTS.md créé
This commit is contained in:
@@ -0,0 +1,55 @@
|
|||||||
|
# AGENTS.md — fvtt-hamalron
|
||||||
|
|
||||||
|
Foundry VTT **game system** (not a module) for Hamalron JDR, a French-language TTRPG.
|
||||||
|
|
||||||
|
System ID: `fvtt-hamalron` · Compatible FVTT v13–v14 · Language: French only (`lang/fr.json`)
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
| Layer | Location | Notes |
|
||||||
|
|-------|----------|-------|
|
||||||
|
| Entrypoint | `fvtt-hamalron.mjs` | ES module, loaded via `system.json` → `esmodules` |
|
||||||
|
| Models | `module/models/*.mjs` | 12 data models (personnage, pnj, arme, armure, competence, equipement, faction, langue, peuple, region, sortilege, tarot) |
|
||||||
|
| Documents | `module/documents/*.mjs` | Actor, Item, ChatMessage, Roll (tirage-tarot) |
|
||||||
|
| Sheets | `module/applications/sheets/*.mjs` | App V2 sheets, one per item/actor type + base classes |
|
||||||
|
| Config | `module/config/system.mjs` | Exposes `globalThis.SYSTEM` with all game constants |
|
||||||
|
| Styles | `styles/*.less` → compiled to `css/fvtt-hamalron.css` |
|
||||||
|
| Templates | `templates/*.hbs` | Handlebars partials |
|
||||||
|
| Tarot deck | `module/applications/tarot-deck-manager.mjs` | Singleton manager, Fisher-Yates shuffle, GM-only |
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Build CSS (LESS → CSS)
|
||||||
|
npx gulp css # one-shot compile
|
||||||
|
npx gulp # default: compile + watch
|
||||||
|
```
|
||||||
|
|
||||||
|
## Linting
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npx eslint .
|
||||||
|
```
|
||||||
|
|
||||||
|
Uses ESLint 9 flat config (`eslint.config.mjs`) with Prettier + JSDoc plugins. Rules: `semi: never`, `quotes: double`, `indent: 2`.
|
||||||
|
|
||||||
|
## Compendium pack management
|
||||||
|
|
||||||
|
Pack data lives in `packs-system/hamalron-items/` (LevelDB format, used by Foundry at runtime).
|
||||||
|
|
||||||
|
The repo has `@foundryvtt/foundryvtt-cli` and tools for YAML ↔ LevelDB conversion:
|
||||||
|
- `tools/packCompendiumsToDist.mjs` — compiles from `packs_src/` (YAML) to `packs/` (.db)
|
||||||
|
- `tools/unpackCompendiumsFromDist.mjs` — extracts from `packs/` (.db) to `packs_src/` (YAML)
|
||||||
|
|
||||||
|
**Note:** `package.json` scripts reference `pushLDBtoYML`/`pullYMLtoLDB` — these files don't exist yet. Use the tool files directly: `node tools/packCompendiumsToDist.mjs` / `node tools/unpackCompendiumsFromDist.mjs` after creating the source directories.
|
||||||
|
|
||||||
|
## Gotchas
|
||||||
|
|
||||||
|
- **No tests** exist anywhere.
|
||||||
|
- **No CI/CD** (no `.github/` directory).
|
||||||
|
- **No typechecking** — plain JS with JSDoc comments.
|
||||||
|
- The `system.json` `hotReload` config references `lang/en.json` and `acks.css` — these files do **not** exist. Only `lang/fr.json` is shipped.
|
||||||
|
- All actor/item sheets are App V2 (unregistered core V1 sheets).
|
||||||
|
- Tarot deck state is persisted in a world-scope setting `tarotDeckState` (not a `Cards` document).
|
||||||
|
- Socket event handler is a no-op (`module/socket.mjs`).
|
||||||
|
- Initiative formula: `1d6` (no decimals).
|
||||||
+2
-2
@@ -102,7 +102,7 @@ Hooks.once("init", function () {
|
|||||||
HamalronUtils.registerSettings()
|
HamalronUtils.registerSettings()
|
||||||
HamalronUtils.registerHandlebarsHelpers()
|
HamalronUtils.registerHandlebarsHelpers()
|
||||||
|
|
||||||
console.info("FTL Nomad | System Initialized")
|
console.info("HAMALRON JDR | System Initialized")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ function preLocalizeConfig() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Hooks.once("ready", function () {
|
Hooks.once("ready", function () {
|
||||||
console.info("FTL Nomad | Ready")
|
console.info("HAMALRON JDR | Ready")
|
||||||
if (game.user.isGM) {
|
if (game.user.isGM) {
|
||||||
ClassCounter.registerUsageCount("fvtt-hamalron", {})
|
ClassCounter.registerUsageCount("fvtt-hamalron", {})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ export default class HamalronActorSheet extends HandlebarsApplicationMixin(found
|
|||||||
toggleSheet: HamalronActorSheet.#onToggleSheet,
|
toggleSheet: HamalronActorSheet.#onToggleSheet,
|
||||||
edit: HamalronActorSheet.#onItemEdit,
|
edit: HamalronActorSheet.#onItemEdit,
|
||||||
delete: HamalronActorSheet.#onItemDelete,
|
delete: HamalronActorSheet.#onItemDelete,
|
||||||
updateCheckboxArray: HamalronActorSheet.#onUpdateCheckboxArray,
|
|
||||||
toChat: HamalronActorSheet.#toChat,
|
toChat: HamalronActorSheet.#toChat,
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -69,7 +68,6 @@ export default class HamalronActorSheet extends HandlebarsApplicationMixin(found
|
|||||||
actor: this.document,
|
actor: this.document,
|
||||||
system: this.document.system,
|
system: this.document.system,
|
||||||
source: this.document.toObject(),
|
source: this.document.toObject(),
|
||||||
enrichedBackstory: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.backstory, { async: true }),
|
|
||||||
isEditMode: this.isEditMode,
|
isEditMode: this.isEditMode,
|
||||||
isPlayMode: this.isPlayMode,
|
isPlayMode: this.isPlayMode,
|
||||||
isEditable: this.isEditable,
|
isEditable: this.isEditable,
|
||||||
@@ -187,44 +185,19 @@ export default class HamalronActorSheet extends HandlebarsApplicationMixin(found
|
|||||||
return fp.browse()
|
return fp.browse()
|
||||||
}
|
}
|
||||||
|
|
||||||
static #onUpdateCheckboxArray(event, target) {
|
|
||||||
console.log("Update checkbox array", event, target)
|
|
||||||
let arrayName = target.dataset.name
|
|
||||||
let arrayIdx = Number(target.dataset.index)
|
|
||||||
let dataPath = `system.mortality.${arrayName}`
|
|
||||||
let tab = foundry.utils.duplicate(this.document.system.mortality[arrayName])
|
|
||||||
tab[arrayIdx] = target.checked
|
|
||||||
this.actor.update({ [dataPath]: tab })
|
|
||||||
}
|
|
||||||
|
|
||||||
static async #toChat(event, target) {
|
static async #toChat(event, target) {
|
||||||
const itemUuid = target.getAttribute("data-item-uuid")
|
const itemUuid = target.getAttribute("data-item-uuid")
|
||||||
const item = fromUuidSync(itemUuid)
|
const item = fromUuidSync(itemUuid)
|
||||||
if (!item) return
|
if (!item) return
|
||||||
let content = ""
|
if (item.type !== "tarot") return
|
||||||
if (item.type === "perk") {
|
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-hamalron/templates/chat-tarot.hbs", item.toObject())
|
||||||
content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-hamalron/templates/chat-perk.hbs", item.toObject())
|
const actor = this.actor || this.document?.parent
|
||||||
}
|
ChatMessage.create({
|
||||||
if (item.type === "malefica") {
|
|
||||||
content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-hamalron/templates/chat-malefica.hbs", item.toObject())
|
|
||||||
}
|
|
||||||
if (item.type === "ritual") {
|
|
||||||
content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-hamalron/templates/chat-ritual.hbs", item.toObject())
|
|
||||||
}
|
|
||||||
if (item.type === "species-trait") {
|
|
||||||
content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-hamalron/templates/chat-trait.hbs", item.toObject())
|
|
||||||
}
|
|
||||||
if (item.type === "tarot") {
|
|
||||||
content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-hamalron/templates/chat-tarot.hbs", item.toObject())
|
|
||||||
}
|
|
||||||
const chatData = {
|
|
||||||
user: game.user.id,
|
user: game.user.id,
|
||||||
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
speaker: ChatMessage.getSpeaker({ actor }),
|
||||||
content: content,
|
content,
|
||||||
type: CONST.CHAT_MESSAGE_TYPES.OTHER,
|
type: CONST.CHAT_MESSAGE_TYPES.OTHER,
|
||||||
}
|
}, { renderSheet: false })
|
||||||
ChatMessage.create(chatData, { renderSheet: false })
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -127,12 +127,13 @@ export default class HamalronItemSheet extends HandlebarsApplicationMixin(foundr
|
|||||||
const el = event.currentTarget
|
const el = event.currentTarget
|
||||||
if ("link" in event.target.dataset) return
|
if ("link" in event.target.dataset) return
|
||||||
|
|
||||||
// Extract the data you need
|
const itemId = el.dataset.itemId
|
||||||
let dragData = null
|
if (!itemId) return
|
||||||
|
|
||||||
if (!dragData) return
|
const item = this.document.items.get(itemId)
|
||||||
|
if (!item) return
|
||||||
|
|
||||||
// Set data transfer
|
const dragData = item.toDragData()
|
||||||
event.dataTransfer.setData("text/plain", JSON.stringify(dragData))
|
event.dataTransfer.setData("text/plain", JSON.stringify(dragData))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,9 @@ export default class HamalronEnemySheet extends HamalronActorSheet {
|
|||||||
contentClasses: ["enemy-content"],
|
contentClasses: ["enemy-content"],
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
createTrait: HamalronEnemySheet.#onCreateTrait,
|
|
||||||
createEquipment: HamalronEnemySheet.#onCreateEquipment,
|
createEquipment: HamalronEnemySheet.#onCreateEquipment,
|
||||||
createWeapon: HamalronEnemySheet.#onCreateWeapon,
|
createWeapon: HamalronEnemySheet.#onCreateWeapon,
|
||||||
createMalefica: HamalronEnemySheet.#onCreateMalefica,
|
createSortilege: HamalronEnemySheet.#onCreateSortilege,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -74,13 +73,13 @@ export default class HamalronEnemySheet extends HamalronActorSheet {
|
|||||||
break
|
break
|
||||||
case "traits":
|
case "traits":
|
||||||
context.tab = context.tabs.traits
|
context.tab = context.tabs.traits
|
||||||
context.traits = doc.itemTypes["species-trait"]
|
context.traits = doc.itemTypes.competence || []
|
||||||
context.traits.sort((a, b) => a.name.localeCompare(b.name))
|
context.traits.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
context.weapons = doc.itemTypes.weapon
|
context.weapons = doc.itemTypes.arme || []
|
||||||
context.weapons.sort((a, b) => a.name.localeCompare(b.name))
|
context.weapons.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
context.maleficas = doc.itemTypes.malefica
|
context.sortileges = doc.itemTypes.sortilege || []
|
||||||
context.maleficas.sort((a, b) => a.name.localeCompare(b.name))
|
context.sortileges.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
context.equipments = doc.itemTypes.equipment
|
context.equipments = doc.itemTypes.equipement || []
|
||||||
context.equipments.sort((a, b) => a.name.localeCompare(b.name))
|
context.equipments.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
break
|
break
|
||||||
case "biography":
|
case "biography":
|
||||||
@@ -92,25 +91,16 @@ export default class HamalronEnemySheet extends HamalronActorSheet {
|
|||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new attack item directly from the sheet and embeds it into the document.
|
|
||||||
* @param {Event} event The initiating click event.
|
|
||||||
* @param {HTMLElement} target The current target of the event listener.
|
|
||||||
*/
|
|
||||||
static #onCreateTrait(event, target) {
|
|
||||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newTrait"), type: "species-trait" }])
|
|
||||||
}
|
|
||||||
|
|
||||||
static #onCreateEquipment(event, target) {
|
static #onCreateEquipment(event, target) {
|
||||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newEquipment"), type: "equipment" }])
|
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newEquipment"), type: "equipement" }])
|
||||||
}
|
}
|
||||||
|
|
||||||
static #onCreateMalefica(event, target) {
|
static #onCreateSortilege(event, target) {
|
||||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newMalefica"), type: "malefica" }])
|
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newSortilege"), type: "sortilege" }])
|
||||||
}
|
}
|
||||||
|
|
||||||
static #onCreateWeapon(event, target) {
|
static #onCreateWeapon(event, target) {
|
||||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newWeapon"), type: "weapon" }])
|
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newWeapon"), type: "arme" }])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -135,8 +125,8 @@ export default class HamalronEnemySheet extends HamalronActorSheet {
|
|||||||
case "stat":
|
case "stat":
|
||||||
{
|
{
|
||||||
let statId = $(event.currentTarget).data("stat-id");
|
let statId = $(event.currentTarget).data("stat-id");
|
||||||
item = this.actor.system.stats[statId];
|
item = this.actor.system?.stats?.[statId];
|
||||||
await this.document.system.roll(rollType, item)
|
if (item) await this.document.system.roll(rollType, item)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "weapon":
|
case "weapon":
|
||||||
@@ -144,7 +134,7 @@ export default class HamalronEnemySheet extends HamalronActorSheet {
|
|||||||
{
|
{
|
||||||
let li = $(event.currentTarget).parents(".item");
|
let li = $(event.currentTarget).parents(".item");
|
||||||
item = this.actor.items.get(li.data("item-id"));
|
item = this.actor.items.get(li.data("item-id"));
|
||||||
await this.document.system.roll(rollType, item)
|
if (item) await this.document.system.roll(rollType, item)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@@ -154,7 +144,7 @@ export default class HamalronEnemySheet extends HamalronActorSheet {
|
|||||||
|
|
||||||
async _onDrop(event) {
|
async _onDrop(event) {
|
||||||
if (!this.isEditable || !this.isEditMode) return
|
if (!this.isEditable || !this.isEditMode) return
|
||||||
const data = TextEditor.getDragEventData(event)
|
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)
|
||||||
|
|
||||||
// Handle different data types
|
// Handle different data types
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import HamalronActorSheet from "./base-actor-sheet.mjs"
|
import HamalronActorSheet from "./base-actor-sheet.mjs"
|
||||||
import { SYSTEM } from "../../config/system.mjs"
|
import { SYSTEM } from "../../config/system.mjs"
|
||||||
|
import HamalronUtils from "../../utils.mjs"
|
||||||
|
|
||||||
export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
||||||
/** @override */
|
/** @override */
|
||||||
@@ -16,11 +17,7 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
|||||||
createEquipment: HamalronPersonnageSheet.#onCreateEquipment,
|
createEquipment: HamalronPersonnageSheet.#onCreateEquipment,
|
||||||
createArmor: HamalronPersonnageSheet.#onCreateArmor,
|
createArmor: HamalronPersonnageSheet.#onCreateArmor,
|
||||||
createWeapon: HamalronPersonnageSheet.#onCreateWeapon,
|
createWeapon: HamalronPersonnageSheet.#onCreateWeapon,
|
||||||
createDeal: HamalronPersonnageSheet.#onCreateDeal,
|
createSortilege: HamalronPersonnageSheet.#onCreateSortilege,
|
||||||
createMalefica: HamalronPersonnageSheet.#onCreateMalefica,
|
|
||||||
createRitual: HamalronPersonnageSheet.#onCreateRitual,
|
|
||||||
createPerk: HamalronPersonnageSheet.#onCreatePerk,
|
|
||||||
modifyAmmo: HamalronPersonnageSheet.#onModifyAmmo,
|
|
||||||
modifyResistance: HamalronPersonnageSheet.#onModifyResistance,
|
modifyResistance: HamalronPersonnageSheet.#onModifyResistance,
|
||||||
discardCard: HamalronPersonnageSheet.#onDiscardCard,
|
discardCard: HamalronPersonnageSheet.#onDiscardCard,
|
||||||
rollCompetence: HamalronPersonnageSheet.#onRollCompetence,
|
rollCompetence: HamalronPersonnageSheet.#onRollCompetence,
|
||||||
@@ -118,21 +115,15 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
|||||||
case "sortileges":
|
case "sortileges":
|
||||||
context.tab = context.tabs.sortileges
|
context.tab = context.tabs.sortileges
|
||||||
context.sortileges = doc.itemTypes.sortilege || []
|
context.sortileges = doc.itemTypes.sortilege || []
|
||||||
// Sort the sortileges by system.domain and then by the system.level
|
context.sortileges.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
context.sortileges.sort((a, b) => {
|
|
||||||
if (a.system.domain === b.system.domain) {
|
|
||||||
return a.system.level.localeCompare(b.system.level)
|
|
||||||
}
|
|
||||||
return a.system.domain.localeCompare(b.system.domain)
|
|
||||||
})
|
|
||||||
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.arme || []
|
||||||
context.weapons.sort((a, b) => a.name.localeCompare(b.name))
|
context.weapons.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
context.armors = doc.itemTypes.armor || []
|
context.armors = doc.itemTypes.armure || []
|
||||||
context.armors.sort((a, b) => a.name.localeCompare(b.name))
|
context.armors.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
context.equipments = doc.itemTypes.equipment || []
|
context.equipments = doc.itemTypes.equipement || []
|
||||||
context.equipments.sort((a, b) => a.name.localeCompare(b.name))
|
context.equipments.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
break
|
break
|
||||||
case "tarot":
|
case "tarot":
|
||||||
@@ -142,16 +133,14 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
|||||||
context.handLimit = 7
|
context.handLimit = 7
|
||||||
context.handSize = context.tarotCards.length
|
context.handSize = context.tarotCards.length
|
||||||
context.isOverLimit = context.handSize > context.handLimit
|
context.isOverLimit = context.handSize > context.handLimit
|
||||||
context.canAddCard = context.handSize < 8
|
context.canAddCard = context.handSize < context.handLimit
|
||||||
// Marquer les cartes de succès et enrichir les descriptions
|
|
||||||
for (const card of context.tarotCards) {
|
for (const card of context.tarotCards) {
|
||||||
card.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(card.system.description, { async: true })
|
card.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(card.system.description, { async: true })
|
||||||
// Vérifier si c'est une carte de succès
|
|
||||||
if (doc.system.cartesSucces && card.system.type !== "atout") {
|
if (doc.system.cartesSucces && card.system.type !== "atout") {
|
||||||
card.isSuccessCard = Object.keys(doc.system.cartesSucces).some(symbole => {
|
card.isSuccessCard = Object.keys(doc.system.cartesSucces).some(symbole => {
|
||||||
const successCardData = doc.system.cartesSucces[symbole]
|
const successCardData = doc.system.cartesSucces[symbole]
|
||||||
return card.system.symbole === symbole &&
|
return card.system.symbole === symbole &&
|
||||||
card.system.valeur === successCardData.value.toString()
|
String(card.system.valeur) === String(successCardData.value)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
card.isSuccessCard = false
|
card.isSuccessCard = false
|
||||||
@@ -160,19 +149,7 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
|||||||
break
|
break
|
||||||
case "biography":
|
case "biography":
|
||||||
context.tab = context.tabs.biography
|
context.tab = context.tabs.biography
|
||||||
context.deals = doc.itemTypes.deal || []
|
context.enrichedHistorial = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.historial, { async: true })
|
||||||
context.enrichedBackstory = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.backstory, { async: true })
|
|
||||||
context.enrichedAppearance = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.appearance, { async: true })
|
|
||||||
context.enrichedScars = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.scars, { async: true })
|
|
||||||
context.enrichedLikes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.likes, { async: true })
|
|
||||||
context.enrichedDislikes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.dislikes, { async: true })
|
|
||||||
context.enrichedFears = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.fears, { async: true })
|
|
||||||
context.enrichedVices = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.vices, { async: true })
|
|
||||||
context.enrichedGoals = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.goals, { async: true })
|
|
||||||
context.enrichedAmbitions = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.ambitions, { async: true })
|
|
||||||
context.enrichedValues = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.values, { async: true })
|
|
||||||
context.enrichedBonds = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.bonds, { async: true })
|
|
||||||
context.enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.notes, { async: true })
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return context
|
return context
|
||||||
@@ -180,44 +157,19 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
|||||||
|
|
||||||
|
|
||||||
static #onCreateEquipment(event, target) {
|
static #onCreateEquipment(event, target) {
|
||||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newEquipment"), type: "equipment" }])
|
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newEquipment"), type: "equipement" }])
|
||||||
}
|
|
||||||
|
|
||||||
static #onCreateDeal(event, target) {
|
|
||||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newDeal"), type: "deal" }])
|
|
||||||
}
|
|
||||||
|
|
||||||
static #onCreateMalefica(event, target) {
|
|
||||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newMalefica"), type: "malefica" }])
|
|
||||||
}
|
|
||||||
|
|
||||||
static #onCreateRitual(event, target) {
|
|
||||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newRitual"), type: "ritual" }])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static #onCreateWeapon(event, target) {
|
static #onCreateWeapon(event, target) {
|
||||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newWeapon"), type: "weapon" }])
|
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newWeapon"), type: "arme" }])
|
||||||
}
|
}
|
||||||
|
|
||||||
static #onCreateArmor(event, target) {
|
static #onCreateArmor(event, target) {
|
||||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newArmor"), type: "armor" }])
|
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newArmor"), type: "armure" }])
|
||||||
}
|
}
|
||||||
|
|
||||||
static #onCreatePerk(event, target) {
|
static #onCreateSortilege(event, target) {
|
||||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newPerk"), type: "perk" }])
|
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newSortilege"), type: "sortilege" }])
|
||||||
}
|
|
||||||
|
|
||||||
static async #onModifyAmmo(event, target) {
|
|
||||||
const quantity = parseInt($(event.target).data("quantity"))
|
|
||||||
const itemId = $(event.target).data("item-id")
|
|
||||||
const item = this.document.items.get(itemId)
|
|
||||||
if (!item) {
|
|
||||||
console.warn(`HamalronCharacterSheet: Item with ID ${itemId} not found`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const currentAmmo = item.system.ammoQuantity || 0
|
|
||||||
const newAmmo = Math.max(0, currentAmmo + quantity) // Ensure ammo doesn't go below 0
|
|
||||||
await item.update({ "system.ammoQuantity": newAmmo })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #onModifyResistance(event, target) {
|
static async #onModifyResistance(event, target) {
|
||||||
@@ -326,7 +278,7 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
|||||||
const { default: HamalronTirageTarot } = await import("../../documents/tirage-tarot.mjs")
|
const { default: HamalronTirageTarot } = await import("../../documents/tirage-tarot.mjs")
|
||||||
await HamalronTirageTarot.handleLeMatEffect(this.document, deckManager)
|
await HamalronTirageTarot.handleLeMatEffect(this.document, deckManager)
|
||||||
} else {
|
} else {
|
||||||
const originalItem = game.items.get(newCard.id)
|
const originalItem = await HamalronUtils.findTarotItem(newCard)
|
||||||
if (originalItem) {
|
if (originalItem) {
|
||||||
await this.document.createEmbeddedDocuments("Item", [originalItem.toObject()])
|
await this.document.createEmbeddedDocuments("Item", [originalItem.toObject()])
|
||||||
ui.notifications.info(game.i18n.localize("HAMALRON.Notifications.cardDiscardedAndDrawn") + newCard.name)
|
ui.notifications.info(game.i18n.localize("HAMALRON.Notifications.cardDiscardedAndDrawn") + newCard.name)
|
||||||
@@ -337,7 +289,7 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
|||||||
ui.notifications.info(game.i18n.localize("HAMALRON.Notifications.cardDiscardedNoNew"))
|
ui.notifications.info(game.i18n.localize("HAMALRON.Notifications.cardDiscardedNoNew"))
|
||||||
}
|
}
|
||||||
|
|
||||||
deckManager.saveDeckState()
|
await deckManager.saveDeckState()
|
||||||
deckManager.render()
|
deckManager.render()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,14 +334,13 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
|||||||
const { default: HamalronTirageTarot } = await import("../../documents/tirage-tarot.mjs")
|
const { default: HamalronTirageTarot } = await import("../../documents/tirage-tarot.mjs")
|
||||||
await HamalronTirageTarot.handleLeMatEffect(this.document, deckManager)
|
await HamalronTirageTarot.handleLeMatEffect(this.document, deckManager)
|
||||||
} else {
|
} else {
|
||||||
// Trouver l'item original pour le dupliquer
|
const originalItem = await HamalronUtils.findTarotItem(newCard)
|
||||||
const originalItem = game.items.get(newCard.id)
|
|
||||||
if (originalItem) {
|
if (originalItem) {
|
||||||
await this.document.createEmbeddedDocuments("Item", [originalItem.toObject()])
|
await this.document.createEmbeddedDocuments("Item", [originalItem.toObject()])
|
||||||
ui.notifications.info(game.i18n.localize("HAMALRON.Notifications.newCardDrawn") + newCard.name)
|
ui.notifications.info(game.i18n.localize("HAMALRON.Notifications.newCardDrawn") + newCard.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deckManager.saveDeckState()
|
await deckManager.saveDeckState()
|
||||||
deckManager.render()
|
deckManager.render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,7 +377,7 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
|||||||
switch (rollType) {
|
switch (rollType) {
|
||||||
case "stat":
|
case "stat":
|
||||||
statKey = $(event.currentTarget).data("stat-id");
|
statKey = $(event.currentTarget).data("stat-id");
|
||||||
item = this.actor.system.stats[statKey];
|
item = this.actor.system?.stats?.[statKey];
|
||||||
break
|
break
|
||||||
case "weapon":
|
case "weapon":
|
||||||
case "damage":
|
case "damage":
|
||||||
@@ -436,7 +387,7 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
|||||||
default:
|
default:
|
||||||
throw new Error(`Unknown roll type ${rollType}`)
|
throw new Error(`Unknown roll type ${rollType}`)
|
||||||
}
|
}
|
||||||
await this.document.system.roll(rollType, item)
|
if (item) await this.document.system.roll(rollType, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onDrop(event) {
|
async _onDrop(event) {
|
||||||
@@ -456,21 +407,11 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet {
|
|||||||
|
|
||||||
const currentTarotCount = this.document.items.filter(i => i.type === "tarot").length
|
const currentTarotCount = this.document.items.filter(i => i.type === "tarot").length
|
||||||
|
|
||||||
// Check if we already have 8 cards (hard limit)
|
if (currentTarotCount >= 7) {
|
||||||
if (currentTarotCount >= 8) {
|
|
||||||
ui.notifications.warn(game.i18n.localize("HAMALRON.Notifications.tarotHandFull"))
|
ui.notifications.warn(game.i18n.localize("HAMALRON.Notifications.tarotHandFull"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (item.type === "species-trait") {
|
|
||||||
// Check if the item is already in the actor
|
|
||||||
const existingTrait = this.document.items.find(i => i.type === "species-trait" && i.name === item.name)
|
|
||||||
if (existingTrait) {
|
|
||||||
await existingTrait.delete()
|
|
||||||
// Display info message
|
|
||||||
ui.notifications.info(game.i18n.localize("HAMALRON.Notifications.speciesTraitDeleted") + existingTrait.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super._onDropItem(item)
|
return super._onDropItem(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ import HamalronItemSheet from "./base-item-sheet.mjs"
|
|||||||
export default class HamalronSortilegeSheet extends HamalronItemSheet {
|
export default class HamalronSortilegeSheet extends HamalronItemSheet {
|
||||||
/** @override */
|
/** @override */
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
classes: ["ritual"],
|
classes: ["sortilege"],
|
||||||
position: {
|
position: {
|
||||||
width: 600,
|
width: 600,
|
||||||
},
|
},
|
||||||
window: {
|
window: {
|
||||||
contentClasses: ["ritual-content"],
|
contentClasses: ["sortilege-content"],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,13 @@ export const NIVEAU_COMPETENCES = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const CHOICE_ADVANTAGES_DISADVANTAGES = {
|
||||||
|
"0": { id: "0", label: "Aucun" },
|
||||||
|
"1": { id: "1", label: "1" },
|
||||||
|
"2": { id: "2", label: "2" },
|
||||||
|
"3": { id: "3", label: "3" },
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Include all constant definitions within the SYSTEM global export
|
* Include all constant definitions within the SYSTEM global export
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
@@ -135,5 +142,6 @@ export const SYSTEM = {
|
|||||||
ENEMY_TYPES: ENEMY_TYPES,
|
ENEMY_TYPES: ENEMY_TYPES,
|
||||||
SORTILEGE_CATEGORIES: SORTILEGE_CATEGORIES,
|
SORTILEGE_CATEGORIES: SORTILEGE_CATEGORIES,
|
||||||
NIVEAU_COMPETENCES: NIVEAU_COMPETENCES,
|
NIVEAU_COMPETENCES: NIVEAU_COMPETENCES,
|
||||||
|
CHOICE_ADVANTAGES_DISADVANTAGES,
|
||||||
ASCII
|
ASCII
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,17 @@
|
|||||||
import HamalronUtils from "../utils.mjs"
|
|
||||||
|
|
||||||
export default class HamalronActor extends Actor {
|
export default class HamalronActor extends Actor {
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
|
|
||||||
// Case of compendium global import
|
|
||||||
if (data instanceof Array) {
|
|
||||||
return super.create(data, options);
|
|
||||||
}
|
|
||||||
// If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic
|
|
||||||
if (data.items) {
|
|
||||||
let actor = super.create(data, options);
|
|
||||||
return actor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.type === 'character') {
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.create(data, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onUpdate(changed, options, userId) {
|
|
||||||
return super._onUpdate(changed, options, userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async _preCreate(data, options, user) {
|
async _preCreate(data, options, user) {
|
||||||
await super._preCreate(data, options, user)
|
await super._preCreate(data, options, user)
|
||||||
|
|
||||||
// Configure prototype token settings
|
if (this.type === "personnage") {
|
||||||
const prototypeToken = {}
|
this.updateSource({
|
||||||
if (this.type === "character") {
|
prototypeToken: {
|
||||||
Object.assign(prototypeToken, {
|
|
||||||
sight: { enabled: true },
|
sight: { enabled: true },
|
||||||
actorLink: true,
|
actorLink: true,
|
||||||
disposition: CONST.TOKEN_DISPOSITIONS.FRIENDLY,
|
disposition: CONST.TOKEN_DISPOSITIONS.FRIENDLY,
|
||||||
})
|
|
||||||
this.updateSource({ prototypeToken })
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import HamalronTirageTarot from "./tirage-tarot.mjs"
|
|
||||||
|
|
||||||
export default class HamalronChatMessage extends ChatMessage {
|
export default class HamalronChatMessage extends ChatMessage {
|
||||||
async _renderRollContent(messageData) {
|
async _renderRollContent(messageData) {
|
||||||
const data = messageData.message
|
const data = messageData.message
|
||||||
if (this.rolls[0] instanceof HamalronRoll) {
|
const { default: HamalronTirageTarot } = await import("./tirage-tarot.mjs")
|
||||||
|
if (this.rolls[0] instanceof HamalronTirageTarot) {
|
||||||
const isPrivate = !this.isContentVisible
|
const isPrivate = !this.isContentVisible
|
||||||
// _renderRollHTML va appeler render sur tous les rolls
|
// _renderRollHTML va appeler render sur tous les rolls
|
||||||
const rollHTML = await this._renderRollHTML(isPrivate)
|
const rollHTML = await this._renderRollHTML(isPrivate)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
|
|
||||||
import { SYSTEM } from "../config/system.mjs"
|
import { SYSTEM } from "../config/system.mjs"
|
||||||
|
import HamalronUtils from "../utils.mjs"
|
||||||
|
|
||||||
export default class HamalronTirageTarot {
|
export default class HamalronTirageTarot extends Roll {
|
||||||
/**
|
/**
|
||||||
* The HTML template path used to render dice checks of this type
|
* The HTML template path used to render dice checks of this type
|
||||||
* @type {string}
|
* @type {string}
|
||||||
@@ -41,7 +42,7 @@ export default class HamalronTirageTarot {
|
|||||||
const newCards = deckManager.drawCards(1)
|
const newCards = deckManager.drawCards(1)
|
||||||
if (newCards.length > 0) {
|
if (newCards.length > 0) {
|
||||||
const newCard = newCards[0]
|
const newCard = newCards[0]
|
||||||
const originalItem = game.items.get(newCard.id)
|
const originalItem = await HamalronUtils.findTarotItem(newCard)
|
||||||
if (originalItem) {
|
if (originalItem) {
|
||||||
await actor.createEmbeddedDocuments("Item", [originalItem.toObject()])
|
await actor.createEmbeddedDocuments("Item", [originalItem.toObject()])
|
||||||
}
|
}
|
||||||
@@ -50,12 +51,42 @@ export default class HamalronTirageTarot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. Regrouper la défausse et le deck, puis mélanger
|
// 3. Regrouper la défausse et le deck, puis mélanger
|
||||||
deckManager.deck.push(...deckManager.discard)
|
await deckManager.resetDeck()
|
||||||
deckManager.discard = []
|
deckManager.render()
|
||||||
deckManager.shuffleDeck()
|
|
||||||
|
|
||||||
|
// 4. Proposer aux autres joueurs de renouveler leur main
|
||||||
|
if (game.user.isGM) {
|
||||||
|
const refreshOthers = await foundry.applications.api.DialogV2.confirm({
|
||||||
|
window: { title: "Le Mat - Renouvellement" },
|
||||||
|
content: `<p>Le Mat a été tiré ! Les autres joueurs peuvent renouveler leur main s'ils le désirent.</p>`,
|
||||||
|
rejectClose: false,
|
||||||
|
modal: true,
|
||||||
|
})
|
||||||
|
if (refreshOthers) {
|
||||||
|
for (const otherActor of game.actors.filter(a => a.type === "personnage")) {
|
||||||
|
if (otherActor.id === actor.id) continue
|
||||||
|
const otherCards = otherActor.items.filter(i => i.type === "tarot")
|
||||||
|
if (otherCards.length > 0) {
|
||||||
|
const otherCardIds = otherCards.map(c => c.id)
|
||||||
|
await otherActor.deleteEmbeddedDocuments("Item", otherCardIds)
|
||||||
|
for (let i = 0; i < 7; i++) {
|
||||||
|
if (deckManager.deck.length > 0) {
|
||||||
|
const newCards = deckManager.drawCards(1)
|
||||||
|
if (newCards.length > 0) {
|
||||||
|
const originalItem = await HamalronUtils.findTarotItem(newCards[0])
|
||||||
|
if (originalItem) {
|
||||||
|
await otherActor.createEmbeddedDocuments("Item", [originalItem.toObject()])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
await deckManager.saveDeckState()
|
await deckManager.saveDeckState()
|
||||||
deckManager.render()
|
deckManager.render()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ui.notifications.info(`Le Mat ! Toutes vos cartes ont été défaussées et vous recevez 7 nouvelles cartes. Le deck a été mélangé.`)
|
ui.notifications.info(`Le Mat ! Toutes vos cartes ont été défaussées et vous recevez 7 nouvelles cartes. Le deck a été mélangé.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,14 +109,10 @@ export default class HamalronTirageTarot {
|
|||||||
if (options.tarotCards && actor.system.cartesSucces) {
|
if (options.tarotCards && actor.system.cartesSucces) {
|
||||||
const competenceSymbole = options.rollItem.system.carteSymbole
|
const competenceSymbole = options.rollItem.system.carteSymbole
|
||||||
options.tarotCards = options.tarotCards.map(card => {
|
options.tarotCards = options.tarotCards.map(card => {
|
||||||
// Pour qu'une carte soit une carte de succès :
|
|
||||||
// 1. Elle ne doit pas être un atout
|
|
||||||
// 2. Son symbole doit correspondre à celui de la compétence
|
|
||||||
// 3. Sa valeur doit correspondre à celle d'une carte de succès pour ce symbole
|
|
||||||
const isSuccessCard = card.system.type !== "atout" &&
|
const isSuccessCard = card.system.type !== "atout" &&
|
||||||
card.system.symbole === competenceSymbole &&
|
card.system.symbole === competenceSymbole &&
|
||||||
actor.system.cartesSucces[competenceSymbole] &&
|
actor.system.cartesSucces[competenceSymbole] &&
|
||||||
card.system.valeur === actor.system.cartesSucces[competenceSymbole].value.toString()
|
String(card.system.valeur) === String(actor.system.cartesSucces[competenceSymbole].value)
|
||||||
// Créer un objet simple avec toutes les propriétés nécessaires
|
// Créer un objet simple avec toutes les propriétés nécessaires
|
||||||
return {
|
return {
|
||||||
id: card.id,
|
id: card.id,
|
||||||
@@ -103,9 +130,11 @@ export default class HamalronTirageTarot {
|
|||||||
let formula = options.rollItem.system.damage
|
let formula = options.rollItem.system.damage
|
||||||
if (options.rollItem?.system?.damageStat && options.rollItem.system.damageStat !== "none" && options.rollItem.system.damageStat !== "") {
|
if (options.rollItem?.system?.damageStat && options.rollItem.system.damageStat !== "none" && options.rollItem.system.damageStat !== "") {
|
||||||
let statKey = options.rollItem.system?.damageStat.toLowerCase()
|
let statKey = options.rollItem.system?.damageStat.toLowerCase()
|
||||||
let statValue = actor.system.stats[statKey].value
|
let statValue = actor.system?.stats?.[statKey]?.value
|
||||||
|
if (statValue != null) {
|
||||||
formula = `${formula} + ${statValue}`
|
formula = `${formula} + ${statValue}`
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let damageRoll = new Roll(formula)
|
let damageRoll = new Roll(formula)
|
||||||
await damageRoll.evaluate()
|
await damageRoll.evaluate()
|
||||||
await damageRoll.toMessage({
|
await damageRoll.toMessage({
|
||||||
@@ -117,9 +146,11 @@ export default class HamalronTirageTarot {
|
|||||||
case "weapon":
|
case "weapon":
|
||||||
{
|
{
|
||||||
options.weapon = foundry.utils.duplicate(options.rollItem)
|
options.weapon = foundry.utils.duplicate(options.rollItem)
|
||||||
let statKey = options.weapon.system.stat.toLowerCase()
|
let statKey = options.weapon.system?.stat?.toLowerCase()
|
||||||
|
if (statKey && actor.system?.stats?.[statKey]) {
|
||||||
options.rollItem = actor.system.stats[statKey]
|
options.rollItem = actor.system.stats[statKey]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
@@ -200,25 +231,6 @@ export default class HamalronTirageTarot {
|
|||||||
},
|
},
|
||||||
rejectClose: false, // Click on Close button will not launch an error
|
rejectClose: false, // Click on Close button will not launch an error
|
||||||
render: (event, dialog) => {
|
render: (event, dialog) => {
|
||||||
$(".roll-stat-advantages").change(event => {
|
|
||||||
options.nbAdvantages = Number(event.target.value)
|
|
||||||
HamalronTirageTarot.updateFullFormula(options)
|
|
||||||
})
|
|
||||||
$(".roll-stat-disadvantages").change(event => {
|
|
||||||
options.nbDisadvantages = Number(event.target.value)
|
|
||||||
HamalronTirageTarot.updateFullFormula(options)
|
|
||||||
})
|
|
||||||
$(".select-combat-option").change(event => {
|
|
||||||
let field = $(event.target).data("field")
|
|
||||||
let modifier = SYSTEM.ATTACK_MODIFIERS[field]
|
|
||||||
if (event.target.checked) {
|
|
||||||
options.numericModifier += modifier
|
|
||||||
} else {
|
|
||||||
options.numericModifier -= modifier
|
|
||||||
}
|
|
||||||
HamalronTirageTarot.updateFullFormula(options)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Gestion de la sélection de carte pour les compétences
|
// Gestion de la sélection de carte pour les compétences
|
||||||
if (options.rollType === "competence") {
|
if (options.rollType === "competence") {
|
||||||
let selectedCardId = null
|
let selectedCardId = null
|
||||||
@@ -342,16 +354,11 @@ export default class HamalronTirageTarot {
|
|||||||
if (selectedCard) {
|
if (selectedCard) {
|
||||||
cardSymboleMatch = selectedCard.system.symbole === options.rollItem.system.carteSymbole
|
cardSymboleMatch = selectedCard.system.symbole === options.rollItem.system.carteSymbole
|
||||||
|
|
||||||
// Vérifier si c'est une carte de succès (les atouts ne peuvent jamais être des cartes de succès)
|
|
||||||
// Pour qu'une carte soit une carte de succès :
|
|
||||||
// 1. Elle ne doit pas être un atout
|
|
||||||
// 2. Son symbole doit correspondre à celui de la compétence
|
|
||||||
// 3. Sa valeur doit correspondre à celle d'une carte de succès pour ce symbole
|
|
||||||
if (actor.system.cartesSucces && selectedCard.system.type !== "atout") {
|
if (actor.system.cartesSucces && selectedCard.system.type !== "atout") {
|
||||||
const competenceSymbole = options.rollItem.system.carteSymbole
|
const competenceSymbole = options.rollItem.system.carteSymbole
|
||||||
isAutomaticSuccess = selectedCard.system.symbole === competenceSymbole &&
|
isAutomaticSuccess = selectedCard.system.symbole === competenceSymbole &&
|
||||||
actor.system.cartesSucces[competenceSymbole] &&
|
actor.system.cartesSucces[competenceSymbole] &&
|
||||||
selectedCard.system.valeur === actor.system.cartesSucces[competenceSymbole].value.toString()
|
String(selectedCard.system.valeur) === String(actor.system.cartesSucces[competenceSymbole].value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -359,7 +366,7 @@ export default class HamalronTirageTarot {
|
|||||||
// Préparer les données pour le chat
|
// Préparer les données pour le chat
|
||||||
const difficultyData = SYSTEM.DIFFICULTY_CHOICES[options.selectedDifficulty || "moyenne"]
|
const difficultyData = SYSTEM.DIFFICULTY_CHOICES[options.selectedDifficulty || "moyenne"]
|
||||||
const isSousTensionOppose = options.selectedDifficulty === "soustension_oppose"
|
const isSousTensionOppose = options.selectedDifficulty === "soustension_oppose"
|
||||||
const isSuccess = isAutomaticSuccess || totalValue > options.targetScore
|
const isSuccess = isAutomaticSuccess || totalValue >= options.targetScore
|
||||||
|
|
||||||
// Détecter si la carte est un valet
|
// Détecter si la carte est un valet
|
||||||
const isValet = selectedCard?.system.valeur === "valet"
|
const isValet = selectedCard?.system.valeur === "valet"
|
||||||
@@ -468,21 +475,7 @@ export default class HamalronTirageTarot {
|
|||||||
if (newCards.length > 0) {
|
if (newCards.length > 0) {
|
||||||
const newCard = newCards[0]
|
const newCard = newCards[0]
|
||||||
console.log("New card to add:", newCard)
|
console.log("New card to add:", newCard)
|
||||||
// Trouver l'item tarot dans game.items
|
const originalItem = await HamalronUtils.findTarotItem(newCard)
|
||||||
let originalItem = game.items.get(newCard.id)
|
|
||||||
console.log("Original item found by ID:", originalItem)
|
|
||||||
|
|
||||||
// Si pas trouvé dans game.items, chercher dans tous les items disponibles
|
|
||||||
if (!originalItem) {
|
|
||||||
console.log("Searching for card in game.items by properties...")
|
|
||||||
originalItem = game.items.find(i =>
|
|
||||||
i.type === "tarot" &&
|
|
||||||
i.name === newCard.name &&
|
|
||||||
i.system.symbole === newCard.symbole &&
|
|
||||||
i.system.valeur === newCard.valeur
|
|
||||||
)
|
|
||||||
console.log("Original item found by search:", originalItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (originalItem) {
|
if (originalItem) {
|
||||||
// Cas spécial : Le Mat
|
// Cas spécial : Le Mat
|
||||||
@@ -505,7 +498,7 @@ export default class HamalronTirageTarot {
|
|||||||
console.log("Deck is empty, cannot draw new card")
|
console.log("Deck is empty, cannot draw new card")
|
||||||
}
|
}
|
||||||
|
|
||||||
deckManager.saveDeckState()
|
await deckManager.saveDeckState()
|
||||||
deckManager.render()
|
deckManager.render()
|
||||||
ui.notifications.info(`${game.i18n.localize("HAMALRON.Notifications.cardUsed")}: ${selectedCard.name}`)
|
ui.notifications.info(`${game.i18n.localize("HAMALRON.Notifications.cardUsed")}: ${selectedCard.name}`)
|
||||||
}
|
}
|
||||||
@@ -673,7 +666,7 @@ export default class HamalronTirageTarot {
|
|||||||
* @returns {Promise} - A promise that resolves when the message is created.
|
* @returns {Promise} - A promise that resolves when the message is created.
|
||||||
*/
|
*/
|
||||||
async toMessage(messageData = {}, { rollMode, create = true } = {}) {
|
async toMessage(messageData = {}, { rollMode, create = true } = {}) {
|
||||||
super.toMessage(
|
return super.toMessage(
|
||||||
{
|
{
|
||||||
isFailure: this.resultType === "failure",
|
isFailure: this.resultType === "failure",
|
||||||
actingCharName: this.actorName,
|
actingCharName: this.actorName,
|
||||||
@@ -682,7 +675,7 @@ export default class HamalronTirageTarot {
|
|||||||
realDamage: this.realDamage,
|
realDamage: this.realDamage,
|
||||||
...messageData,
|
...messageData,
|
||||||
},
|
},
|
||||||
{ rollMode: rollMode },
|
{ rollMode, create },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ export default class HamalronArme extends foundry.abstract.TypeDataModel {
|
|||||||
|
|
||||||
prepareDerivedData() {
|
prepareDerivedData() {
|
||||||
super.prepareDerivedData();
|
super.prepareDerivedData();
|
||||||
let actor = this.parent?.actor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default class HamalronArmure extends foundry.abstract.TypeDataModel {
|
|||||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||||
schema.protection = new fields.NumberField({ required: true, initial: 0, min: 0, integer: true })
|
schema.protection = new fields.NumberField({ required: true, initial: 0, min: 0, integer: true })
|
||||||
|
|
||||||
schema.cost = new fields.NumberField({ required: true, initial: 0, min: 0 })
|
schema.cout = new fields.NumberField({ required: true, initial: 0, min: 0 })
|
||||||
|
|
||||||
return schema
|
return schema
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default class HamalronEquipement extends foundry.abstract.TypeDataModel {
|
|||||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||||
|
|
||||||
schema.quantity = new fields.NumberField({ required: true, initial: 1, min: 0, integer: true })
|
schema.quantity = new fields.NumberField({ required: true, initial: 1, min: 0, integer: true })
|
||||||
schema.cost = new fields.NumberField({ required: true, initial: 0, min: 0 })
|
schema.cout = new fields.NumberField({ required: true, initial: 0, min: 0 })
|
||||||
|
|
||||||
return schema
|
return schema
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { SYSTEM } from "../config/system.mjs";
|
import { SYSTEM } from "../config/system.mjs";
|
||||||
|
|
||||||
export default class HamalronFaction extends foundry.abstract.TypeDataModel {
|
export default class HamalronLangue extends foundry.abstract.TypeDataModel {
|
||||||
static defineSchema() {
|
static defineSchema() {
|
||||||
const fields = foundry.data.fields;
|
const fields = foundry.data.fields;
|
||||||
const schema = {};
|
const schema = {};
|
||||||
@@ -12,5 +12,5 @@ export default class HamalronFaction extends foundry.abstract.TypeDataModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static LOCALIZATION_PREFIXES = ["HAMALRON.Faction"];
|
static LOCALIZATION_PREFIXES = ["HAMALRON.Langue"];
|
||||||
}
|
}
|
||||||
@@ -66,17 +66,13 @@ export default class HamalronPersonnage extends foundry.abstract.TypeDataModel {
|
|||||||
* @returns {Promise<null>} - A promise that resolves to null if the roll is cancelled.
|
* @returns {Promise<null>} - A promise that resolves to null if the roll is cancelled.
|
||||||
*/
|
*/
|
||||||
async roll(rollType, rollItem) {
|
async roll(rollType, rollItem) {
|
||||||
let opponentTarget
|
|
||||||
const hasTarget = opponentTarget !== undefined
|
|
||||||
|
|
||||||
let roll = await HamalronTirageTarot.prompt({
|
let roll = await HamalronTirageTarot.prompt({
|
||||||
rollType,
|
rollType,
|
||||||
rollItem,
|
rollItem,
|
||||||
actorId: this.parent.id,
|
actorId: this.parent.id,
|
||||||
actorName: this.parent.name,
|
actorName: this.parent.name,
|
||||||
actorImage: this.parent.img,
|
actorImage: this.parent.img,
|
||||||
hasTarget,
|
hasTarget: false,
|
||||||
target: opponentTarget
|
|
||||||
})
|
})
|
||||||
if (!roll) return null
|
if (!roll) return null
|
||||||
|
|
||||||
|
|||||||
@@ -24,18 +24,13 @@ export default class HamalronPNJ extends foundry.abstract.TypeDataModel {
|
|||||||
static LOCALIZATION_PREFIXES = ["HAMALRON.PNJ"]
|
static LOCALIZATION_PREFIXES = ["HAMALRON.PNJ"]
|
||||||
|
|
||||||
async roll(rollType, rollItem) {
|
async roll(rollType, rollItem) {
|
||||||
let opponentTarget
|
|
||||||
const hasTarget = opponentTarget !== undefined
|
|
||||||
|
|
||||||
let roll = await HamalronTirageTarot.prompt({
|
let roll = await HamalronTirageTarot.prompt({
|
||||||
rollType,
|
rollType,
|
||||||
rollItem,
|
rollItem,
|
||||||
actorId: this.parent.id,
|
actorId: this.parent.id,
|
||||||
actorName: this.parent.name,
|
actorName: this.parent.name,
|
||||||
actorImage: this.parent.img,
|
actorImage: this.parent.img,
|
||||||
traits: this.parent.items.filter(i => i.type === "trait"),
|
hasTarget: false,
|
||||||
hasTarget,
|
|
||||||
target: opponentTarget
|
|
||||||
})
|
})
|
||||||
if (!roll) return null
|
if (!roll) return null
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ export default class HamalronSortilege extends foundry.abstract.TypeDataModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static LOCALIZATION_PREFIXES = ["HAMALRON.Ritual"]
|
static LOCALIZATION_PREFIXES = ["HAMALRON.Sortilege"]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export default class HamalronTarot extends foundry.abstract.TypeDataModel {
|
|||||||
schema.image = new fields.FilePathField({
|
schema.image = new fields.FilePathField({
|
||||||
required: false,
|
required: false,
|
||||||
categories: ["IMAGE"],
|
categories: ["IMAGE"],
|
||||||
default: "icons/svg/treasure.svg",
|
initial: "icons/svg/treasure.svg",
|
||||||
})
|
})
|
||||||
|
|
||||||
return schema;
|
return schema;
|
||||||
|
|||||||
+25
-13
@@ -1,19 +1,6 @@
|
|||||||
|
|
||||||
import { SYSTEM } from "./config/system.mjs"
|
|
||||||
|
|
||||||
export default class HamalronUtils {
|
export default class HamalronUtils {
|
||||||
|
|
||||||
static registerSettings() {
|
static registerSettings() {
|
||||||
game.settings.register("fvtt-hamalron", "settings-era", {
|
|
||||||
name: game.i18n.localize("HAMALRON.Settings.era"),
|
|
||||||
hint: game.i18n.localize("HAMALRON.Settings.eraHint"),
|
|
||||||
default: "jazz",
|
|
||||||
scope: "world",
|
|
||||||
type: String,
|
|
||||||
choices: SYSTEM.AVAILABLE_SETTINGS,
|
|
||||||
config: true,
|
|
||||||
onChange: _ => window.location.reload()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async loadCompendiumData(compendium) {
|
static async loadCompendiumData(compendium) {
|
||||||
@@ -26,6 +13,31 @@ export default class HamalronUtils {
|
|||||||
return compendiumData.filter(filter)
|
return compendiumData.filter(filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async findTarotItem(cardData) {
|
||||||
|
if (!cardData) return null
|
||||||
|
let item = game.items.get(cardData.id)
|
||||||
|
if (item) return item
|
||||||
|
item = game.items.find(i =>
|
||||||
|
i.type === "tarot" &&
|
||||||
|
i.name === cardData.name &&
|
||||||
|
i.system.symbole === cardData.symbole &&
|
||||||
|
String(i.system.valeur) === String(cardData.valeur)
|
||||||
|
)
|
||||||
|
if (item) return item
|
||||||
|
for (const pack of game.packs) {
|
||||||
|
if (pack.documentName !== "Item") continue
|
||||||
|
const index = pack.index.find(e =>
|
||||||
|
e.type === "tarot" &&
|
||||||
|
e.name === cardData.name
|
||||||
|
)
|
||||||
|
if (index) {
|
||||||
|
item = await pack.getDocument(index._id)
|
||||||
|
if (item) return item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
static registerHandlebarsHelpers() {
|
static registerHandlebarsHelpers() {
|
||||||
|
|
||||||
Handlebars.registerHelper('isNull', function (val) {
|
Handlebars.registerHelper('isNull', function (val) {
|
||||||
|
|||||||
@@ -19,40 +19,10 @@
|
|||||||
|
|
||||||
<fieldset class="enemy-definition">
|
<fieldset class="enemy-definition">
|
||||||
{{formField systemFields.enemyType value=system.enemyType rootId=partId disabled=isPlayMode}}
|
{{formField systemFields.enemyType value=system.enemyType rootId=partId disabled=isPlayMode}}
|
||||||
{{formField systemFields.flavorText value=system.flavorText rootId=partId disabled=isPlayMode}}
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset class="enemy-stats enemy-stats-{{ifThen isPlayMode 'play' 'edit'}}">
|
|
||||||
<legend>{{localize "HAMALRON.Label.stats"}}</legend>
|
|
||||||
<div class="enemy-stat">
|
|
||||||
<label class="rollable" data-roll-type="stat" data-stat-id="flesh"><i class="fa-regular fa-dice"></i>{{localize
|
|
||||||
"HAMALRON.Label.flesh"}}</label>
|
|
||||||
{{formInput systemFields.stats.fields.flesh.fields.value value=system.stats.flesh.value rootId=partId disabled=isPlayMode type="number" }}
|
|
||||||
</div>
|
|
||||||
<div class="enemy-stat">
|
|
||||||
<label class="rollable" data-roll-type="stat" data-stat-id="skin"><i class="fa-regular fa-dice"></i>{{localize
|
|
||||||
"HAMALRON.Label.skin"}}</label>
|
|
||||||
{{formInput systemFields.stats.fields.skin.fields.value value=system.stats.skin.value rootId=partId disabled=isPlayMode type="number" }}
|
|
||||||
</div>
|
|
||||||
<div class="enemy-stat">
|
|
||||||
<label class="rollable" data-roll-type="stat" data-stat-id="heart"><i class="fa-regular fa-dice"></i>{{localize
|
|
||||||
"HAMALRON.Label.heart"}}</label>
|
|
||||||
{{formInput systemFields.stats.fields.heart.fields.value value=system.stats.heart.value rootId=partId disabled=isPlayMode type="number" }}
|
|
||||||
</div>
|
|
||||||
<div class="enemy-stat">
|
|
||||||
<label class="rollable" data-roll-type="stat" data-stat-id="mind"><i class="fa-regular fa-dice"></i>{{localize
|
|
||||||
"HAMALRON.Label.mind"}}</label>
|
|
||||||
{{formInput systemFields.stats.fields.mind.fields.value value=system.stats.mind.value rootId=partId disabled=isPlayMode type="number" }}
|
|
||||||
</div>
|
|
||||||
<div class="enemy-stat">
|
|
||||||
<label class="rollable" data-roll-type="stat" data-stat-id="soul"><i class="fa-regular fa-dice"></i>{{localize
|
|
||||||
"HAMALRON.Label.soul"}}</label>
|
|
||||||
{{formInput systemFields.stats.fields.soul.fields.value value=system.stats.soul.value rootId=partId disabled=isPlayMode type="number" }}
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
+24
-122
@@ -1,117 +1,6 @@
|
|||||||
<section class="tab enemy-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
|
<section class="tab enemy-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
|
||||||
<div class="main-div">
|
<div class="main-div">
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.characteristics"}}</legend>
|
|
||||||
<div class="counters">
|
|
||||||
<div class="flexcol">
|
|
||||||
<div>
|
|
||||||
<label>Trauma : </label>{{formInput systemFields.trauma.fields.current value=system.trauma.current}} /
|
|
||||||
{{formInput systemFields.trauma.fields.max value=system.trauma.max}}
|
|
||||||
|
|
||||||
<label class="spaced-left"> Darkness </label>
|
|
||||||
{{formInput systemFields.darkness.fields.current value=system.darkness.current}} /
|
|
||||||
{{formInput systemFields.darkness.fields.max value=system.darkness.max}}
|
|
||||||
{{formInput systemFields.darkness.fields.value value=system.darkness.value}}
|
|
||||||
<label class="spaced-left"> Defense </label>
|
|
||||||
{{formInput systemFields.defense.fields.base value=system.defense.base}}
|
|
||||||
{{formInput systemFields.defense.fields.resilience value=system.defense.resilience}}
|
|
||||||
<label class="spaced-left"> Movement </label>{{formInput systemFields.movement.fields.base value=system.movement.base}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flexrow characteristics-label">
|
|
||||||
<label></label><span>Curr.</span><span>Max</span>
|
|
||||||
<label></label><span> Curr.</span><span> Max</span><span> Mal.DR</span>
|
|
||||||
<label></label><span> Total</span><span> Resi.</span>
|
|
||||||
<label></label>
|
|
||||||
<label></label>
|
|
||||||
<label></label>
|
|
||||||
<label></label>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.ailments"}}</legend>
|
|
||||||
|
|
||||||
<div class="ailments">
|
|
||||||
{{#each system.ailments as |item id|}}
|
|
||||||
<div class="ailment " data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="false">
|
|
||||||
<label>{{item.label}}</label> <input type="checkbox" class="checkbox" name="system.ailments.{{id}}.enabled"
|
|
||||||
{{#if item.enabled}} checked {{/if}}>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<div class="enemy-column">
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.traits"}}{{#if isEditMode}}
|
|
||||||
<a class="action" data-tooltip="{{localize "HAMALRON.Tooltip.addTrait"}}" data-tooltip-direction="UP"><i
|
|
||||||
class="fas fa-plus" data-action="createTrait"></i></a>{{/if}}
|
|
||||||
</legend>
|
|
||||||
<div class="traits">
|
|
||||||
{{#each traits as |item|}}
|
|
||||||
<div class="trait item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
|
|
||||||
|
|
||||||
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
|
|
||||||
<!-- <img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />-->
|
|
||||||
<div class="name" data-roll-type="trait" data-action="toChat" data-item-uuid="{{item.uuid}}" data-tooltip="{{{item.system.description}}}">
|
|
||||||
<a>{{item.name}}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="controls">
|
|
||||||
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
|
||||||
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
|
||||||
<a data-tooltip="{{localize 'HAMALRON.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
|
|
||||||
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.maleficas"}}{{#if isEditMode}}
|
|
||||||
<a class="action" data-tooltip="{{localize "HAMALRON.Tooltip.addMalefica"}}" data-tooltip-direction="UP"><i
|
|
||||||
class="fas fa-plus" data-action="createMalefica"></i></a>{{/if}}
|
|
||||||
</legend>
|
|
||||||
<div class="maleficas">
|
|
||||||
{{#each maleficas as |item|}}
|
|
||||||
<div class="malefica item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
|
|
||||||
|
|
||||||
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
|
|
||||||
<!-- <img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />-->
|
|
||||||
<div class="name" data-roll-type="malefica" data-action="toChat" data-item-uuid="{{item.uuid}}" data-tooltip="{{{item.system.description}}}">
|
|
||||||
<a>{{item.name}}</a>
|
|
||||||
</div>
|
|
||||||
<span class="domain" data-tooltip="Domain">{{upperFirst item.system.domain}}</span>
|
|
||||||
<span class="level" data-tooltip="Level">{{getRomanLevel item.system.level}}</span>
|
|
||||||
{{#if item.system.hasDamage}}
|
|
||||||
<a class="damage rollable" data-tooltip="Damage" data-item-id="{{item.id}}" data-action="roll"
|
|
||||||
data-roll-type="damage" data-roll-value="{{item.system.damage}}">
|
|
||||||
<i class="fa-regular fa-dice"></i>
|
|
||||||
{{item.system.damage}}</a>
|
|
||||||
{{else}}
|
|
||||||
<span class="damage" data-tooltip="Damage">-</span>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<div class="controls">
|
|
||||||
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
|
||||||
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
|
||||||
<a data-tooltip="{{localize 'HAMALRON.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
|
|
||||||
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{{localize "HAMALRON.Label.weapons"}}{{#if isEditMode}}
|
<legend>{{localize "HAMALRON.Label.weapons"}}{{#if isEditMode}}
|
||||||
<a class="action" data-tooltip="{{localize "HAMALRON.Tooltip.addWeapon"}}" data-tooltip-direction="UP"><i
|
<a class="action" data-tooltip="{{localize "HAMALRON.Tooltip.addWeapon"}}" data-tooltip-direction="UP"><i
|
||||||
@@ -120,22 +9,35 @@
|
|||||||
<div class="weapons">
|
<div class="weapons">
|
||||||
{{#each weapons as |item|}}
|
{{#each weapons as |item|}}
|
||||||
<div class="weapon item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
|
<div class="weapon item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
|
||||||
|
|
||||||
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
|
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
|
||||||
<i class="fa-regular fa-dice"></i>
|
<div class="name" data-tooltip="{{{item.system.description}}}">
|
||||||
<div class="name rollable" data-roll-type="weapon" data-tooltip="{{{item.system.description}}}">
|
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</div>
|
</div>
|
||||||
<span class="type" data-tooltip="Type">{{upperFirst item.system.weaponType}}</span>
|
<span class="type" data-tooltip="Type">{{upperFirst item.system.weaponType}}</span>
|
||||||
<span class="properties" data-tooltip="Properties">{{upperFirst item.system.properties}}</span>
|
|
||||||
<span class="range" data-tooltip="Range">{{upperFirst item.system.range}}</span>
|
|
||||||
<span class="ammo" data-tooltip="Ammo">{{upperFirst item.system.ammo}}</span>
|
|
||||||
|
|
||||||
<a class="damage rollable" data-tooltip="Damage" data-item-id="{{item.id}}" data-action="roll"
|
<div class="controls">
|
||||||
data-roll-type="damage" data-roll-value="{{item.system.damage}}">
|
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
||||||
<i class="fa-regular fa-dice"></i>
|
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
||||||
{{item.system.damage}}</a>
|
<a data-tooltip="{{localize 'HAMALRON.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
|
||||||
|
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>{{localize "HAMALRON.Label.sortileges"}}{{#if isEditMode}}
|
||||||
|
<a class="action" data-tooltip="{{localize "HAMALRON.Tooltip.addSortilege"}}" data-tooltip-direction="UP"><i
|
||||||
|
class="fas fa-plus" data-action="createSortilege"></i></a>{{/if}}
|
||||||
|
</legend>
|
||||||
|
<div class="sortileges">
|
||||||
|
{{#each sortileges as |item|}}
|
||||||
|
<div class="sortilege item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
|
||||||
|
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
|
||||||
|
<div class="name" data-tooltip="{{{item.system.description}}}">
|
||||||
|
{{item.name}}
|
||||||
|
</div>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
||||||
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
||||||
@@ -154,12 +56,12 @@
|
|||||||
</legend>
|
</legend>
|
||||||
<div class="equipments">
|
<div class="equipments">
|
||||||
{{#each equipments as |item|}}
|
{{#each equipments as |item|}}
|
||||||
{{!log 'armor' this}}
|
|
||||||
<div class="equipment" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
|
<div class="equipment" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
|
||||||
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
|
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
|
||||||
<div class="name" data-tooltip="{{{item.system.description}}}">
|
<div class="name" data-tooltip="{{{item.system.description}}}">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</div>
|
</div>
|
||||||
|
<span class="quantity" data-tooltip="Quantity">{{item.system.quantity}}</span>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
||||||
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<nav class="tabs" data-group="sheet">
|
||||||
|
{{#each tabs}}
|
||||||
|
<a class="item {{cssClass}}" data-tab="{{id}}" data-group="{{group}}">
|
||||||
|
{{#if icon}}<i class="{{icon}}"></i> {{/if}}{{localize label}}
|
||||||
|
</a>
|
||||||
|
{{/each}}
|
||||||
|
</nav>
|
||||||
@@ -9,33 +9,12 @@
|
|||||||
<div class="weapons">
|
<div class="weapons">
|
||||||
{{#each weapons as |item|}}
|
{{#each weapons as |item|}}
|
||||||
<div class="weapon item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
|
<div class="weapon item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
|
||||||
|
|
||||||
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}} - {{upperFirst item.system.weaponType}}" />
|
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}} - {{upperFirst item.system.weaponType}}" />
|
||||||
<i class="fa-regular fa-dice"></i>
|
<div class="name" data-tooltip="{{{item.system.description}}}">
|
||||||
<div class="name rollable" data-roll-type="weapon" data-tooltip="{{{item.system.description}}}">
|
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</div>
|
</div>
|
||||||
<!-- <span class="type" data-tooltip="Type">{{upperFirst item.system.weaponType}}</span> -->
|
<span class="type" data-tooltip="Type">{{upperFirst item.system.weaponType}}</span>
|
||||||
<span class="properties" data-tooltip="Properties">{{upperFirst item.system.properties}}</span>
|
<span class="cout" data-tooltip="Coût">{{item.system.cout}}</span>
|
||||||
<span class="range" data-tooltip="Range">{{upperFirst item.system.range}}</span>
|
|
||||||
|
|
||||||
{{#if (eq item.system.weaponType "melee")}}
|
|
||||||
<span class="ammoQuantity" > </span>
|
|
||||||
<span class="ammo" ></span>
|
|
||||||
|
|
||||||
{{else}}
|
|
||||||
<span class="ammoQuantity" data-tooltip="ammoQuantity">
|
|
||||||
<i class="fa-solid fa-octagon-plus" data-action="modifyAmmo" data-quantity="1" data-item-id="{{item.id}}"></i>
|
|
||||||
{{item.system.ammoQuantity}}
|
|
||||||
<i class="fa-solid fa-octagon-minus" data-action="modifyAmmo" data-quantity="-1" data-item-id="{{item.id}}"></i>
|
|
||||||
</span>
|
|
||||||
<span class="ammo" data-tooltip="Ammo">{{upperFirst item.system.ammo}}</span>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<a class="damage rollable" data-tooltip="Damage" data-item-id="{{item.id}}" data-action="roll"
|
|
||||||
data-roll-type="damage" data-roll-value="{{item.system.damageFormula}}">
|
|
||||||
<i class="fa-regular fa-dice"></i>
|
|
||||||
{{item.system.damageFormula}}</a>
|
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
||||||
@@ -60,9 +39,8 @@
|
|||||||
<div class="name" data-tooltip="{{{item.system.description}}}">
|
<div class="name" data-tooltip="{{{item.system.description}}}">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</div>
|
</div>
|
||||||
<span class="bonus" data-tooltip="Bonus">{{item.system.bonus}}</span>
|
<span class="protection" data-tooltip="Protection">{{item.system.protection}}</span>
|
||||||
<span class="resilience" data-tooltip="Resilience">{{item.system.resilience}}</span>
|
<span class="cout" data-tooltip="Coût">{{item.system.cout}}</span>
|
||||||
<span class="reduction" data-tooltip="Reduction">{{item.system.reduction}}</span>
|
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
||||||
@@ -82,13 +60,13 @@
|
|||||||
</legend>
|
</legend>
|
||||||
<div class="equipments">
|
<div class="equipments">
|
||||||
{{#each equipments as |item|}}
|
{{#each equipments as |item|}}
|
||||||
{{!log 'armor' this}}
|
|
||||||
<div class="equipment" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
|
<div class="equipment" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
|
||||||
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
|
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
|
||||||
<div class="name" data-tooltip="{{{item.system.description}}}">
|
<div class="name" data-tooltip="{{{item.system.description}}}">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</div>
|
</div>
|
||||||
<span class="quantity" data-tooltip="Quantity">{{item.system.quantity}}</span>
|
<span class="quantity" data-tooltip="Quantity">{{item.system.quantity}}</span>
|
||||||
|
<span class="cout" data-tooltip="Coût">{{item.system.cout}}</span>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
<a data-tooltip="{{localize 'HAMALRON.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
||||||
@@ -101,27 +79,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset class="limboes">
|
|
||||||
<legend>Limboes and Ammo</legend>
|
|
||||||
<div class="limboes-line">
|
|
||||||
<div class="ammo-item">
|
|
||||||
<input type="text" class="limboes-name" value="{{system.limboes}}" name="system.limboes"/>
|
|
||||||
<span class="limboes-quantity">Limboes</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="ammo-item">
|
|
||||||
<input type="text" class="ammo" value="{{system.ammo}}" name="system.ammo"/>
|
|
||||||
<span class="limboes-quantity">Ammo</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{#each system.ammoArray as |ammo key|}}
|
|
||||||
<div class="ammo-item">
|
|
||||||
<input type="text" class="ammo-quantity" value="{{ammo.value}}" min="0" name="system.ammoArray.{{key}}.value" />
|
|
||||||
<span class="ammo-name">{{upperFirst ammo.label}}</span>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -8,9 +8,9 @@
|
|||||||
<legend>{{localize "HAMALRON.Label.sortileges"}}{{#if isEditMode}}
|
<legend>{{localize "HAMALRON.Label.sortileges"}}{{#if isEditMode}}
|
||||||
<a
|
<a
|
||||||
class="action"
|
class="action"
|
||||||
data-tooltip="{{localize 'HAMALRON.Tooltip.addMalefica'}}"
|
data-tooltip="{{localize 'HAMALRON.Tooltip.addSortilege'}}"
|
||||||
data-tooltip-direction="UP"
|
data-tooltip-direction="UP"
|
||||||
><i class="fas fa-plus" data-action="createMalefica"></i></a>{{/if}}
|
><i class="fas fa-plus" data-action="createSortilege"></i></a>{{/if}}
|
||||||
</legend>
|
</legend>
|
||||||
<div class="sortileges">
|
<div class="sortileges">
|
||||||
{{#each sortileges as |item|}}
|
{{#each sortileges as |item|}}
|
||||||
@@ -20,105 +20,21 @@
|
|||||||
data-item-uuid="{{item.uuid}}"
|
data-item-uuid="{{item.uuid}}"
|
||||||
data-drag="true"
|
data-drag="true"
|
||||||
>
|
>
|
||||||
|
|
||||||
<img
|
<img
|
||||||
class="item-img"
|
class="item-img"
|
||||||
src="{{item.img}}"
|
src="{{item.img}}"
|
||||||
data-tooltip="{{item.name}}"
|
data-tooltip="{{item.name}}"
|
||||||
/>
|
/>
|
||||||
<!--<img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />-->
|
|
||||||
<div
|
<div
|
||||||
class="name"
|
class="name"
|
||||||
data-action="toChat"
|
data-action="toChat"
|
||||||
data-item-uuid="{{item.uuid}}"
|
data-item-uuid="{{item.uuid}}"
|
||||||
data-roll-type="malefica"
|
|
||||||
data-tooltip="{{{item.system.description}}}<br>Time:{{item.system.time}}<br>Duration:{{item.system.duration}}<br>Range:{{item.system.range}}<br>Target:{{item.system.target}}"
|
|
||||||
>
|
|
||||||
<a>{{item.name}}</a>
|
|
||||||
</div>
|
|
||||||
<span class="domain" data-tooltip="Domain">{{upperFirst
|
|
||||||
item.system.domain
|
|
||||||
}}</span>
|
|
||||||
<span class="level" data-tooltip="Level">{{getRomanLevel
|
|
||||||
item.system.level
|
|
||||||
}}</span>
|
|
||||||
{{#if item.system.hasDamage}}
|
|
||||||
<a
|
|
||||||
class="damage rollable"
|
|
||||||
data-tooltip="Damage"
|
|
||||||
data-item-id="{{item.id}}"
|
|
||||||
data-action="roll"
|
|
||||||
data-roll-type="damage"
|
|
||||||
data-roll-value="{{item.system.damage}}"
|
|
||||||
>
|
|
||||||
<i class="fa-regular fa-dice"></i>
|
|
||||||
{{item.system.damage}}</a>
|
|
||||||
{{else}}
|
|
||||||
<span class="damage" data-tooltip="Damage">-</span>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<div class="controls">
|
|
||||||
<a
|
|
||||||
data-tooltip="{{localize 'HAMALRON.Edit'}}"
|
|
||||||
data-action="edit"
|
|
||||||
data-item-id="{{item.id}}"
|
|
||||||
data-item-uuid="{{item.uuid}}"
|
|
||||||
><i class="fas fa-edit"></i></a>
|
|
||||||
<a
|
|
||||||
data-tooltip="{{localize 'HAMALRON.Delete'}}"
|
|
||||||
data-action="delete"
|
|
||||||
data-item-id="{{item.id}}"
|
|
||||||
data-item-uuid="{{item.uuid}}"
|
|
||||||
><i class="fas fa-trash"></i></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.rituals"}}{{#if isEditMode}}
|
|
||||||
<a
|
|
||||||
class="action"
|
|
||||||
data-tooltip="{{localize 'HAMALRON.Tooltip.addRitual'}}"
|
|
||||||
data-tooltip-direction="UP"
|
|
||||||
><i class="fas fa-plus" data-action="createRitual"></i></a>{{/if}}
|
|
||||||
</legend>
|
|
||||||
<div class="rituals">
|
|
||||||
{{#each rituals as |item|}}
|
|
||||||
<div
|
|
||||||
class="ritual item"
|
|
||||||
data-item-id="{{item.id}}"
|
|
||||||
data-item-uuid="{{item.uuid}}"
|
|
||||||
data-drag="true"
|
|
||||||
>
|
|
||||||
|
|
||||||
<img
|
|
||||||
class="item-img"
|
|
||||||
src="{{item.img}}"
|
|
||||||
data-tooltip="{{item.name}}"
|
|
||||||
/>
|
|
||||||
<!--<img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />-->
|
|
||||||
<div
|
|
||||||
class="name"
|
|
||||||
data-action="toChat"
|
|
||||||
data-item-uuid="{{item.uuid}}"
|
|
||||||
data-roll-type="weapon"
|
|
||||||
data-tooltip="{{{item.system.description}}}"
|
data-tooltip="{{{item.system.description}}}"
|
||||||
>
|
>
|
||||||
<a>{{item.name}}</a>
|
<a>{{item.name}}</a>
|
||||||
</div>
|
</div>
|
||||||
<span class="ingredients" data-tooltip="Ingredients">{{upperFirst
|
<span class="categorie" data-tooltip="Catégorie">{{upperFirst
|
||||||
item.system.ingredients
|
item.system.categorie
|
||||||
}}</span>
|
|
||||||
<span class="difficulty" data-tooltip="Difficulty">{{upperFirst
|
|
||||||
item.system.difficulty
|
|
||||||
}}</span>
|
|
||||||
<span class="threshold" data-tooltip="Threshold">{{upperFirst
|
|
||||||
item.system.threshold
|
|
||||||
}}</span>
|
|
||||||
<span class="limit" data-tooltip="Limit">{{upperFirst
|
|
||||||
item.system.limit
|
|
||||||
}}</span>
|
}}</span>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
|
|||||||
Reference in New Issue
Block a user