12 Commits

Author SHA1 Message Date
eedce1a498 Latest fixes
All checks were successful
Release Creation / build (release) Successful in 46s
2025-09-17 07:47:40 +02:00
76a99fe33f Various fixes 2025-09-16 23:49:02 +02:00
59a39850ce Fix miracle/spell rolls + upadte compendiums
All checks were successful
Release Creation / build (release) Successful in 56s
2025-09-09 20:14:25 +02:00
6eeb391d1a Move aiming to attacker
All checks were successful
Release Creation / build (release) Successful in 1m9s
2025-09-05 23:26:11 +02:00
c7727076bf Various fixes and renamingé
All checks were successful
Release Creation / build (release) Successful in 1m30s
2025-09-02 21:06:33 +02:00
d0411f9ec9 Various fixes and renamingé 2025-09-02 18:17:31 +02:00
e5653a4edc Latest modifications & changes
All checks were successful
Release Creation / build (release) Successful in 1m47s
2025-08-31 11:28:52 +02:00
527e33a805 Roll D12 for monsters, with enabled fields for attacks
All checks were successful
Release Creation / build (release) Successful in 1m22s
2025-06-10 20:37:46 +02:00
b5857cb3b7 Various fixes for v13
All checks were successful
Release Creation / build (release) Successful in 53s
2025-06-05 16:14:25 +02:00
7a06e8a5c9 Combat tab for v13
All checks were successful
Release Creation / build (release) Successful in 1m20s
2025-05-29 18:48:33 +02:00
b4d6616cb4 Foundry v13 migration
All checks were successful
Release Creation / build (release) Successful in 58s
2025-05-14 10:02:08 +02:00
aaef4dd896 Replace and fix mortal field 2025-05-10 10:02:38 +02:00
90 changed files with 1382 additions and 806 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"COMBAT": {
"Round": "Second",
"Round": "Second {round}",
"Rounds": "Seconds",
"RoundNext": "Next second"
},
@@ -83,7 +83,7 @@
},
"challenges": {
"agility": {
"label": "Agility"
"label": "Dexterity"
},
"dying": {
"label": "Dying"
@@ -181,7 +181,7 @@
},
"challenges": {
"agility": {
"label": "Agility"
"label": "Dexterity"
},
"dying": {
"label": "Dying"
@@ -281,6 +281,7 @@
}
},
"Label": {
"agility": "Dexterity",
"gotoToken": "Go to token",
"combatAction": "Combat action",
"currentAction": "Current ongoing action",
@@ -348,7 +349,7 @@
"cha": "CHA",
"challenge": "Challenge",
"challenges": {
"agility": "Agility",
"agility": "Dexterity",
"dying": "Dying",
"strength": "Strength"
},

View File

@@ -11,12 +11,12 @@ import * as models from "./module/models/_module.mjs"
import * as documents from "./module/documents/_module.mjs"
import * as applications from "./module/applications/_module.mjs"
import { LethalFantasyCombatTracker, LethalFantasyCombat} from "./module/applications/combat.mjs"
import { LethalFantasyCombatTracker, LethalFantasyCombat } from "./module/applications/combat.mjs"
import { Macros } from "./module/macros.mjs"
import { setupTextEnrichers } from "./module/enrichers.mjs"
import { default as LethalFantasyUtils } from "./module/utils.mjs"
export class ClassCounter{static printHello(){console.log("Hello")}static sendJsonPostRequest(e,s){const t={method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(s)};return fetch(e,t).then((e=>{if(!e.ok)throw new Error("La requête a échoué avec le statut "+e.status);return e.json()})).catch((e=>{throw console.error("Erreur envoi de la requête:",e),e}))}static registerUsageCount(e=game.system.id,s={}){if(game.user.isGM){game.settings.register(e,"world-key",{name:"Unique world key",scope:"world",config:!1,default:"",type:String});let t=game.settings.get(e,"world-key");null!=t&&""!=t&&"NONE"!=t&&"none"!=t.toLowerCase()||(t=foundry.utils.randomID(32),game.settings.set(e,"world-key",t));let a={name:e,system:game.system.id,worldKey:t,version:game.system.version,language:game.settings.get("core","language"),remoteAddr:game.data.addresses.remote,nbInstalledModules:game.modules.size,nbActiveModules:game.modules.filter((e=>e.active)).length,nbPacks:game.world.packs.size,nbUsers:game.users.size,nbScenes:game.scenes.size,nbActors:game.actors.size,nbPlaylist:game.playlists.size,nbTables:game.tables.size,nbCards:game.cards.size,optionsData:s,foundryVersion:`${game.release.generation}.${game.release.build}`};this.sendJsonPostRequest("https://www.uberwald.me/fvtt_appcount/count_post.php",a)}}}
export class ClassCounter { static printHello() { console.log("Hello") } static sendJsonPostRequest(e, s) { const t = { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify(s) }; return fetch(e, t).then((e => { if (!e.ok) throw new Error("La requête a échoué avec le statut " + e.status); return e.json() })).catch((e => { throw console.error("Erreur envoi de la requête:", e), e })) } static registerUsageCount(e = game.system.id, s = {}) { if (game.user.isGM) { game.settings.register(e, "world-key", { name: "Unique world key", scope: "world", config: !1, default: "", type: String }); let t = game.settings.get(e, "world-key"); null != t && "" != t && "NONE" != t && "none" != t.toLowerCase() || (t = foundry.utils.randomID(32), game.settings.set(e, "world-key", t)); let a = { name: e, system: game.system.id, worldKey: t, version: game.system.version, language: game.settings.get("core", "language"), remoteAddr: game.data.addresses.remote, nbInstalledModules: game.modules.size, nbActiveModules: game.modules.filter((e => e.active)).length, nbPacks: game.world.packs.size, nbUsers: game.users.size, nbScenes: game.scenes.size, nbActors: game.actors.size, nbPlaylist: game.playlists.size, nbTables: game.tables.size, nbCards: game.cards.size, optionsData: s, foundryVersion: `${game.release.generation}.${game.release.build}` }; this.sendJsonPostRequest("https://www.uberwald.me/fvtt_appcount/count_post.php", a) } } }
Hooks.once("init", function () {
console.info("Lethal Fantasy RPG | Initializing System")
@@ -55,20 +55,20 @@ Hooks.once("init", function () {
}
// Register sheet application classes
Actors.unregisterSheet("core", ActorSheet)
Actors.registerSheet("lethalFantasy", applications.LethalFantasyCharacterSheet, { types: ["character"], makeDefault: true })
Actors.registerSheet("lethalFantasy", applications.LethalFantasyMonsterSheet, { types: ["monster"], makeDefault: true })
foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet)
foundry.documents.collections.Actors.registerSheet("lethalFantasy", applications.LethalFantasyCharacterSheet, { types: ["character"], makeDefault: true })
foundry.documents.collections.Actors.registerSheet("lethalFantasy", applications.LethalFantasyMonsterSheet, { types: ["monster"], makeDefault: true })
Items.unregisterSheet("core", ItemSheet)
Items.registerSheet("lethalFantasy", applications.LethalFantasySkillSheet, { types: ["skill"], makeDefault: true })
Items.registerSheet("lethalFantasy", applications.LethalFantasyGiftSheet, { types: ["gift"], makeDefault: true })
Items.registerSheet("lethalFantasy", applications.LethalFantasyVulnerabilitySheet, { types: ["vulnerability"], makeDefault: true })
Items.registerSheet("lethalFantasy", applications.LethalFantasyWeaponSheet, { types: ["weapon"], makeDefault: true })
Items.registerSheet("lethalFantasy", applications.LethalFantasySpellSheet, { types: ["spell"], makeDefault: true })
Items.registerSheet("lethalFantasy", applications.LethalFantasyArmorSheet, { types: ["armor"], makeDefault: true })
Items.registerSheet("lethalFantasy", applications.LethalFantasyShieldSheet, { types: ["shield"], makeDefault: true })
Items.registerSheet("lethalFantasy", applications.LethalFantasyEquipmentSheet, { types: ["equipment"], makeDefault: true })
Items.registerSheet("lethalFantasy", applications.LethalFantasyMiracleSheet, { types: ["miracle"], makeDefault: true })
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ActorSheet)
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasySkillSheet, { types: ["skill"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyGiftSheet, { types: ["gift"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyVulnerabilitySheet, { types: ["vulnerability"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyWeaponSheet, { types: ["weapon"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasySpellSheet, { types: ["spell"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyArmorSheet, { types: ["armor"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyShieldSheet, { types: ["shield"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyEquipmentSheet, { types: ["equipment"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyMiracleSheet, { types: ["miracle"], makeDefault: true })
// Other Document Configuration
CONFIG.ChatMessage.documentClass = documents.LethalFantasyChatMessage
@@ -89,7 +89,7 @@ Hooks.once("init", function () {
setupTextEnrichers()
LethalFantasyUtils.registerHandlebarsHelpers()
LethalFantasyUtils.setHookListeners( )
LethalFantasyUtils.setHookListeners()
console.info("LETHAL FANTASY | System Initialized")
})
@@ -105,11 +105,6 @@ function preLocalizeConfig() {
}
}
}
// CONFIG.Dice.rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
// localizeConfigObject(SYSTEM.ACTION.TAG_CATEGORIES, ["label"])
// localizeConfigObject(CONFIG.Dice.rollModes, ["label"])
}
Hooks.once("ready", function () {
@@ -133,7 +128,7 @@ Hooks.once("ready", function () {
// Test if version below 13
let hookName = "renderChatMessage"
if (foundry.utils.isNewerVersion(game.version, "12.0", )) {
if (foundry.utils.isNewerVersion(game.version, "12.0",)) {
hookName = "renderChatMessageHTML"
}
Hooks.on(hookName, (message, html, data) => {

View File

@@ -1,18 +1,54 @@
/* -------------------------------------------- */
export class LethalFantasyCombatTracker extends CombatTracker {
export class LethalFantasyCombatTracker extends foundry.applications.sidebar.tabs.CombatTracker {
async getData(options) {
let data = await super.getData(options);
for (let u of data.turns) {
static PARTS = {
"header": {
"template": "systems/fvtt-lethal-fantasy/templates/combat-tracker-header-v2.hbs"
},
"tracker": {
"template": "systems/fvtt-lethal-fantasy/templates/combat-tracker-v2.hbs"
},
"footer": {
"template": "systems/fvtt-lethal-fantasy/templates/combat-tracker-footer-v2.hbs"
}
}
static DEFAULT_OPTIONS = foundry.utils.mergeObject(super.DEFAULT_OPTIONS, {
actions: {
initiativePlus: LethalFantasyCombatTracker.#initiativePlus,
initiativeMinus: LethalFantasyCombatTracker.#initiativeMinus,
},
});
async _prepareContext(options) {
let data = await super._prepareContext(options);
console?.log("Combat Tracker Data", data);
/*for (let u of data.turns) {
let c = game.combat.combatants.get(u.id);
u.progressionCount = c.system.progressionCount
u.isMonster = c.actor.type === "monster"
}
console.log("Combat Data", data);
console.log("Combat Data", data);*/
return data;
}
static #initiativePlus(ev) {
ev.preventDefault();
let cId = ev.target.closest(".combatant").dataset.combatantId;
let c = game.combat.combatants.get(cId);
c.update({ 'initiative': c.initiative + 1 });
console.log("Initiative Plus");
}
static #initiativeMinus(ev) {
ev.preventDefault();
let cId = ev.target.closest(".combatant").dataset.combatantId;
let c = game.combat.combatants.get(cId);
let newInit = Math.max(c.initiative - 1, 0);
c.update({ 'initiative': newInit });
}
activateListeners(html) {
super.activateListeners(html);
// Display Combat settings
@@ -21,7 +57,6 @@ export class LethalFantasyCombatTracker extends CombatTracker {
let cId = ev.currentTarget.closest(".combatant").dataset.combatantId;
let c = game.combat.combatants.get(cId);
c.update({ 'initiative': c.initiative + 1 });
console.log("Initiative Plus");
});
html.find(".initiative-minus").click(ev => {
@@ -160,10 +195,10 @@ export class LethalFantasyCombat extends Combat {
}
for (let c of this.combatants) {
if ( nextRound >= c.initiative) {
if (nextRound >= c.initiative) {
let user = game.users.find(u => u.active && u.character && u.character.id === c.actor.id);
if (user?.hasPlayerOwner) {
game.socket.emit(`system.${SYSTEM.id}`, { type: "rollProgressionDice", progressionCount: c.system.progressionCount+1, actorId: c.actor.id, combatId: this.id, combatantId: c.id });
game.socket.emit(`system.${SYSTEM.id}`, { type: "rollProgressionDice", progressionCount: c.system.progressionCount + 1, actorId: c.actor.id, combatId: this.id, combatantId: c.id });
} else {
user = game.users.find(u => u.active && u.isGM);
c.actor.system.rollProgressionDice(this.id, c.id);

View File

@@ -23,7 +23,7 @@ export default class LethalFantasyArmorSheet extends LethalFantasyItemSheet {
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
return context
}

View File

@@ -67,7 +67,7 @@ export default class LethalFantasyActorSheet extends HandlebarsApplicationMixin(
actor: this.document,
system: this.document.system,
source: this.document.toObject(),
enrichedDescription: await TextEditor.enrichHTML(this.document.system.description, { async: true }),
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true }),
isEditMode: this.isEditMode,
isPlayMode: this.isPlayMode,
isEditable: this.isEditable,
@@ -100,7 +100,7 @@ export default class LethalFantasyActorSheet extends HandlebarsApplicationMixin(
dragover: this._onDragOver.bind(this),
drop: this._onDrop.bind(this),
}
return new DragDrop(d)
return new foundry.applications.ux.DragDrop.implementation(d)
})
}
@@ -140,7 +140,7 @@ export default class LethalFantasyActorSheet extends HandlebarsApplicationMixin(
if ("link" in event.target.dataset) return
const el = event.currentTarget.closest('[data-drag="true"]')
const dragType = el.dataset.dragType
const dragType = el?.dataset?.dragType
let dragData = {}

View File

@@ -58,22 +58,22 @@ export default class LethalFantasyItemSheet extends HandlebarsApplicationMixin(f
/** @override */
async _prepareContext() {
const context = {
fields: this.document.schema.fields,
systemFields: this.document.system.schema.fields,
item: this.document,
system: this.document.system,
source: this.document.toObject(),
enrichedDescription: await TextEditor.enrichHTML(this.document.system.description, { async: true }),
isEditMode: this.isEditMode,
isPlayMode: this.isPlayMode,
isEditable: this.isEditable,
}
let context = await super._prepareContext()
context.fields = this.document.schema.fields
context.systemFields = this.document.system.schema.fields
context.item = this.document
context.system = this.document.system
context.source = this.document.toObject()
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
context.isEditMode = this.isEditMode
context.isPlayMode = this.isPlayMode
context.isEditable = this.isEditable
return context
}
/** @override */
_onRender(context, options) {
super._onRender(context, options)
this.#dragDrop.forEach((d) => d.bind(this.element))
}
@@ -94,7 +94,7 @@ export default class LethalFantasyItemSheet extends HandlebarsApplicationMixin(f
dragover: this._onDragOver.bind(this),
drop: this._onDrop.bind(this),
}
return new DragDrop(d)
return new foundry.applications.ux.DragDrop.implementation(d)
})
}

View File

@@ -90,9 +90,6 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
return context
}
_generateTooltip(type, target) {
}
/** @override */
async _preparePartContext(partId, context) {
const doc = this.document
@@ -127,8 +124,8 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
break
case "biography":
context.tab = context.tabs.biography
context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true })
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.description, { async: true })
context.enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.notes, { async: true })
break
}
return context
@@ -143,18 +140,17 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
*/
async _onDrop(event) {
if (!this.isEditable || !this.isEditMode) return
const data = TextEditor.getDragEventData(event)
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)
// Handle different data types
switch (data.type) {
case "Item":
const item = await fromUuid(data.uuid)
return this._onDropItem(item)
if (data.type === "Item") {
const item = await fromUuid(data.uuid)
return this._onDropItem(item)
}
}
static async #onRangedAttackDefense(event, target) {
const hasTarget = false
// Future use : const hasTarget = false
let roll = await LethalFantasyRoll.promptRangedDefense({
actorId: this.actor.id,

View File

@@ -22,7 +22,7 @@ export default class LethalFantasyEquipmentSheet extends LethalFantasyItemSheet
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
return context
}
}

View File

@@ -19,10 +19,4 @@ export default class LethalFantasyGiftSheet extends LethalFantasyItemSheet {
},
}
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
return context
}
}

View File

@@ -22,7 +22,7 @@ export default class LethalFantasyMiracleSheet extends LethalFantasyItemSheet {
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
return context
}

View File

@@ -63,9 +63,6 @@ export default class LethalFantasyMonsterSheet extends LethalFantasyActorSheet {
return context
}
_generateTooltip(type, target) {
}
/** @override */
async _preparePartContext(partId, context) {
const doc = this.document
@@ -78,8 +75,8 @@ export default class LethalFantasyMonsterSheet extends LethalFantasyActorSheet {
break
case "biography":
context.tab = context.tabs.biography
context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true })
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.description, { async: true })
context.enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.notes, { async: true })
break
}
return context

View File

@@ -22,7 +22,7 @@ export default class LethalFantasyShieldSheet extends LethalFantasyItemSheet {
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
return context
}
}

View File

@@ -22,7 +22,7 @@ export default class LethalFantasySkillSheet extends LethalFantasyItemSheet {
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
return context
}
}

View File

@@ -22,7 +22,7 @@ export default class LethalFantasySpellSheet extends LethalFantasyItemSheet {
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
return context
}

View File

@@ -22,7 +22,7 @@ export default class LethalFantasyVulnerabilitySheet extends LethalFantasyItemSh
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
return context
}
}

View File

@@ -18,11 +18,11 @@ export default class LethalFantasyWeaponSheet extends LethalFantasyItemSheet {
template: "systems/fvtt-lethal-fantasy/templates/weapon.hbs",
},
}
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
return context
}

View File

@@ -44,73 +44,64 @@ export const MONEY = {
}
export const MORTAL_CHOICES = {
"mankind": {label: "Mankind", value: "Mankind", defenseBonus: 0},
"elf": {label: "Elf", value: "Elf", defenseBonus: 0},
"dwarf": {label: "Dwarf", value: "Dwarf", defenseBonus: 0},
"halfelf": {label: "Half-Elf", value: "Half-Elf", defenseBonus: 0},
"halforc": {label: "Half-Orc", value: "Half-Orc", defenseBonus: 0},
"gnome": {label: "Gnome", value: "Gnome", defenseBonus: 2},
"shirefolk": {label: "Shire Folk", value: "Shire Folk", defenseBonus: 2},
"Elf": {label: "Elf", value: "Elf", defenseBonus: 0},
"Half-orc": {label: "Half-Orc", value: "Half-Orc", defenseBonus: 0},
"Half-Orc": {label: "Half-Orc", value: "Half-Orc", defenseBonus: 0},
"Dwarf": {label: "Dwarf", value: "Dwarf", defenseBonus: 0},
"Half-elf": {label: "Half-Elf", value: "Half-Elf", defenseBonus: 0},
"Gnome": {label: "Gnome", value: "Gnome", defenseBonus: 2},
"Shire Folk": {label: "Shire Folk", value: "Shire Folk", defenseBonus: 2},
"Shire folk": {label: "Shire Folk", value: "Shire Folk", defenseBonus: 2},
"Mankind": {label: "Human", value: "Human", defenseBonus: 0},
"mankind": { label: "Mankind", id: "mankind", defenseBonus: 0 },
"elf": { label: "Elf", id: "elf", defenseBonus: 0 },
"dwarf": { label: "Dwarf", id: "dwarf", defenseBonus: 0 },
"halfelf": { label: "Half-Elf", id: "halfelf", defenseBonus: 0 },
"halforc": { label: "Half-Orc", id: "halforc", defenseBonus: 0 },
"gnome": { label: "Gnome", id: "gnome", defenseBonus: 2 },
"halflings": { label: "Halfling", id: "halflings", defenseBonus: 2 }
}
export const FAVOR_CHOICES = {
"none": {label: "None", value: "none"},
"favor": {label: "Favor", value: "favor"},
"disfavor": {label: "Disfavor", value: "disfavor"}
"none": { label: "None", value: "none" },
"favor": { label: "Favor", value: "favor" },
"disfavor": { label: "Disfavor", value: "disfavor" }
}
export const MOVEMENT_CHOICES = {
"none": {label: "None (D8E)", value: "D8"},
"walk": {label: "Walk (D10E)", value: "D10"},
"jog": {label: "Jog (D12E)", value: "D12"},
"run": {label: "Run (D20E)", value: "D20"},
"incombat": {label: "In Combat (D12E)", value: "D12"}
"none": { label: "None (D20E Disfavor)", disfavor: true, value: "2D20kl" },
"walk": { label: "Walk (D20E)", disfavor: true, value: "D20" },
"incombat": { label: "In Combat (D20E)", favor: false, value: "D20" },
"run": { label: "Jog/Run/Sprint (D20E Favor)", favor: true, value: "2D20kh" }
}
export const MOVE_DIRECTION_CHOICES = {
"none": {label: "None (+0)", value: "0"},
"away": {label: "Away (+4)", value: "+4"},
"toward": {label: "Toward (+0)", value: "0"},
"lateral": {label: "Lateral (+10)", value: "+10"}
"away": { label: "Away (+0)", value: "+0" },
"toward": { label: "Toward (0)", value: "0" },
"lateral": { label: "Lateral (Red +5)", value: "+5" },
"none": { label: "None (+0)", value: "0" },
}
export const SIZE_CHOICES = {
"tiny": {label: "Tiny (+10)", value: "+10"},
"small": {label: "Small (+5)", value: "+5"},
"medium": {label: "Medium (+0)", value: "0"},
"huge": {label: "Huge (-10)", value: "-10"}
"tiny": { label: "Tiny (Blue +11)", value: "+11" },
"small": { label: "Small (Purple +7)", value: "+7" },
"medium": { label: "Medium (Red +5)", value: "+5" },
"large": { label: "Large (Yellow +1)", value: "+1" },
"huge": { label: "Huge (0)", value: "0" }
}
export const RANGE_CHOICES = {
"pointblank": {label: "Point Blank (-5)", value: "-5"},
"short": {label: "Short (+0)", value: "0"},
"medium": {label: "Medium (+8)", value: "+8"},
"long": {label: "Long (+15)", value: "+15"},
"extreme": {label: "Extreme (+20)", value: "+20"},
"beyondskill": {label: "Beyond Skill (+25)", value: "+25"}
"pointblank": { label: "Point Blank (Special)", value: "pointblank" },
"short": { label: "Short (+0)", value: "0" },
"medium": { label: "Medium (Red +5)", value: "+5" },
"long": { label: "Long (Purle +7)", value: "+7" },
"extreme": { label: "Extreme (Grey +9)", value: "+9" },
"beyondskill": { label: "Beyond Skill (Blue +11)", value: "beyondskill" }
}
export const ATTACKER_AIM_CHOICES = {
"simple": {label: "Simple (+0)", value: "0"},
"careful": {label: "Careful (-4)", value: "-4"},
"focused": {label: "Focused (-8)", value: "-8"}
"simple": { label: "Simple (+0)", value: "0" },
"careful": { label: "Careful (Red +5)", value: "+4" },
"focused": { label: "Focused (Grey +9)", value: "+9" }
}
export const SPELL_LETHARGY_DICE = [
{dice: "D6", level: "1-5", value: "6", maxLevel: 5},
{dice: "D8", level: "6-10", value: "8", maxLevel: 10},
{dice: "D10", value: "10", level: "11-15", maxLevel: 15},
{dice: "D12", value: "12", level: "16-20", maxLevel: 20},
{dice: "D20", value: "20", level: "21-25", maxLevel: 25}
{ dice: "D6", level: "1-5", value: "6", maxLevel: 5 },
{ dice: "D8", level: "6-10", value: "8", maxLevel: 10 },
{ dice: "D10", value: "10", level: "11-15", maxLevel: 15 },
{ dice: "D12", value: "12", level: "16-20", maxLevel: 20 },
{ dice: "D20", value: "20", level: "21-25", maxLevel: 25 }
]
export const INITIATIVE_DICE_CHOICES_PER_CLASS = {
@@ -118,44 +109,44 @@ export const INITIATIVE_DICE_CHOICES_PER_CLASS = {
{ "name": "Asleep or totally distracted (2D12)", "value": "2D12" },
{ "name": "Awake but unsuspecting (2D8)", "value": "2D8" },
{ "name": "Declared Ready on Alert (2D6)", "value": "2D6" },
{ "name": "Aware of the enemy, can hear them but not see (2D4)", "value": "2D4" },
{ "name": "Aware and know exactly where the enemy is (2D3)", "value": "2D3" }
/*{ "name": "Aware of the enemy, can hear them but not see (2D4)", "value": "2D4" },
{ "name": "Aware and know exactly where the enemy is (2D3)", "value": "2D3" }*/
],
"fighter": [
{ "name": "Asleep or totally distracted (1D12)", "value": "1D12" },
{ "name": "Awake but unsuspecting (1D8)", "value": "1D8" },
{ "name": "Declared Ready on Alert (1D6)", "value": "1D6" },
{ "name": "Aware of the enemy, can hear them but not see (1D4)", "value": "1D4" },
{ "name": "Aware and know exactly where the enemy is (1D3)", "value": "1D3" }
{ "name": "Declared Ready on Alert (1)", "value": "1" },
/*{ "name": "Aware of the enemy, can hear them but not see (1D4)", "value": "1D4" },
{ "name": "Aware and know exactly where the enemy is (1D3)", "value": "1D3" }*/
],
"rogue": [
{ "name": "Asleep or totally distracted (1D10)", "value": "1D10" },
{ "name": "Awake but unsuspecting (1D8)", "value": "1D8" },
{ "name": "Declared Ready on Alert (1D6)", "value": "1D6" },
{ "name": "Aware of the enemy, can hear them but not see (1D3)", "value": "1D3" },
{ "name": "Aware and know exactly where the enemy is (1D2)", "value": "1D2" }
{ "name": "Declared Ready on Alert (1)", "value": "1" },
/*{ "name": "Aware of the enemy, can hear them but not see (1D3)", "value": "1D3" },
{ "name": "Aware and know exactly where the enemy is (1D2)", "value": "1D2" }*/
],
"ranger": [
{ "name": "Asleep or totally distracted (1D10)", "value": "1D10" },
{ "name": "Awake but unsuspecting (1D8)", "value": "1D8" },
{ "name": "Declared Ready on Alert (1D6)", "value": "1D6" },
{ "name": "Aware of the enemy, can hear them but not see (1D4)", "value": "1D4" },
{ "name": "Aware and know exactly where the enemy is (1D3)", "value": "1D3"}
{ "name": "Declared Ready on Alert (1)", "value": "1" },
/*{ "name": "Aware of the enemy, can hear them but not see (1D4)", "value": "1D4" },
{ "name": "Aware and know exactly where the enemy is (1D3)", "value": "1D3" }*/
],
"cleric": [
{ "name": "Asleep or totally distracted (1D12)", "value": "1D12" },
{ "name": "Awake but unsuspecting (1D10)", "value": "1D10" },
{ "name": "Declared Ready on Alert (1D8)", "value": "1D8" },
{ "name": "Aware of the enemy, can hear them but not see (1D6)", "value": "1D6" },
{ "name": "Aware and know exactly where the enemy is (1D4)", "value": "1D4" }
{ "name": "Declared Ready on Alert (1)", "value": "1" },
/*{ "name": "Aware of the enemy, can hear them but not see (1D6)", "value": "1D6" },
{ "name": "Aware and know exactly where the enemy is (1D4)", "value": "1D4" }*/
],
"magicuser": [
{ "name": "Sleeping to recover Aether Points (2D20)", "value": "2D20" },
{ "name": "Asleep or totally distracted (1D20)", "value": "1D20" },
{ "name": "Awake but unsuspecting (1D12)", "value": "1D12" },
{ "name": "Declared Ready on Alert (1D10)", "value": "1D10" },
{ "name": "Aware of the enemy, can hear them but not see (1D8)", "value": "1D8" },
{ "name": "Aware and know exactly where the enemy is (1D6)", "value": "1D6" }
{ "name": "Declared Ready on Alert (1)", "value": "1" },
/*{ "name": "Aware of the enemy, can hear them but not see (1D8)", "value": "1D8" },
{ "name": "Aware and know exactly where the enemy is (1D6)", "value": "1D6" }*/
]
}
@@ -169,12 +160,12 @@ export const CHAR_CLASSES = {
}
export const CHAR_CLASSES_DEFINES = {
"untrained": {id: "untrained", label: "Untrained"},
"fighter": {id: "fighter", label: "Fighter"},
"rogue": {id: "rogue", label: "Rogue"},
"ranger": {id: "ranger", label: "Ranger"},
"cleric": {id: "cleric", label: "Cleric"},
"magicuser": {id: "magicuser", label: "Magic User"}
"untrained": { id: "untrained", label: "Untrained" },
"fighter": { id: "fighter", label: "Fighter" },
"rogue": { id: "rogue", label: "Rogue" },
"ranger": { id: "ranger", label: "Ranger" },
"cleric": { id: "cleric", label: "Cleric" },
"magicuser": { id: "magicuser", label: "Magic User" }
}
export const DICE_VALUES = {
@@ -187,10 +178,10 @@ export const DICE_VALUES = {
"d20": "D20"
}
export const CHARACTERISTIC_ATTACK = [ "str", "int", "wis", "dex"]
export const CHARACTERISTIC_RANGED_ATTACK = [ "int", "wis", "dex"]
export const CHARACTERISTIC_DEFENSE = [ "int", "wis", "dex" ]
export const CHARACTERISTIC_DAMAGE = [ "str" ]
export const CHARACTERISTIC_ATTACK = ["str", "int", "wis", "dex"]
export const CHARACTERISTIC_RANGED_ATTACK = ["int", "wis", "dex"]
export const CHARACTERISTIC_DEFENSE = ["int", "wis", "dex"]
export const CHARACTERISTIC_DAMAGE = ["str"]
export const DEFENSE_DICE_VALUES = {
"0": "0",
@@ -226,41 +217,41 @@ export const SPELL_CRITICAL = {
}
export const CHOICE_MODIFIERS = {
"-9": "-9",
"-8": "-8",
"-7": "-7",
"-6": "-6",
"-5": "-5",
"-4": "-4",
"-3": "-3",
"-2": "-2",
"-1": "-1",
"+0": "0",
"+1": "+1",
"+2": "+2",
"+3": "+3",
"+4": "+4",
"+5": "+5",
"+6": "+6",
"+7": "+7",
"+8": "+8",
"+9": "+9",
"+10": "+10",
"+11": "+11",
"+12": "+12",
"+13": "+13",
"+14": "+14",
"+15": "+15",
"+16": "+16",
"+17": "+17",
"+18": "+18",
"+19": "+19",
"+20": "+20",
"+21": "+21",
"+22": "+22",
"+23": "+23",
"+24": "+24",
"+25": "+25"
"-9": "-9",
"-8": "-8",
"-7": "-7",
"-6": "-6",
"-5": "-5",
"-4": "-4",
"-3": "-3",
"-2": "-2",
"-1": "-1",
"+0": "0",
"+1": "+1",
"+2": "+2",
"+3": "+3",
"+4": "+4",
"+5": "+5",
"+6": "+6",
"+7": "+7",
"+8": "+8",
"+9": "+9",
"+10": "+10",
"+11": "+11",
"+12": "+12",
"+13": "+13",
"+14": "+14",
"+15": "+15",
"+16": "+16",
"+17": "+17",
"+18": "+18",
"+19": "+19",
"+20": "+20",
"+21": "+21",
"+22": "+22",
"+23": "+23",
"+24": "+24",
"+25": "+25"
}
export const ASCII = `

View File

@@ -96,6 +96,10 @@ export default class LethalFantasyRoll extends Roll {
return this.options.badResult
}
get rollData() {
return this.options.rollData
}
/**
* Prompt the user with a dialog to configure and execute a roll.
*
@@ -124,6 +128,9 @@ export default class LethalFantasyRoll extends Roll {
let hasFavor = false
let hasMaxValue = true
let hasGrantedDice = false
let pointBlank = false
let letItFly = false
let beyondSkill = false
let hasStaticModifier = false
let hasExplode = true
@@ -132,13 +139,11 @@ export default class LethalFantasyRoll extends Roll {
hasD30 = options.rollType === "save"
if (options.rollTarget.rollKey === "dying") {
dice = options.rollTarget.value
maxValue = Number(options.rollTarget.value.match(/\d+/)[0])
hasModifier = false
hasChangeDice = true
hasFavor = true
} else {
dice = "1D20"
maxValue = 20
hasFavor = true
}
@@ -148,7 +153,6 @@ export default class LethalFantasyRoll extends Roll {
dice = options.rollTarget.formula
baseFormula = options.rollTarget.formula
hasModifier = false
maxValue = 100
hasMaxValue = false
hasChangeDice = false
hasFavor = false
@@ -158,7 +162,6 @@ export default class LethalFantasyRoll extends Roll {
options.rollName = options.rollTarget.name
dice = "1D20"
baseFormula = "D20"
maxValue = 20
hasModifier = true
hasChangeDice = false
hasFavor = true
@@ -172,29 +175,27 @@ export default class LethalFantasyRoll extends Roll {
} else if (options.rollType === "monster-skill") {
options.rollName = game.i18n.localize(`LETHALFANTASY.Label.${options.rollTarget.rollKey}`)
dice = "1D100"
baseFormula = "D100"
maxValue = 100
dice = "1D20"
baseFormula = "D20"
hasModifier = true
hasFavor = true
hasChangeDice = false
} else if (options.rollType === "skill") {
options.rollName = options.rollTarget.name
dice = "1D100"
baseFormula = "D100"
maxValue = 100
hasD30 = true
dice = "1D20"
baseFormula = "D20"
hasModifier = true
hasFavor = true
hasChangeDice = false
options.rollTarget.value = options.rollTarget.system.skillTotal
options.rollTarget.value = Math.floor(options.rollTarget.system.skillTotal / 10)
} else if (options.rollType === "weapon-attack" || options.rollType === "weapon-defense") {
hasD30 = true
options.rollName = options.rollTarget.name
dice = "1D20"
baseFormula = "D20"
maxValue = 20
hasModifier = true
hasChangeDice = false
hasFavor = true
@@ -216,7 +217,6 @@ export default class LethalFantasyRoll extends Roll {
options.rollName = options.rollTarget.name
dice = "1D20"
baseFormula = "D20"
maxValue = 20
hasModifier = true
hasChangeDice = false
options.rollTarget.value = options.rollTarget.actorModifiers.levelSpellModifier + options.rollTarget.actorModifiers.intSpellModifier
@@ -234,7 +234,6 @@ export default class LethalFantasyRoll extends Roll {
options.rollName = options.rollTarget.name
dice = "1D20"
baseFormula = "D20"
maxValue = 20
hasChangeDice = false
options.rollTarget.value = options.rollTarget.actorModifiers.levelMiracleModifier + options.rollTarget.actorModifiers.chaMiracleModifier
options.rollTarget.charModifier = options.rollTarget.actorModifiers.chaMiracleModifier
@@ -271,7 +270,6 @@ export default class LethalFantasyRoll extends Roll {
}
dice = dice.replace("E", "")
baseFormula = dice
maxValue = 20
} else if (options.rollType.includes("monster-damage")) {
options.rollName = options.rollTarget.name
@@ -282,7 +280,6 @@ export default class LethalFantasyRoll extends Roll {
dice = options.rollTarget.damageDice
dice = dice.replace("E", "")
baseFormula = dice
maxValue = 20
}
@@ -292,8 +289,7 @@ export default class LethalFantasyRoll extends Roll {
hasModifier = false
}
console.log("Roll mode", CONFIG.Dice.rollModes)
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
console.log("Roll mode", rollModes)
const fieldRollMode = new foundry.data.fields.StringField({
@@ -318,7 +314,10 @@ export default class LethalFantasyRoll extends Roll {
hasModifier,
hasFavor,
hasChangeDice,
pointBlank,
baseValue: options.rollTarget.value,
attackerAimChoices: SYSTEM.ATTACKER_AIM_CHOICES,
attackerAim: "0",
changeDice: `${dice}`,
fieldRollMode,
choiceModifier,
@@ -332,7 +331,7 @@ export default class LethalFantasyRoll extends Roll {
favor: "none",
targetName
}
const content = await renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-dialog.hbs", dialogContext)
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-dialog.hbs", dialogContext)
let position = game.user.getFlag(SYSTEM.id, "roll-dialog-pos") || { top: -1, left: -1 }
const label = game.i18n.localize("LETHALFANTASY.Roll.roll")
@@ -345,7 +344,8 @@ export default class LethalFantasyRoll extends Roll {
{
label: label,
callback: (event, button, dialog) => {
let position = $(dialog).position()
console.log("Roll context", event, button, dialog)
let position = dialog.position
game.user.setFlag(SYSTEM.id, "roll-dialog-pos", foundry.utils.duplicate(position))
const output = Array.from(button.form.elements).reduce((obj, input) => {
if (input.name) obj[input.name] = input.value
@@ -359,7 +359,16 @@ export default class LethalFantasyRoll extends Roll {
"selectGranted": (event, button, dialog) => {
hasGrantedDice = true
},
"gotoToken" : (event, button, dialog) => {
"selectBeyondSkill": (event, button, dialog) => {
beyondSkill = button.checked
},
"selectPointBlank": (event, button, dialog) => {
pointBlank = button.checked
},
"selectLetItFly": (event, button, dialog) => {
letItFly = button.checked
},
"gotoToken": (event, button, dialog) => {
let tokenId = $(button).data("tokenId")
let token = canvas.tokens?.get(tokenId)
if (token) {
@@ -383,16 +392,15 @@ export default class LethalFantasyRoll extends Roll {
let bonus = Number(options.rollTarget.value)
fullModifier = rollContext.modifier === "" ? 0 : parseInt(rollContext.modifier, 10) + bonus
fullModifier += (rollContext.saveSpell) ? options.rollTarget.actorModifiers.saveModifier : 0
if (Number(rollContext.attackerAim) > 0) {
fullModifier += Number(rollContext.attackerAim)
}
if (fullModifier === 0) {
modifierFormula = "0"
} else {
if (options.rollType === "skill" || options.rollType === "monster-skill") {
modifierFormula = `${fullModifier}`
} else {
let modAbs = Math.abs(fullModifier)
modifierFormula = `D${modAbs + 1} - 1`
}
let modAbs = Math.abs(fullModifier)
modifierFormula = `D${modAbs + 1} - 1`
}
if (hasStaticModifier) {
modifierFormula += ` + ${options.rollTarget.staticModifier}`
@@ -415,6 +423,14 @@ export default class LethalFantasyRoll extends Roll {
}
}
// Latest addition : favor choice at point blank range
if (pointBlank) {
rollContext.favor = "favor"
}
if (beyondSkill) {
rollContext.favor = "disfavor"
}
// Specific pain case
if (options.rollType === "save" && options.rollTarget.rollKey === "pain" || options.rollTarget.rollKey === "paincourage") {
baseFormula = options.rollTarget.rollDice
@@ -426,6 +442,18 @@ export default class LethalFantasyRoll extends Roll {
// Specific pain/poison/contagion case
if (options.rollType === "save" && (options.rollTarget.rollKey === "pain" || options.rollTarget.rollKey === "paincourage" || options.rollTarget.rollKey === "poison" || options.rollTarget.rollKey === "contagion")) {
hasD30 = false
hasStaticModifier = true
modifierFormula = ` + ${Math.abs(fullModifier)}`
}
if (letItFly) {
baseFormula = "1D20"
titleFormula = `1D20E`
modifierFormula = "0"
fullModifier = 0
hasFavor = false
hasExplode = true
rollContext.favor = "none"
}
maxValue = Number(baseFormula.match(/\d+$/)[0]) // Update the max value agains
@@ -440,6 +468,9 @@ export default class LethalFantasyRoll extends Roll {
actorImage: options.actorImage,
rollMode: rollContext.visibility,
hasTarget: options.hasTarget,
pointBlank,
beyondSkill,
letItFly,
hasGrantedDice,
titleFormula,
targetName,
@@ -552,6 +583,7 @@ export default class LethalFantasyRoll extends Roll {
rollBase.options.titleFormula = titleFormula
rollBase.options.D30result = options.D30result
rollBase.options.badResult = badResult
rollBase.options.rollData = foundry.utils.duplicate(rollData)
/**
* A hook event that fires after the roll has been made.
@@ -569,7 +601,7 @@ export default class LethalFantasyRoll extends Roll {
/* ***********************************************************/
static async promptInitiative(options = {}) {
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
const fieldRollMode = new foundry.data.fields.StringField({
choices: rollModes,
blank: false,
@@ -592,7 +624,7 @@ export default class LethalFantasyRoll extends Roll {
}
console.log("CTX", dialogContext)
const content = await renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-initiative-dialog.hbs", dialogContext)
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-initiative-dialog.hbs", dialogContext)
const label = game.i18n.localize("LETHALFANTASY.Label.initiative")
const rollContext = await foundry.applications.api.DialogV2.wait({
@@ -631,7 +663,7 @@ export default class LethalFantasyRoll extends Roll {
/* ***********************************************************/
static async promptCombatAction(options = {}) {
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
const fieldRollMode = new foundry.data.fields.StringField({
choices: rollModes,
blank: false,
@@ -655,7 +687,7 @@ export default class LethalFantasyRoll extends Roll {
...options
}
const content = await renderTemplate("systems/fvtt-lethal-fantasy/templates/combat-action-dialog.hbs", dialogContext)
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-lethal-fantasy/templates/combat-action-dialog.hbs", dialogContext)
let buttons = []
if (currentAction) {
@@ -769,7 +801,7 @@ export default class LethalFantasyRoll extends Roll {
await combatant.setFlag(SYSTEM.id, "currentAction", actionItem)
let message = `${combatant.name} action : ${selectedItem.name}, start rolling progression dice or casting time`
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
rollContext = (actionItem.type == "weapon") ? "rollProgressionDice" : "rollLethargyDice" // Set the roll context to rollProgressionDice
rollContext = (actionItem.type === "weapon") ? "rollProgressionDice" : "rollLethargyDice" // Set the roll context to rollProgressionDice
currentAction = actionItem
}
@@ -890,7 +922,7 @@ export default class LethalFantasyRoll extends Roll {
/* ***********************************************************/
static async promptRangedDefense(rollTarget) {
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
const fieldRollMode = new foundry.data.fields.StringField({
choices: rollModes,
blank: false,
@@ -913,7 +945,7 @@ export default class LethalFantasyRoll extends Roll {
}
console.log("CTX", dialogContext)
const content = await renderTemplate("systems/fvtt-lethal-fantasy/templates/range-defense-dialog.hbs", dialogContext)
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-lethal-fantasy/templates/range-defense-dialog.hbs", dialogContext)
const label = game.i18n.localize("LETHALFANTASY.Label.rangeDefenseRoll")
const rollContext = await foundry.applications.api.DialogV2.wait({
@@ -935,25 +967,39 @@ export default class LethalFantasyRoll extends Roll {
rejectClose: false // Click on Close button will not launch an error
})
// If the user cancels the dialog, exit
if (rollContext === null) return
console.log("RollContext", rollContext)
// Add disfavor/favor option if point blank range
if (rollContext.range === "pointblank") {
rollContext.movement = rollContext.movement.replace("kh", "")
rollContext.movement = rollContext.movement.replace("kl", "")
rollContext.movement += "kl" // Add the kl to the movement (disfavor for point blank range)
rollContext.range = "0"
}
if (rollContext.range === "beyondskill") {
rollContext.movement = rollContext.movement.replace("kh", "")
rollContext.movement = rollContext.movement.replace("kl", "")
rollContext.movement += "kh" // Add the kl to the movement (favor for point blank range)
rollContext.range = "+11"
}
// Build the final modifier
let fullModifier = Number(rollContext.moveDirection) +
Number(rollContext.size) +
Number(rollContext.range) +
Number(rollContext.attackerAim)
console.log("Modifier", fullModifier)
Number(rollContext?.attackerAim || 0)
console.log("Modifier", fullModifier, rollContext)
let modifierFormula
if (fullModifier === 0) {
modifierFormula = "0"
} else {
let modAbs = Math.abs(fullModifier)
modifierFormula = `${modAbs}`
modifierFormula = `D${modAbs+1} -1`
}
// If the user cancels the dialog, exit
if (rollContext === null) return
let rollData = { ...rollContext }
let options = { ...rollContext }
options.rollName = "Ranged Defense"
@@ -965,8 +1011,15 @@ export default class LethalFantasyRoll extends Roll {
let rollD30 = await new Roll("1D30").evaluate()
options.D30result = rollD30.total
if (rollContext.movement.includes("kh")) {
rollData.favor = "favor"
}
if (rollContext.movement.includes("kl")) {
rollData.favor = "disfavor"
}
let dice = rollContext.movement
let maxValue = Number(dice.match(/\d+$/)[0]) // Update the max value agains
let maxValue = 20 // As per latest changes (was : Number(dice.match(/\d+$/)[0])
let rollTotal = -1
let diceResults = []
let resultType
@@ -998,7 +1051,7 @@ export default class LethalFantasyRoll extends Roll {
rollBase.options.titleFormula = `${dice}E + ${modifierFormula}`
rollBase.options.D30result = options.D30result
rollBase.options.rollName = "Ranged Defense"
rollBase.options.rollData = foundry.utils.duplicate(rollData)
/**
* A hook event that fires after the roll has been made.
* @function
@@ -1053,7 +1106,7 @@ export default class LethalFantasyRoll extends Roll {
async render(chatOptions = {}) {
let chatData = await this._getChatCardData(chatOptions.isPrivate)
console.log("ChatData", chatData)
return await renderTemplate(this.constructor.CHAT_TEMPLATE, chatData)
return await foundry.applications.handlebars.renderTemplate(this.constructor.CHAT_TEMPLATE, chatData)
}
/*
@@ -1082,6 +1135,7 @@ export default class LethalFantasyRoll extends Roll {
targetArmor: this.targetArmor,
D30result: this.D30result,
badResult: this.badResult,
rollData: this.rollData,
isPrivate: isPrivate
}
cardData.cssClass = cardData.css.join(" ")
@@ -1113,6 +1167,7 @@ export default class LethalFantasyRoll extends Roll {
targetArmor: this.targetArmor,
targetMalus: this.targetMalus,
realDamage: this.realDamage,
rollData: this.rollData,
...messageData,
},
{ rollMode: rollMode },

View File

@@ -174,6 +174,31 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod
/** @override */
static LOCALIZATION_PREFIXES = ["LETHALFANTASY.Character"]
static migrateData(data) {
if (data?.biodata?.mortal) {
if (!SYSTEM.MORTAL_CHOICES[data.biodata.mortal]) {
for (let key in SYSTEM.MORTAL_CHOICES) {
let mortal = SYSTEM.MORTAL_CHOICES[key]
if ( mortal.label.toLowerCase() === data.biodata.mortal.toLowerCase()) {
data.biodata.mortal = mortal.id
}
if ( data.biodata.mortal.toLowerCase().includes("shire")) {
data.biodata.mortal = "halflings"
}
if ( data.biodata.mortal.toLowerCase().includes("human")) {
data.biodata.mortal = "mankind"
}
}
}
if (!SYSTEM.MORTAL_CHOICES[data.biodata.mortal]) {
console.warn("Lethal Fantasy | Migrate data: Mortal not found, forced to mankind", data.biodata.mortal)
data.biodata.mortal = "mankind"
}
}
return super.migrateData(data)
}
prepareDerivedData() {
super.prepareDerivedData();
let grit = 0
@@ -275,7 +300,7 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod
actorName: this.parent.name,
actorImage: this.parent.img,
combatId,
combatantId ,
combatantId,
actorClass,
maxInit,
})
@@ -302,10 +327,10 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod
let formula = ""
if (s.type === "spell") {
let dice = LethalFantasyUtils.getLethargyDice(s.system.level)
title = `${s.name} (Casting time: ${s.system.castingTime}, Lethargy: ${dice})`
title = `${s.name} (Casting time: ${s.system.castingTime}, Lethargy: ${dice})`
formula = `${s.system.castingTime}+${dice}`
} else {
title = `${s.name} (Prayer time: ${s.system.prayerTime})`
title = `${s.name} (Prayer time: ${s.system.prayerTime})`
formula = `${s.system.prayerTime}`
}
weaponsChoices.push({ id: s.id, name: title, combatProgressionDice: formula })

View File

@@ -73,6 +73,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
defenseModifier: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
damageDice: new fields.StringField({ required: true, nullable: false, initial: "1D6" }),
damageModifier: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
enabled: new fields.BooleanField({ initial: true, required: true, nullable: false }),
}
return new fields.SchemaField(schema, { label })
}
@@ -108,9 +109,9 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
schema.biodata = new fields.SchemaField({
alignment: new fields.StringField({ required: true, nullable: false, initial: "" }),
vision: new fields.StringField({ required: true, nullable: false, initial: "" }),
height: new fields.StringField({ required: true, nullable: false, initial: "" }),
height: new fields.StringField({ required: true, nullable: false, initial: "" }),
length: new fields.StringField({ required: true, nullable: false, initial: "" }),
weight: new fields.StringField({ required: true, nullable: false, initial: "" })
weight: new fields.StringField({ required: true, nullable: false, initial: "" })
})
schema.combat = new fields.SchemaField({
attackModifier: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
@@ -170,7 +171,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
case "weapon-damage-small":
case "weapon-damage-medium":
case "weapon-attack":
case "weapon-defense":
case "weapon-defense": {
let weapon = this.actor.items.find((i) => i.type === "weapon" && i.id === rollKey)
let skill
let skills = this.actor.items.filter((i) => i.type === "skill" && i.name.toLowerCase() === weapon.name.toLowerCase())
@@ -205,6 +206,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
rollTarget.weaponSkillModifier = skill.weaponSkillModifier
rollTarget.rollKey = rollKey
rollTarget.combat = foundry.utils.duplicate(this.combat)
}
break
default:
ui.notifications.error(game.i18n.localize("LETHALFANTASY.Notifications.rollTypeNotFound") + String(rollType))
@@ -238,18 +240,18 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
async rollProgressionDice(combatId, combatantId) {
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes)
const fieldRollMode = new foundry.data.fields.StringField({
choices: rollModes,
blank: false,
default: "public",
})
let roll = new Roll("1D8")
let roll = new Roll("1D12")
await roll.evaluate()
let combatant = game.combats.get(combatId)?.combatants?.get(combatantId)
let msg = await roll.toMessage({ flavor: `Progression Roll for ${this.parent.name}` } )
let msg = await roll.toMessage({ flavor: `Progression Roll for ${this.parent.name}` })
if (game?.dice3d) {
await game.dice3d.waitFor3DAnimationByMessageID(msg.id)
}
@@ -257,14 +259,14 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
let hasAttack = false
for (let key in this.attacks) {
let attack = this.attacks[key]
if (attack.attackScore > 0 && attack.attackScore === roll.total) {
if (attack.enabled && attack.attackScore > 0 && attack.attackScore === roll.total) {
hasAttack = true
let message = game.i18n.format("LETHALFANTASY.Notifications.messageProgressionOKMonster", { isMonster: true, name: this.parent.name, weapon: attack.name, roll: roll.total })
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: this.parent }) })
let token = combatant?.token
this.prepareMonsterRoll("monster-attack", key, undefined, token?.id)
if ( token?.object ) {
token.object?.control({releaseOthers: true});
if (token?.object) {
token.object?.control({ releaseOthers: true });
return canvas.animatePan(token.object.center);
}
}
@@ -272,7 +274,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
if (!hasAttack) {
let message = game.i18n.format("LETHALFANTASY.Notifications.messageProgressionKOMonster", { isMonster: true, name: this.parent.name, roll: roll.total })
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: this.parent }) })
}
}
}

View File

@@ -22,28 +22,28 @@ export default class LethalFantasyUtils {
static setHookListeners() {
Hooks.on('renderTokenHUD', async (hud, html, token) => {
const lossHPButton = await renderTemplate('systems/fvtt-lethal-fantasy/templates/loss-hp-hud.hbs', {} )
html.find('div.left').append(lossHPButton);
html.find('img.lethal-hp-loss-hud').click((event) => {
const lossHPButton = await foundry.applications.handlebars.renderTemplate('systems/fvtt-lethal-fantasy/templates/loss-hp-hud.hbs', {} )
$(html).find('div.left').append(lossHPButton);
$(html).find('img.lethal-hp-loss-hud').click((event) => {
event.preventDefault();
let hpMenu = html.find('.hp-loss-wrap')[0]
let hpMenu = $(html).find('.hp-loss-wrap')[0]
if (hpMenu.classList.contains("hp-loss-hud-disabled")) {
html.find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-active');
html.find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-disabled');
html.find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-active');
html.find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-disabled');
html.find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-active');
html.find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-disabled');
} else {
html.find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-active');
html.find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-disabled');
html.find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-active');
html.find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-disabled');
html.find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-active');
html.find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-disabled');
}
})
html.find('.loss-hp-hud-click').click((event) => {
$(html).find('.loss-hp-hud-click').click((event) => {
event.preventDefault();
let hpLoss = event.currentTarget.dataset.hpValue;
if (token) {
@@ -51,12 +51,12 @@ export default class LethalFantasyUtils {
console.log(tokenFull, token)
let actor = tokenFull.actor;
actor.applyDamage(Number(hpLoss));
html.find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-active');
html.find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-disabled');
html.find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-active');
html.find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-disabled');
html.find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-active');
html.find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-disabled');
}
})
})

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000303
MANIFEST-000416

View File

@@ -1,8 +1,8 @@
2025/05/06-10:52:19.288970 7fc4e7fff6c0 Recovering log #300
2025/05/06-10:52:19.300271 7fc4e7fff6c0 Delete type=3 #298
2025/05/06-10:52:19.300323 7fc4e7fff6c0 Delete type=0 #300
2025/05/06-10:53:10.017977 7fc4e73ff6c0 Level-0 table #306: started
2025/05/06-10:53:10.018020 7fc4e73ff6c0 Level-0 table #306: 0 bytes OK
2025/05/06-10:53:10.024080 7fc4e73ff6c0 Delete type=0 #304
2025/05/06-10:53:10.044191 7fc4e73ff6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
2025/05/06-10:53:10.044277 7fc4e73ff6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
2025/09/17-07:46:03.118742 7f3080dfa6c0 Recovering log #414
2025/09/17-07:46:03.213578 7f3080dfa6c0 Delete type=3 #412
2025/09/17-07:46:03.213653 7f3080dfa6c0 Delete type=0 #414
2025/09/17-07:46:49.420076 7f307a7fc6c0 Level-0 table #419: started
2025/09/17-07:46:49.420100 7f307a7fc6c0 Level-0 table #419: 0 bytes OK
2025/09/17-07:46:49.429915 7f307a7fc6c0 Delete type=0 #417
2025/09/17-07:46:49.430201 7f307a7fc6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
2025/09/17-07:46:49.430227 7f307a7fc6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)

View File

@@ -1,15 +1,8 @@
2025/05/06-10:45:53.342160 7fc4ecbf86c0 Recovering log #296
2025/05/06-10:45:53.353010 7fc4ecbf86c0 Delete type=3 #294
2025/05/06-10:45:53.353081 7fc4ecbf86c0 Delete type=0 #296
2025/05/06-10:51:12.708848 7fc4e73ff6c0 Level-0 table #301: started
2025/05/06-10:51:12.714248 7fc4e73ff6c0 Level-0 table #301: 213746 bytes OK
2025/05/06-10:51:12.720525 7fc4e73ff6c0 Delete type=0 #299
2025/05/06-10:51:12.748598 7fc4e73ff6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
2025/05/06-10:51:12.748667 7fc4e73ff6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at '!items!zw9RQocTdz3HRjZK' @ 564 : 1
2025/05/06-10:51:12.748677 7fc4e73ff6c0 Compacting 1@1 + 1@2 files
2025/05/06-10:51:12.755813 7fc4e73ff6c0 Generated table #302@1: 485 keys, 214492 bytes
2025/05/06-10:51:12.755833 7fc4e73ff6c0 Compacted 1@1 + 1@2 files => 214492 bytes
2025/05/06-10:51:12.761728 7fc4e73ff6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
2025/05/06-10:51:12.761886 7fc4e73ff6c0 Delete type=2 #289
2025/05/06-10:51:12.762144 7fc4e73ff6c0 Delete type=2 #301
2025/05/06-10:51:12.795034 7fc4e73ff6c0 Manual compaction at level-1 from '!items!zw9RQocTdz3HRjZK' @ 564 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
2025/09/16-23:16:29.221312 7f307affd6c0 Recovering log #410
2025/09/16-23:16:29.232289 7f307affd6c0 Delete type=3 #408
2025/09/16-23:16:29.232343 7f307affd6c0 Delete type=0 #410
2025/09/16-23:47:50.382735 7f307a7fc6c0 Level-0 table #415: started
2025/09/16-23:47:50.383046 7f307a7fc6c0 Level-0 table #415: 0 bytes OK
2025/09/16-23:47:50.390243 7f307a7fc6c0 Delete type=0 #413
2025/09/16-23:47:50.410779 7f307a7fc6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
2025/09/16-23:47:50.410810 7f307a7fc6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000302
MANIFEST-000416

View File

@@ -1,8 +1,8 @@
2025/05/06-10:52:19.304583 7fc4ed3f96c0 Recovering log #299
2025/05/06-10:52:19.314806 7fc4ed3f96c0 Delete type=3 #297
2025/05/06-10:52:19.314910 7fc4ed3f96c0 Delete type=0 #299
2025/05/06-10:53:10.030599 7fc4e73ff6c0 Level-0 table #305: started
2025/05/06-10:53:10.030635 7fc4e73ff6c0 Level-0 table #305: 0 bytes OK
2025/05/06-10:53:10.036964 7fc4e73ff6c0 Delete type=0 #303
2025/05/06-10:53:10.044214 7fc4e73ff6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
2025/05/06-10:53:10.044269 7fc4e73ff6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
2025/09/17-07:46:03.218339 7f307bfff6c0 Recovering log #414
2025/09/17-07:46:03.309130 7f307bfff6c0 Delete type=3 #412
2025/09/17-07:46:03.309200 7f307bfff6c0 Delete type=0 #414
2025/09/17-07:46:49.410790 7f307a7fc6c0 Level-0 table #419: started
2025/09/17-07:46:49.410814 7f307a7fc6c0 Level-0 table #419: 0 bytes OK
2025/09/17-07:46:49.419958 7f307a7fc6c0 Delete type=0 #417
2025/09/17-07:46:49.430187 7f307a7fc6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
2025/09/17-07:46:49.430218 7f307a7fc6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)

View File

@@ -1,15 +1,8 @@
2025/05/06-10:45:53.355849 7fc4edbfa6c0 Recovering log #295
2025/05/06-10:45:53.366571 7fc4edbfa6c0 Delete type=3 #293
2025/05/06-10:45:53.366637 7fc4edbfa6c0 Delete type=0 #295
2025/05/06-10:51:12.732133 7fc4e73ff6c0 Level-0 table #300: started
2025/05/06-10:51:12.736129 7fc4e73ff6c0 Level-0 table #300: 15304 bytes OK
2025/05/06-10:51:12.742079 7fc4e73ff6c0 Delete type=0 #298
2025/05/06-10:51:12.748632 7fc4e73ff6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
2025/05/06-10:51:12.771871 7fc4e73ff6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at '!items!zjvGljrLk5SshC9D' @ 65 : 1
2025/05/06-10:51:12.771882 7fc4e73ff6c0 Compacting 1@1 + 1@2 files
2025/05/06-10:51:12.776442 7fc4e73ff6c0 Generated table #301@1: 31 keys, 15417 bytes
2025/05/06-10:51:12.776461 7fc4e73ff6c0 Compacted 1@1 + 1@2 files => 15417 bytes
2025/05/06-10:51:12.782727 7fc4e73ff6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
2025/05/06-10:51:12.782835 7fc4e73ff6c0 Delete type=2 #288
2025/05/06-10:51:12.782952 7fc4e73ff6c0 Delete type=2 #300
2025/05/06-10:51:12.795077 7fc4e73ff6c0 Manual compaction at level-1 from '!items!zjvGljrLk5SshC9D' @ 65 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
2025/09/16-23:16:29.238114 7f3080dfa6c0 Recovering log #409
2025/09/16-23:16:29.248900 7f3080dfa6c0 Delete type=3 #407
2025/09/16-23:16:29.248979 7f3080dfa6c0 Delete type=0 #409
2025/09/16-23:47:50.397435 7f307a7fc6c0 Level-0 table #415: started
2025/09/16-23:47:50.397478 7f307a7fc6c0 Level-0 table #415: 0 bytes OK
2025/09/16-23:47:50.404058 7f307a7fc6c0 Delete type=0 #413
2025/09/16-23:47:50.410801 7f307a7fc6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
2025/09/16-23:47:50.410854 7f307a7fc6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000302
MANIFEST-000416

View File

@@ -1,8 +1,8 @@
2025/05/06-10:52:19.275594 7fc4ecbf86c0 Recovering log #299
2025/05/06-10:52:19.285984 7fc4ecbf86c0 Delete type=3 #297
2025/05/06-10:52:19.286069 7fc4ecbf86c0 Delete type=0 #299
2025/05/06-10:53:10.024277 7fc4e73ff6c0 Level-0 table #305: started
2025/05/06-10:53:10.024336 7fc4e73ff6c0 Level-0 table #305: 0 bytes OK
2025/05/06-10:53:10.030435 7fc4e73ff6c0 Delete type=0 #303
2025/05/06-10:53:10.044204 7fc4e73ff6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
2025/05/06-10:53:10.044252 7fc4e73ff6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
2025/09/17-07:46:03.016134 7f307affd6c0 Recovering log #414
2025/09/17-07:46:03.115017 7f307affd6c0 Delete type=3 #412
2025/09/17-07:46:03.115113 7f307affd6c0 Delete type=0 #414
2025/09/17-07:46:49.400823 7f307a7fc6c0 Level-0 table #419: started
2025/09/17-07:46:49.400858 7f307a7fc6c0 Level-0 table #419: 0 bytes OK
2025/09/17-07:46:49.410679 7f307a7fc6c0 Delete type=0 #417
2025/09/17-07:46:49.430172 7f307a7fc6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
2025/09/17-07:46:49.430210 7f307a7fc6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)

View File

@@ -1,15 +1,8 @@
2025/05/06-10:45:53.317135 7fc4e7fff6c0 Recovering log #295
2025/05/06-10:45:53.339293 7fc4e7fff6c0 Delete type=3 #293
2025/05/06-10:45:53.339350 7fc4e7fff6c0 Delete type=0 #295
2025/05/06-10:51:12.783010 7fc4e73ff6c0 Level-0 table #300: started
2025/05/06-10:51:12.787977 7fc4e73ff6c0 Level-0 table #300: 154604 bytes OK
2025/05/06-10:51:12.794741 7fc4e73ff6c0 Delete type=0 #298
2025/05/06-10:51:12.795090 7fc4e73ff6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
2025/05/06-10:51:12.795140 7fc4e73ff6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at '!items!zt8s7564ep1La4XQ' @ 281 : 1
2025/05/06-10:51:12.795156 7fc4e73ff6c0 Compacting 1@1 + 1@2 files
2025/05/06-10:51:12.800410 7fc4e73ff6c0 Generated table #301@1: 95 keys, 121769 bytes
2025/05/06-10:51:12.800436 7fc4e73ff6c0 Compacted 1@1 + 1@2 files => 121769 bytes
2025/05/06-10:51:12.806480 7fc4e73ff6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
2025/05/06-10:51:12.806620 7fc4e73ff6c0 Delete type=2 #288
2025/05/06-10:51:12.806871 7fc4e73ff6c0 Delete type=2 #300
2025/05/06-10:51:12.827417 7fc4e73ff6c0 Manual compaction at level-1 from '!items!zt8s7564ep1La4XQ' @ 281 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
2025/09/16-23:16:29.207343 7f307bfff6c0 Recovering log #409
2025/09/16-23:16:29.216984 7f307bfff6c0 Delete type=3 #407
2025/09/16-23:16:29.217040 7f307bfff6c0 Delete type=0 #409
2025/09/16-23:47:50.390364 7f307a7fc6c0 Level-0 table #415: started
2025/09/16-23:47:50.390390 7f307a7fc6c0 Level-0 table #415: 0 bytes OK
2025/09/16-23:47:50.397293 7f307a7fc6c0 Delete type=0 #413
2025/09/16-23:47:50.410791 7f307a7fc6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
2025/09/16-23:47:50.410840 7f307a7fc6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000002
MANIFEST-000116

View File

@@ -1,5 +1,8 @@
2025/05/06-10:52:19.344307 7fc4e7fff6c0 Delete type=3 #1
2025/05/06-10:53:10.044408 7fc4e73ff6c0 Level-0 table #5: started
2025/05/06-10:53:10.051976 7fc4e73ff6c0 Level-0 table #5: 433603 bytes OK
2025/05/06-10:53:10.058524 7fc4e73ff6c0 Delete type=0 #3
2025/05/06-10:53:10.078387 7fc4e73ff6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
2025/09/17-07:46:03.403212 7f307affd6c0 Recovering log #114
2025/09/17-07:46:03.504394 7f307affd6c0 Delete type=3 #112
2025/09/17-07:46:03.504449 7f307affd6c0 Delete type=0 #114
2025/09/17-07:46:49.470775 7f307a7fc6c0 Level-0 table #119: started
2025/09/17-07:46:49.470837 7f307a7fc6c0 Level-0 table #119: 0 bytes OK
2025/09/17-07:46:49.482316 7f307a7fc6c0 Delete type=0 #117
2025/09/17-07:46:49.503080 7f307a7fc6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
2025/09/17-07:46:49.523511 7f307a7fc6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)

View File

@@ -0,0 +1,8 @@
2025/09/16-23:16:29.263902 7f307affd6c0 Recovering log #109
2025/09/16-23:16:29.274398 7f307affd6c0 Delete type=3 #107
2025/09/16-23:16:29.274490 7f307affd6c0 Delete type=0 #109
2025/09/16-23:47:50.437467 7f307a7fc6c0 Level-0 table #115: started
2025/09/16-23:47:50.437529 7f307a7fc6c0 Level-0 table #115: 0 bytes OK
2025/09/16-23:47:50.443898 7f307a7fc6c0 Delete type=0 #113
2025/09/16-23:47:50.474392 7f307a7fc6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
2025/09/16-23:47:50.474456 7f307a7fc6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000302
MANIFEST-000415

View File

@@ -1,8 +1,8 @@
2025/05/06-10:52:19.317853 7fc4edbfa6c0 Recovering log #299
2025/05/06-10:52:19.327788 7fc4edbfa6c0 Delete type=3 #297
2025/05/06-10:52:19.327923 7fc4edbfa6c0 Delete type=0 #299
2025/05/06-10:53:10.037095 7fc4e73ff6c0 Level-0 table #305: started
2025/05/06-10:53:10.037121 7fc4e73ff6c0 Level-0 table #305: 0 bytes OK
2025/05/06-10:53:10.044101 7fc4e73ff6c0 Delete type=0 #303
2025/05/06-10:53:10.044224 7fc4e73ff6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
2025/05/06-10:53:10.044260 7fc4e73ff6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
2025/09/17-07:46:03.312040 7f307b7fe6c0 Recovering log #413
2025/09/17-07:46:03.400421 7f307b7fe6c0 Delete type=3 #411
2025/09/17-07:46:03.400487 7f307b7fe6c0 Delete type=0 #413
2025/09/17-07:46:49.390955 7f307a7fc6c0 Level-0 table #418: started
2025/09/17-07:46:49.391029 7f307a7fc6c0 Level-0 table #418: 0 bytes OK
2025/09/17-07:46:49.400683 7f307a7fc6c0 Delete type=0 #416
2025/09/17-07:46:49.430144 7f307a7fc6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
2025/09/17-07:46:49.430391 7f307a7fc6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)

View File

@@ -1,15 +1,8 @@
2025/05/06-10:45:53.369722 7fc4ed3f96c0 Recovering log #295
2025/05/06-10:45:53.379868 7fc4ed3f96c0 Delete type=3 #293
2025/05/06-10:45:53.379989 7fc4ed3f96c0 Delete type=0 #295
2025/05/06-10:51:12.720972 7fc4e73ff6c0 Level-0 table #300: started
2025/05/06-10:51:12.724909 7fc4e73ff6c0 Level-0 table #300: 20719 bytes OK
2025/05/06-10:51:12.731912 7fc4e73ff6c0 Delete type=0 #298
2025/05/06-10:51:12.748619 7fc4e73ff6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
2025/05/06-10:51:12.762241 7fc4e73ff6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at '!items!zkK6ixtCsCw3RH9X' @ 62 : 1
2025/05/06-10:51:12.762247 7fc4e73ff6c0 Compacting 1@1 + 1@2 files
2025/05/06-10:51:12.765506 7fc4e73ff6c0 Generated table #301@1: 27 keys, 20869 bytes
2025/05/06-10:51:12.765523 7fc4e73ff6c0 Compacted 1@1 + 1@2 files => 20869 bytes
2025/05/06-10:51:12.771435 7fc4e73ff6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
2025/05/06-10:51:12.771569 7fc4e73ff6c0 Delete type=2 #288
2025/05/06-10:51:12.771746 7fc4e73ff6c0 Delete type=2 #300
2025/05/06-10:51:12.795060 7fc4e73ff6c0 Manual compaction at level-1 from '!items!zkK6ixtCsCw3RH9X' @ 62 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
2025/09/16-23:16:29.250993 7f307bfff6c0 Recovering log #409
2025/09/16-23:16:29.261540 7f307bfff6c0 Delete type=3 #407
2025/09/16-23:16:29.261614 7f307bfff6c0 Delete type=0 #409
2025/09/16-23:47:50.404206 7f307a7fc6c0 Level-0 table #414: started
2025/09/16-23:47:50.404257 7f307a7fc6c0 Level-0 table #414: 0 bytes OK
2025/09/16-23:47:50.410667 7f307a7fc6c0 Delete type=0 #412
2025/09/16-23:47:50.410817 7f307a7fc6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
2025/09/16-23:47:50.410847 7f307a7fc6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)

Binary file not shown.

View File

@@ -45,7 +45,7 @@
min-width: 2.2rem;
max-width: 2.2rem;
margin-left: 4px;
font-size: calc(var(--font-size-standard) * 1.0);
font-size: calc(var(--font-size-standard) * 1);
}
.character-hp-max {
clear: both;
@@ -57,7 +57,7 @@
input {
width: 3.2rem;
text-align: center;
font-size: calc(var(--font-size-standard) * 1.0);
font-size: calc(var(--font-size-standard) * 1);
}
}
}
@@ -93,6 +93,10 @@
.character-characteristic {
display: flex;
align-items: center;
span {
min-width: 2.2rem;
max-width: 2.2rem;
}
.rollable:hover,
.rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary);
@@ -108,7 +112,7 @@
}
}
}
.character-challenges {
display: flex;
flex-direction: column;
@@ -218,7 +222,7 @@
}
}
.tab.character-biography {
.tab.character-biography .main-div {
.biodata {
display: grid;
grid-template-columns: repeat(4, 1fr);
@@ -248,7 +252,7 @@
}
}
.tab.character-skills {
.tab.character-skills .main-div {
display: grid;
grid-template-columns: 1fr;
legend {
@@ -310,7 +314,7 @@
}
}
.tab.character-equipment {
.tab.character-equipment .main-div {
display: grid;
grid-template-columns: 1fr;
legend {
@@ -349,7 +353,7 @@
}
}
.tab.character-combat {
.tab.character-combat .main-div {
display: grid;
grid-template-columns: 1fr;
legend {
@@ -469,7 +473,7 @@
min-width: 12rem;
}
.item-detail {
min-width:2rem;
min-width: 2rem;
}
}
.shields {
@@ -488,16 +492,15 @@
}
}
.item-detail {
min-width:2.5rem;
min-width: 2.5rem;
}
.name {
min-width: 12rem;
}
}
}
.tab.character-spells {
.tab.character-spells .main-div {
display: grid;
grid-template-columns: 1fr;
legend {
@@ -530,7 +533,6 @@
}
}
.spells {
display: grid;
grid-template-columns: repeat(2, 1fr);
@@ -541,7 +543,8 @@
align-items: center;
gap: 4px;
.item-img {
width: 24px;
min-width: 24px;
max-width: 24px;
height: 24px;
}
.name {
@@ -558,7 +561,7 @@
}
}
.tab.character-miracles {
.tab.character-miracles .main-div {
display: grid;
grid-template-columns: 1fr;
legend {

View File

@@ -5,6 +5,5 @@
@font-face {
font-family: "BaskervilleBold";
src: url("../fonts/baskerville-bold.ttf") format("truetype");
src: url("../assets/fonts/baskerville-bold.ttf") format("truetype");
}

View File

@@ -6,6 +6,17 @@
--logo-standard: url("../assets/ui/lf_logo_small_02.webp");
}
.initiative-area {
min-width: 8rem;
max-width: 8rem;
display: flex;
flex-direction: row;
input {
min-width: 3rem;
max-width: 3rem;
}
}
#logo {
content: var(--logo-standard);
width: 50px;

View File

@@ -35,9 +35,10 @@
padding-bottom: 0;
width: max-content;
margin: 0;
color:#252424;
}
#token-hud .hp-loss-wrap .hud-loss-hp-button-select {
padding-left: 8px;
font-size: 0.7rem;
font-size: 0.9rem;
}

View File

@@ -6,6 +6,14 @@
background-repeat: no-repeat;
background-size: 100% 100%;
nav.tabs [data-tab] {
color: #636060;
}
nav.tabs [data-tab].active {
color: #252424;
}
input:disabled,
select:disabled {
background-color: rgba(0, 0, 0, 0.2);
@@ -39,11 +47,11 @@
input,
select {
text-align: center;
font-size: calc(var(--font-size-standard) * 1.0);
font-size: calc(var(--font-size-standard) * 1);
}
select {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.0);
font-size: calc(var(--font-size-standard) * 1);
}
}
@@ -67,23 +75,43 @@
padding-top: 4px;
}
overflow: auto;
.form-group {
display: flex;
flex: 1;
flex-direction: row;
label {
align-content: center;
min-width: 10rem;
max-width: 10rem;
}
select,
input {
text-align: left;
min-width: 12rem;
max-width: 12rem;
}
input[type="checkbox"] {
min-width: 1.2rem;
max-width: 1.2rem;
margin-right: 0.5rem;
}
}
label {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.0);
font-size: calc(var(--font-size-standard) * 1);
flex: 50%;
}
.align-top {
align-self: flex-start;
padding: 0.1rem;
margin-right: 0.2rem;
/*border-color: black;
border-width: 1px;
border-style: solid;
border-radius: 2%;*/
}
.shift-right {
margin-left: 2rem;
}
}
}

View File

@@ -19,12 +19,12 @@
border: none;
}
}
.monster-pc {
display: flex;
gap: 10px;
flex: 1;
.monster-hp {
display: flex;
@@ -99,6 +99,10 @@
text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer;
}
span {
min-width: 2.2rem;
max-width: 2.2rem;
}
.form-group {
flex: 1;
padding-left: 4px;
@@ -223,7 +227,7 @@
}
}
.tab.monster-biography {
.tab.monster-biography .main-div {
.biodata {
display: grid;
grid-template-columns: repeat(4, 1fr);
@@ -248,7 +252,7 @@
}
}
.tab.monster-skills {
.tab.monster-skills .main-div{
display: grid;
grid-template-columns: 1fr;
legend {
@@ -462,4 +466,3 @@
min-height: 150px;
}
}

View File

@@ -25,7 +25,6 @@
border-radius: 4px;
padding: 0.5rem;
}
}
.lethalfantasy-range-defense-dialog {
@@ -45,13 +44,12 @@
justify-content: left;
}
.field-name {
width:4rem;
width: 4rem;
min-width: 4rem;
max-width: 4rem;
}
}
.dialog-form {
.form-footer {
button {
@@ -87,7 +85,6 @@
}
}
.main,
.dialog-damage,
.dialog-resource,
@@ -99,8 +96,13 @@
justify-content: center;
align-items: center;
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.0);
font-size: calc(var(--font-size-standard) * 1);
color: var(--color-dark-1);
select {
min-width: 8rem;
max-width: 8rem;
margin-left: 1rem;
}
}
&.dice-roll {
@@ -133,7 +135,7 @@
flex-direction: column;
.introText {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.0);
font-size: calc(var(--font-size-standard) * 1);
width: 210px;
margin-left: 20px;
}
@@ -144,7 +146,7 @@
flex-direction: column;
justify-content: center;
align-items: center;
font-size: calc(var(--font-size-standard) * 1.0);
font-size: calc(var(--font-size-standard) * 1);
text-shadow: 0 0 10px var(--color-shadow-primary);
}
}

View File

@@ -6,7 +6,7 @@
"download": "#{DOWNLOAD}#",
"url": "#{URL}#",
"license": "LICENSE",
"version": "12.0.35",
"version": "13.0.0",
"authors": [
{
"name": "Uberwald",
@@ -14,8 +14,8 @@
}
],
"compatibility": {
"minimum": "12",
"verified": "12"
"minimum": "13",
"verified": "13"
},
"esmodules": ["lethal-fantasy.mjs"],
"styles": ["css/fvtt-lethal-fantasy.css"],

View File

@@ -1,4 +1,5 @@
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
<div class="main-div">
<fieldset>
<legend>{{localize "LETHALFANTASY.Label.biodata"}}</legend>
@@ -92,5 +93,5 @@
<legend>{{localize "LETHALFANTASY.Label.notes"}}</legend>
{{formInput systemFields.notes enriched=enrichedNotes value=system.notes name="system.notes" toggled=true}}
</fieldset>
</div>
</section>

View File

@@ -1,10 +1,11 @@
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="combat" data-group="sheet">
<div class="main-div">
<fieldset>
<legend>{{localize "LETHALFANTASY.Label.combatDetails"}}</legend>
<div class="combat-details">
<div class="combat-detail">
<button class="action" data-action="rangedAttackDefense">
{{localize "LETHALFANTASY.Label.rangedAttackDefense"}}
</button>
@@ -155,5 +156,6 @@
{{/each}}
</div>
</fieldset>
<div>
</section>

View File

@@ -1,4 +1,5 @@
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
<div class="main-div">
<fieldset>
<legend>{{localize "LETHALFANTASY.Label.money"}}</legend>
@@ -31,5 +32,5 @@
</div>
</fieldset>
</div>
</section>

View File

@@ -13,9 +13,11 @@
<fieldset class="">
<div class="flexrow character-hp">
<span class="name">{{localize "LETHALFANTASY.Label.HP"}}</span>
{{formInput systemFields.hp.fields.value value=system.hp.value disabled=isPlayMode classes="character-hp-value"}}
{{formInput systemFields.hp.fields.value value=system.hp.value disabled=isPlayMode
classes="character-hp-value"}}
&nbsp;/&nbsp;
{{formInput systemFields.hp.fields.max value=system.hp.max disabled=isPlayMode classes="character-hp-value"}}
{{formInput systemFields.hp.fields.max value=system.hp.max disabled=isPlayMode
classes="character-hp-value"}}
</div>
<div class="flexrow character-hp">
<span class="name">{{localize "LETHALFANTASY.Label.grit"}}</span>
@@ -36,7 +38,8 @@
<div class="flexrow ">
<span class="">{{localize "LETHALFANTASY.Label.damageResistanceShort"}}</span>
{{formInput systemFields.hp.fields.damageResistance value=system.hp.fields.damageResistance disabled=isPlayMode classes="character-hp"}}
{{formInput systemFields.hp.fields.damageResistance value=system.hp.fields.damageResistance
disabled=isPlayMode classes="character-hp"}}
</div>
@@ -81,39 +84,43 @@
<div class="character-save">
<span class="name">
<a class="rollable" data-roll-type="save" data-roll-key="contagion"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.contagion"}}
</a>
</span>
</span>
{{formField systemFields.saves.fields.contagion.fields.value value=system.saves.contagion.value
disabled=true}}
<span class="name">
<a class="rollable" data-roll-type="save" data-roll-key="poison"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.poison"}}
class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.poison"}}
</a>
</span>
{{formField systemFields.saves.fields.poison.fields.value value=system.saves.poison.value
</span>
{{formField systemFields.saves.fields.poison.fields.value value=system.saves.poison.value
disabled=true }}
<!--
<span class="name-pain">
<a class="rollable" data-roll-type="save" data-roll-key="pain" data-roll-dice="D12"><i
class="lf-roll-small fa-solid fa-dice-d12"></i>
{{localize "LETHALFANTASY.Label.saves.pain"}}
<a class="rollable" data-roll-type="save" data-roll-key="pain" data-roll-dice="D12"><i
class="lf-roll-small fa-solid fa-dice-d12"></i>
{{localize "LETHALFANTASY.Label.saves.pain"}}
</a>
</span>
<span class="name-pain">
<a class="rollable" data-roll-type="save" data-roll-key="pain" data-roll-dice="D20"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.pain"}}
<span class="name-pain">
<a class="rollable" data-roll-type="save" data-roll-key="pain" data-roll-dice="D20"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.pain"}}
</a>
</span>
</span>
{{formField systemFields.saves.fields.pain.fields.value value=system.saves.pain.value disabled=true}}
<span data-tooltip="Pain save if wound exceeds">
{{formField systemFields.hp.fields.painDamage value=system.hp.painDamage disabled=isPlayMode tooltip="Pain Damage"}}
{{formField systemFields.hp.fields.painDamage value=system.hp.painDamage disabled=isPlayMode
tooltip="Pain Damage"}}
</span>
-->
</div>
</div>
</fieldset>
@@ -132,7 +139,7 @@
class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.challenges.agility"}}</a></span>
{{formField systemFields.challenges.fields.agility.fields.value value=system.challenges.agility.value
disabled=true
disabled=true
}}
<span class="name"><a class="rollable" data-roll-type="challenge" data-roll-key="dying"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
@@ -174,14 +181,14 @@
<fieldset class="character-characteristics character-characteristics-{{ifThen isPlayMode 'play' 'edit'}}">
<legend>{{localize "LETHALFANTASY.Label.characteristics"}}</legend>
<div class="character-characteristic">
{{localize "LETHALFANTASY.Label.str"}}
<span>{{localize "LETHALFANTASY.Label.str"}}</span>
{{formField systemFields.characteristics.fields.str.fields.value value=system.characteristics.str.value
disabled=isPlayMode data-char-id="str" }}
{{formField systemFields.characteristics.fields.str.fields.percent value=system.characteristics.str.percent
disabled=isPlayMode type="number"}}
</div>
<div class="character-characteristic">
{{localize "LETHALFANTASY.Label.int"}}
<span>{{localize "LETHALFANTASY.Label.int"}}</span>
{{formField systemFields.characteristics.fields.int.fields.value value=system.characteristics.int.value
disabled=isPlayMode data-char-id="int" }}
@@ -189,7 +196,7 @@
disabled=isPlayMode type="number" }}
</div>
<div class="character-characteristic">
{{localize "LETHALFANTASY.Label.wis"}}
<span>{{localize "LETHALFANTASY.Label.wis"}}</span>
{{formField systemFields.characteristics.fields.wis.fields.value value=system.characteristics.wis.value
disabled=isPlayMode data-char-id="wis" }}
@@ -197,7 +204,7 @@
disabled=isPlayMode type="number"}}
</div>
<div class="character-characteristic">
{{localize "LETHALFANTASY.Label.dex"}}
<span>{{localize "LETHALFANTASY.Label.dex"}}</span>
{{formField systemFields.characteristics.fields.dex.fields.value value=system.characteristics.dex.value
disabled=isPlayMode data-char-id="wis" }}
@@ -205,7 +212,7 @@
disabled=isPlayMode type="number" }}
</div>
<div class="character-characteristic">
{{localize "LETHALFANTASY.Label.con"}}
<span>{{localize "LETHALFANTASY.Label.con"}}</span>
{{formField systemFields.characteristics.fields.con.fields.value value=system.characteristics.con.value
disabled=isPlayMode data-char-id="con" }}
@@ -213,7 +220,7 @@
disabled=isPlayMode type="number"}}
</div>
<div class="character-characteristic">
{{localize "LETHALFANTASY.Label.cha"}}
<span>{{localize "LETHALFANTASY.Label.cha"}}</span>
{{formField systemFields.characteristics.fields.cha.fields.value value=system.characteristics.cha.value
disabled=isPlayMode data-char-id="cha" }}
@@ -221,21 +228,13 @@
disabled=isPlayMode type="number"}}
</div>
<div class="character-characteristic">
{{localize "LETHALFANTASY.Label.luc"}}
<span>{{localize "LETHALFANTASY.Label.luc"}}</span>
{{formField systemFields.characteristics.fields.luc.fields.value value=system.characteristics.luc.value
disabled=isPlayMode data-char-id="luc" }}
{{formField systemFields.characteristics.fields.luc.fields.percent value=system.characteristics.luc.percent
disabled=isPlayMode type="number"}}
</div>
<div class="character-characteristic">
{{localize "LETHALFANTASY.Label.app"}}
{{formField systemFields.characteristics.fields.app.fields.value value=system.characteristics.app.value
disabled=isPlayMode data-char-id="app" }}
{{formField systemFields.characteristics.fields.app.fields.percent value=system.characteristics.app.percent
disabled=isPlayMode type="number"}}
</div>
</fieldset>
</section>

View File

@@ -1,50 +1,52 @@
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
<div class="main-div">
<fieldset>
<legend>{{localize "LETHALFANTASY.Label.divinityPoints"}}</legend>
<div class="miracle-details">
<div class="miracle-detail">
<span >Current</span>
{{formField systemFields.divinityPoints.fields.value value=system.divinityPoints.value localize=true}}
<a data-action="divinityPointsPlus"><i class="fa-solid fa-hexagon-plus"></i></a>
<a data-action="divinityPointsMinus"><i class="fa-solid fa-hexagon-minus"></i></a>
<fieldset>
<legend>{{localize "LETHALFANTASY.Label.divinityPoints"}}</legend>
<div class="miracle-details">
<div class="miracle-detail">
<span>Current</span>
{{formField systemFields.divinityPoints.fields.value value=system.divinityPoints.value localize=true}}
<a data-action="divinityPointsPlus"><i class="fa-solid fa-hexagon-plus"></i></a>
<a data-action="divinityPointsMinus"><i class="fa-solid fa-hexagon-minus"></i></a>
<span >Max</span>
{{formField systemFields.divinityPoints.fields.max value=system.divinityPoints.max localize=true disabled=isPlayMode}}
<span>Max</span>
{{formField systemFields.divinityPoints.fields.max value=system.divinityPoints.max localize=true
disabled=isPlayMode}}
</div>
</div>
</div>
</fieldset>
</fieldset>
<fieldset>
<legend>{{localize "LETHALFANTASY.Label.miracles"}}{{#if isEditMode}}<a class="action" data-tooltip="{{localize "
LETHALFANTASY.Tooltip.addMiracle"}}" data-tooltip-direction="UP"><i class="fas fa-plus"
data-action="createMiracle"></i></a>{{/if}}</legend>
<div class="miracles">
{{#each miracles as |item|}}
<div class="miracle" 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" >
{{item.name}}
</div>
<a class="rollable" data-roll-type="miracle-attack" data-roll-key="{{item.id}}" data-tooltip="Miracle Attack">
<i class="lf-roll-small fa-solid fa-swords" data-roll-type="miracle-attack" data-roll-key="{{item.id}}"></i>
</a>
<a class="rollable" data-roll-type="miracle-power" data-roll-key="{{item.id}}" data-tooltip="Miracle Power">
<i class="fa-duotone fa-solid fa-stars" data-roll-type="miracle-power" data-roll-key="{{item.id}}"></i>
</a>
<div class="controls">
<a data-tooltip="{{localize 'LETHALFANTASY.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 'LETHALFANTASY.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
<fieldset>
<legend>{{localize "LETHALFANTASY.Label.miracles"}}{{#if isEditMode}}<a class="action" data-tooltip="{{localize "
LETHALFANTASY.Tooltip.addMiracle"}}" data-tooltip-direction="UP"><i class="fas fa-plus"
data-action="createMiracle"></i></a>{{/if}}</legend>
<div class="miracles">
{{#each miracles as |item|}}
<div class="miracle" 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">
{{item.name}}
</div>
<a class="rollable" data-roll-type="miracle-attack" data-roll-key="{{item.id}}" data-tooltip="Miracle Attack">
<i class="lf-roll-small fa-solid fa-swords" data-roll-type="miracle-attack" data-roll-key="{{item.id}}"></i>
</a>
<a class="rollable" data-roll-type="miracle-power" data-roll-key="{{item.id}}" data-tooltip="Miracle Power">
<i class="fa-duotone fa-solid fa-stars" data-roll-type="miracle-power" data-roll-key="{{item.id}}"></i>
</a>
<div class="controls">
<a data-tooltip="{{localize 'LETHALFANTASY.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 'LETHALFANTASY.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>
{{/each}}
</div>
</fieldset>
</fieldset>
</div>
</section>

View File

@@ -1,4 +1,5 @@
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="skills" data-group="sheet">
<div class="main-div">
<fieldset>
<legend data-tooltip="{{localize " LETHALFANTASY.Tooltip.skills"}}" data-tooltip-direction="UP">{{localize
@@ -68,5 +69,5 @@
{{/each}}
</div>
</fieldset>
</div>
</section>

View File

@@ -1,50 +1,51 @@
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
<div class="main-div">
<fieldset>
<legend>{{localize "LETHALFANTASY.Label.aetherPoints"}}</legend>
<div class="spell-details">
<div class="spell-detail">
<span >Current</span>
{{formField systemFields.aetherPoints.fields.value value=system.aetherPoints.value localize=true}}
<a data-action="aetherPointsPlus"><i class="fa-solid fa-hexagon-plus"></i></a>
<a data-action="aetherPointsMinus"><i class="fa-solid fa-hexagon-minus"></i></a>
<fieldset>
<legend>{{localize "LETHALFANTASY.Label.aetherPoints"}}</legend>
<div class="spell-details">
<div class="spell-detail">
<span>Current</span>
{{formField systemFields.aetherPoints.fields.value value=system.aetherPoints.value localize=true}}
<a data-action="aetherPointsPlus"><i class="fa-solid fa-hexagon-plus"></i></a>
<a data-action="aetherPointsMinus"><i class="fa-solid fa-hexagon-minus"></i></a>
<span >Max</span>
{{formField systemFields.aetherPoints.fields.max value=system.aetherPoints.max localize=true disabled=isPlayMode}}
<span>Max</span>
{{formField systemFields.aetherPoints.fields.max value=system.aetherPoints.max localize=true
disabled=isPlayMode}}
</div>
</div>
</div>
</fieldset>
</fieldset>
<fieldset>
<legend>{{localize "LETHALFANTASY.Label.spells"}}{{#if isEditMode}}<a class="action" data-tooltip="{{localize "
LETHALFANTASY.Tooltip.addSpell"}}" data-tooltip-direction="UP"><i class="fas fa-plus"
data-action="createSpell"></i></a>{{/if}}</legend>
<div class="spells">
{{#each spells as |item|}}
<div class="spell" 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" >
{{item.name}}
</div>
<a class="rollable" data-roll-type="spell-attack" data-roll-key="{{item.id}}" data-tooltip="Spell Attack">
<i class="lf-roll-small fa-solid fa-swords" data-roll-type="spell-attack" data-roll-key="{{item.id}}"></i>
</a>
<a class="rollable" data-roll-type="spell-power" data-roll-key="{{item.id}}" data-tooltip="Spell Power">
<i class="fa-duotone fa-solid fa-stars" data-roll-type="spell-power" data-roll-key="{{item.id}}"></i>
</a>
<div class="controls">
<a data-tooltip="{{localize 'LETHALFANTASY.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 'LETHALFANTASY.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
<fieldset>
<legend>{{localize "LETHALFANTASY.Label.spells"}}{{#if isEditMode}}<a class="action" data-tooltip="{{localize "
LETHALFANTASY.Tooltip.addSpell"}}" data-tooltip-direction="UP"><i class="fas fa-plus"
data-action="createSpell"></i></a>{{/if}}</legend>
<div class="spells">
{{#each spells as |item|}}
<div class="spell" 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">
{{item.name}}
</div>
<a class="rollable" data-roll-type="spell-attack" data-roll-key="{{item.id}}" data-tooltip="Spell Attack">
<i class="lf-roll-small fa-solid fa-swords" data-roll-type="spell-attack" data-roll-key="{{item.id}}"></i>
</a>
<a class="rollable" data-roll-type="spell-power" data-roll-key="{{item.id}}" data-tooltip="Spell Power">
<i class="fa-duotone fa-solid fa-stars" data-roll-type="spell-power" data-roll-key="{{item.id}}"></i>
</a>
<div class="controls">
<a data-tooltip="{{localize 'LETHALFANTASY.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 'LETHALFANTASY.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>
{{/each}}
</div>
</fieldset>
</fieldset>
</div>
</section>

View File

@@ -6,7 +6,7 @@
</div>
<div class="intro-right">
<span>{{upperFirst rollName}}</span>
<span>{{actingCharName}} - {{upperFirst rollName}}</span>
{{#if (match rollType "attack")}}
<span>Attack roll !</span>
@@ -23,6 +23,22 @@
<span>{{rollTarget.weapon.name}}</span>
{{/if}}
{{#if rollData.letItFly}}
<span>Let It Fly attack ! </span>
{{/if}}
{{#if rollData.pointBlank}}
<span>Point Blank Range Attack !</span>
{{/if}}
{{#if rollData.beyondSkill}}
<span>Beyond Skill Range Attack !</span>
{{/if}}
{{#if (eq rollData.favor "favor")}}
<span>Favor roll</span>
{{/if}}
{{#if (eq rollData.favor "disfavor")}}
<span>Disfavor roll</span>
{{/if}}
<span>Formula : {{titleFormula}}</span>
{{#each diceResults as |result|}}

View File

@@ -18,7 +18,7 @@
<fieldSet>
<legend>{{localize "LETHALFANTASY.Roll.visibility"}}</legend>
<select name="visibility">
{{selectOptions rollModes selected=visibility}}
{{selectOptions rollModes selected=visibility localize=true}}
</select>
</fieldSet>

View File

@@ -0,0 +1,39 @@
<nav class="combat-controls" data-tooltip-direction="UP">
{{~#if hasCombat~}}
{{!-- GM Controls --}}
{{#if user.isGM}}
{{#if combat.round}}
<!-- <button type="button" class="inline-control combat-control icon fa-solid fa-backward-step"
data-action="previousRound" data-tooltip aria-label="{{ localize "COMBAT.RoundPrev" }}"></button>
<button type="button" class="inline-control combat-control icon fa-solid fa-arrow-left" data-action="previousTurn"
data-tooltip aria-label="{{ localize "COMBAT.TurnPrev" }}"></button> -->
<button type="button" class="combat-control combat-control-lg" data-action="endCombat">
<i class="fa-solid fa-xmark" inert></i>
<span>{{ localize "COMBAT.End" }}</span>
</button>
<!-- <button type="button" class="inline-control combat-control icon fa-solid fa-arrow-right" data-action="nextTurn"
data-tooltip aria-label="{{ localize "COMBAT.TurnNext" }}"></button> -->
<button type="button" class="inline-control combat-control icon fa-solid fa-forward-step" data-action="nextRound"
data-tooltip aria-label="{{ localize "COMBAT.RoundNext" }}"></button>
{{else}}
<button type="button" class="combat-control combat-control-lg" data-action="startCombat">
<i class="fa-solid fa-swords" inert></i>
<span>{{ localize "COMBAT.Begin" }}</span>
</button>
{{/if}}
{{!-- Active Player Controls --}}
{{else if control}}
<!-- <button type="button" class="inline-control combat-control icon fa-solid fa-arrow-left" data-action="previousTurn"
data-tooltip aria-label="{{ localize "COMBAT.TurnPrev" }}"></button>
<button type="button" class="combat-control combat-control-lg" data-action="nextTurn">
<i class="fa-solid fa-check"></i>
<span>{{ localize "COMBAT.TurnEnd" }}</span>
</button>
<button type="button" class="inline-control combat-control icon fa-solid fa-arrow-right" data-action="nextTurn"
data-tooltip aria-label="{{ localize "COMBAT.TurnNext" }}"></button> -->
{{/if}}
{{/if}}
</nav>

View File

@@ -0,0 +1,92 @@
<header class="combat-tracker-header">
{{!-- Encounter Controls --}}
{{#if user.isGM}}
<nav class="encounters {{ css }}" aria-label="{{ localize "COMBAT.NavLabel" }}">
{{!-- Cycle Display --}}
{{#if displayCycle}}
<button type="button" class="inline-control icon fa-solid fa-plus" data-action="createCombat"
data-tooltip aria-label="{{ localize "COMBAT.Create" }}"></button>
<div class="cycle-combats">
<button type="button" class="inline-control icon fa-solid fa-caret-left" data-action="cycleCombat"
{{#if previousId}}data-combat-id="{{ previousId }}" {{else}}disabled{{/if}}
data-tooltip aria-label="{{ localize "COMBAT.EncounterPrevious" }}"></button>
<div class="encounter-count">
<span class="value">{{ currentIndex }}</span>
<span class="separator">&sol;</span>
<span class="max">{{ combats.length }}</span>
</div>
<button type="button" class="inline-control icon fa-solid fa-caret-right" data-action="cycleCombat"
{{#if nextId}}data-combat-id="{{ nextId }}" {{else}}disabled{{/if}}
data-tooltip aria-label="{{ localize "COMBAT.EncounterNext" }}"></button>
</div>
<button type="button" class="inline-control icon fa-solid fa-gear" data-action="trackerSettings"
data-tooltip aria-label="{{ localize "COMBAT.Settings" }}"></button>
{{!-- Tabbed Display --}}
{{else if combats.length}}
<button type="button" class="inline-control icon fa-solid fa-plus" data-action="createCombat"
data-tooltip aria-label="{{ localize "COMBAT.Create" }}"></button>
{{#each combats}}
<button type="button" class="inline-control {{#if active}}active{{/if}}" data-action="cycleCombat"
data-combat-id="{{ id }}">
{{ label }}
</button>
{{/each}}
<button type="button" class="inline-control icon fa-solid fa-gear" data-action="trackerSettings"
data-tooltip aria-label="{{ localize "COMBAT.Settings" }}"></button>
{{!-- No Combats --}}
{{else}}
<button type="button" class="combat-control-lg" data-action="createCombat">
<i class="fa-solid fa-plus" inert></i>
<span>{{ localize "COMBAT.Create" }}</span>
</button>
{{/if}}
</nav>
{{/if}}
<div class="encounter-controls {{#if hasCombat}}combat{{/if}}">
{{!-- Bulk Rolls --}}
<div class="control-buttons left flexrow">
{{#if user.isGM}}
<button type="button" class="inline-control combat-control icon fa-solid fa-users" data-action="rollAll"
{{#unless combat.turns.length}}disabled{{/unless}} data-tooltip="COMBAT.RollAll"
aria-label="{{ localize "COMBAT.RollAll" }}"></button>
<button type="button" class="inline-control combat-control icon fa-solid fa-users-cog" data-action="rollNPC"
{{#unless combat.turns.length}}disabled{{/unless}} data-tooltip="COMBAT.RollNPC"
aria-label="{{ localize "COMBAT.RollNPC" }}"></button>
{{else}}
<div class="spacer"></div>
<div class="spacer"></div>
{{/if}}
</div>
{{!-- Combat Status --}}
<strong class="encounter-title">
{{#if combats.length}}
{{#if combat.round}}
{{ localize "COMBAT.Round" round=combat.round }}
{{else}}
{{ localize "COMBAT.NotStarted" }}
{{/if}}
{{else}}
{{ localize "COMBAT.None" }}
{{/if}}
</strong>
{{!-- Combat Controls --}}
<div class="control-buttons right flexrow">
<div class="spacer"></div>
<button type="button" class="encounter-context-menu inline-control combat-control icon fa-solid fa-ellipsis-vertical"
{{#unless (and user.isGM hasCombat)}}disabled{{/unless}}></button>
</div>
</div>
</header>

View File

@@ -0,0 +1,81 @@
<ol class="combat-tracker plain">
{{#each turns}}
<li class="combatant {{ css }}" data-combatant-id="{{ id }}" data-action="activateCombatant">
{{!-- TODO: Targets --}}
{{!-- Image --}}
<img class="token-image" src="{{ img }}" alt="{{ name }}" loading="lazy">
{{!-- Name & Controls --}}
<div class="token-name">
<strong class="name">{{ name }}</strong>
<div class="combatant-controls">
{{#if @root.user.isGM}}
<button type="button" class="inline-control combatant-control icon fa-solid fa-eye-slash {{#if hidden}}active{{/if}}"
data-action="toggleHidden" data-tooltip aria-label="{{ localize "COMBAT.ToggleVis" }}"></button>
<button type="button" class="inline-control combatant-control icon fa-solid fa-skull {{#if isDefeated}}active{{/if}}"
data-action="toggleDefeated" data-tooltip
aria-label="{{ localize "COMBAT.ToggleDead" }}"></button>
{{/if}}
{{#if canPing}}
<button type="button" class="inline-control combatant-control icon fa-solid fa-bullseye-arrow"
data-action="pingCombatant" data-tooltip
aria-label="{{ localize "COMBAT.PingCombatant" }}"></button>
{{/if}}
{{#unless @root.user.isGM}}
<button type="button" class="inline-control combatant-control icon fa-solid fa-arrows-to-eye"
data-action="panToCombatant" data-tooltip
aria-label="{{ localize "COMBAT.PanToCombatant" }}"></button>
{{/unless}}
{{!-- TODO: Target Control --}}
<div class="token-effects" data-tooltip-html="{{ effects.tooltip }}">
{{#each effects.icons}}
<img class="token-effect" src="{{ img }}" alt="{{ name }}">
{{/each}}
</div>
</div>
</div>
{{!-- Resource --}}
{{#if resource includeZero=true}}
<div class="token-resource">
<span class="resource">{{ resource }}</span>
</div>
{{/if}}
{{!-- Initiative --}}
<div class="token-initiative initiative-area">
{{#if initiative includeZero=true}}
{{!-- Decimal Initiative --}}
{{#if @root.hasDecimals}}
<span>{{ initiative }}</span>
{{!-- Simple Initiative --}}
{{else}}
<input type="text" class="initiative-input" inputmode="numeric" pattern="^[+=\-]?\d*" value="{{ initiative }}"
aria-label="{{ localize "COMBAT.InitiativeScore" }}" {{#unless @root.user.isGM}}readonly{{/unless}}>
{{/if}}
{{#if isOwner}}
<a data-action="initiativePlus" class="initiative-plus" data-combatant-id="{{this.id}}"><i class="fa-solid fa-hexagon-plus"></i></a>
<a data-action="initiativeMinus" class="initiative-minus" data-combatant-id="{{this.id}}"><i class="fa-solid fa-hexagon-minus"></i></a>
{{/if}}
{{#if isMonster}}
<span class="initiative">-</span>
{{else}}
<span class="initiative" data-tooltip="Current max. progression counter">{{progressionCount}}</span>
{{/if}}
{{!-- Roll Initiative --}}
{{else if isOwner}}
<button type="button" class="combatant-control roll" data-action="rollInitiative" data-tooltip
aria-label="{{ localize "COMBAT.InitiativeRoll" }}"
style="--initiative-icon: url('{{ @root.initiativeIcon.icon }}'); --initiative-icon-hover: url('{{ @root.initiativeIcon.hover }}');"></button>
{{/if}}
</div>
</li>
{{/each}}
</ol>

View File

@@ -4,7 +4,7 @@
<legend>{{localize "LETHALFANTASY.Label.combatDetails"}}</legend>
<div class="combat-details">
<div class="combat-detail">
<button class="action" data-action="rangedAttackDefense">
{{localize "LETHALFANTASY.Label.rangedAttackDefense"}}
</button>
@@ -21,6 +21,9 @@
<div class="attacks">
{{#each system.attacks as |item key|}}
<div class="attack" data-attack-key="{{key}}" >
<div class="">
<input type="checkbox" name="system.attacks.{{item.key}}.enabled" value="{{item.enabled}}" data-tooltip="Attack enabled/disabled" />
</div>
<div class="name">
<input type="text" name="system.attacks.{{item.key}}.name" value="{{item.name}}" data-tooltip="Attack name" />
</div>

View File

@@ -13,13 +13,15 @@
<fieldset class="monster-characteristics monster-characteristics-{{ifThen isPlayMode 'play' 'edit'}}">
<div class="flexrow monster-hp">
<span class="name">{{localize "LETHALFANTASY.Label.HP"}}</span>
{{formInput systemFields.hp.fields.value value=system.hp.value disabled=isPlayMode classes="monster-hp-value"}}
{{formInput systemFields.hp.fields.value value=system.hp.value disabled=isPlayMode
classes="monster-hp-value"}}
&nbsp;/&nbsp;
{{formInput systemFields.hp.fields.max value=system.hp.max disabled=isPlayMode classes="monster-hp-value"}}
</div>
<div class="flexrow monster-hp">
<span class="damage-resistance">{{localize "LETHALFANTASY.Label.damageResistance"}}</span>
{{formInput systemFields.hp.fields.damageResistance value=system.hp.damageResistance disabled=isPlayMode classes="monster-hp-value"}}
{{formInput systemFields.hp.fields.damageResistance value=system.hp.damageResistance disabled=isPlayMode
classes="monster-hp-value"}}
</div>
</fieldset>
@@ -41,7 +43,8 @@
class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.will"}}
</a></span>
{{formField systemFields.saves.fields.will.fields.value value=system.saves.will.value disabled=isPlayMode }}
{{formField systemFields.saves.fields.will.fields.value value=system.saves.will.value disabled=isPlayMode
}}
<span class="name">
<a class="rollable" data-roll-type="save" data-roll-key="dodge"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
@@ -62,25 +65,25 @@
<div class="monster-save">
<span class="name">
<a class="rollable" data-roll-type="save" data-roll-key="contagion"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.contagion"}}
</a>
</span>
</span>
{{formField systemFields.saves.fields.contagion.fields.value value=system.saves.contagion.value
disabled=isPlayMode}}
<span class="name">
<a class="rollable" data-roll-type="save" data-roll-key="poison"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.poison"}}
</a>
</span>
{{formField systemFields.saves.fields.poison.fields.value value=system.saves.poison.value
disabled=isPlayMode }}
<span class="name">
<a class="rollable" data-roll-type="save" data-roll-key="poison"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.poison"}}
</a>
</span>
{{formField systemFields.saves.fields.poison.fields.value value=system.saves.poison.value
disabled=isPlayMode }}
<!-- <span class="name">
<a class="rollable" data-roll-type="save" data-roll-key="paincourage" data-roll-dice="D20" data-tooltip="Pain/Courage check on wound of..."><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.paincourage"}}
</a>
</span>
@@ -88,10 +91,10 @@
<span data-tooltip="Pain save if wound exceeds">
{{formField systemFields.hp.fields.painDamage value=system.hp.painDamage disabled=isPlayMode tooltip="Pain Damage"}}
</span>
</span>-->
</div>
</div>
</fieldset>
@@ -102,19 +105,22 @@
<span class="name"><a class="rollable" data-roll-type="monster-skill" data-roll-key="resistTorture"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.resistTorture"}}</a></span>
{{formField systemFields.resists.fields.resistTorture.fields.value value=system.resists.resistTorture.value
{{formField systemFields.resists.fields.resistTorture.fields.value
value=system.resists.resistTorture.value
disabled=isPlayMode
}}
<span class="name"><a class="rollable" data-roll-type="monster-skill" data-roll-key="resistPerformance"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.resistPerformance"}}</a></span>
{{formField systemFields.resists.fields.resistPerformance.fields.value value=system.resists.resistPerformance.value
disabled=isPlayMode
{{formField systemFields.resists.fields.resistPerformance.fields.value
value=system.resists.resistPerformance.value
disabled=isPlayMode
}}
<span class="name"><a class="rollable" data-roll-type="monster-skill" data-roll-key="resistIntimidation"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
<span class="name"><a class="rollable" data-roll-type="monster-skill"
data-roll-key="resistIntimidation"><i class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.resistIntimidation"}}</a></span>
{{formField systemFields.resists.fields.resistIntimidation.fields.value value=system.resists.resistIntimidation.value
{{formField systemFields.resists.fields.resistIntimidation.fields.value
value=system.resists.resistIntimidation.value
disabled=isPlayMode }}
<span class="name"><a class="rollable" data-roll-type="monster-skill" data-roll-key="perception"><i
@@ -157,7 +163,7 @@
<fieldset class="monster-characteristics monster-characteristics-{{ifThen isPlayMode 'play' 'edit'}}">
<legend>{{localize "LETHALFANTASY.Label.characteristics"}}</legend>
<div class="monster-characteristic">
{{localize "LETHALFANTASY.Label.int"}}
<span>{{localize "LETHALFANTASY.Label.int"}}</span>
{{formField systemFields.characteristics.fields.int.fields.value value=system.characteristics.int.value
disabled=isPlayMode data-char-id="int" }}
@@ -165,7 +171,7 @@
disabled=isPlayMode type="number" }}
</div>
<div class="monster-characteristic">
{{localize "LETHALFANTASY.Label.dex"}}
<span>{{localize "LETHALFANTASY.Label.dex"}}</span>
{{formField systemFields.characteristics.fields.dex.fields.value value=system.characteristics.dex.value
disabled=isPlayMode data-char-id="wis" }}

View File

@@ -1,79 +0,0 @@
<section>
{{!log "opponent sheet" this}}
<div class="opponent-header">
<img class="opponent-img" src="{{actor.img}}" data-edit="img" data-action="editImage" data-tooltip="{{actor.name}}" />
{{formInput fields.name value=source.name}}
<a class="control" data-action="toggleSheet" data-tooltip="TENEBRIS.ToggleSheet" data-tooltip-direction="UP">
<i class="fa-solid fa-user-{{ifThen isPlayMode 'lock' 'pen'}}"></i>
</a>
</div>
<div class="opponent-main">
<div class="opponent-gauche">
<fieldset class="opponent-caracteristiques">
<legend>{{localize "TENEBRIS.Character.Label.caracteristiques"}}</legend>
{{formField systemFields.dv value=system.dv disabled=isPlayMode}}
{{formField systemFields.pv.fields.value value=system.pv.value}}
{{formField systemFields.pv.fields.max value=system.pv.max disabled=isPlayMode}}
{{formField systemFields.armure value=system.armure disabled=isPlayMode}}
{{formField systemFields.malus value=system.malus disabled=isPlayMode}}
{{formField systemFields.actions value=system.actions disabled=isPlayMode}}
</fieldset>
<fieldset class="opponent-attacks">
<legend>{{localize "TENEBRIS.Character.Label.attaques"}}
{{#if isEditMode}}<a class="action" data-tooltip="{{localize 'TENEBRIS.Tooltip.addAttack'}}" data-tooltip-direction="UP"><i
class="fas fa-plus"
data-action="createAttack"
></i></a>{{/if}}</legend>
{{#each attacks as |attack|}}
<div class="opponent-attack" data-drag="true" data-drag-type="attack" data-roll-value="{{attack.system.degats}}" data-roll-target="{{attack.name}}">
<div class="attack-name">
<a
class="rollable"
data-item-id="{{attack.id}}"
data-item-name="{{attack.name}}"
data-action="roll"
data-roll-type="attack"
data-roll-value="{{attack.system.degats}}"
>{{attack.system.degats}}</a>
(<span data-tooltip="{{attack.system.toolTip}}">{{attack.name}}</span>)
</div>
{{#if @root.isEditMode}}
<div class="controls">
<a data-tooltip="{{localize 'TENEBRIS.Edit'}}" data-action="edit" data-item-id="{{attack.id}}" data-item-uuid="{{attack.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'TENEBRIS.Delete'}}" data-action="delete" data-item-id="{{attack.id}}" data-item-uuid="{{attack.uuid}}"><i class="fas fa-trash"></i></a>
</div>
{{/if}}
</div>
{{/each}}
</fieldset>
{{#if (or isEditMode (and isPlayMode hasSpells))}}
<fieldset class="opponent-spells">
<legend>{{localize "TENEBRIS.Label.spells"}}{{#if isEditMode}}<a class="action" data-tooltip="{{localize "TENEBRIS.Tooltip.addSpell"}}" data-tooltip-direction="UP"><i class="fas fa-plus" data-action="createSpell"></i></a>{{/if}}</legend>
{{#each spells as |spell|}}
<div class="opponent-spell">
<div class="name" data-tooltip="{{{spell.system.description}}}">
{{spell.name}}
</div>
{{#if @root.isEditMode}}
<div class="controls">
<a data-tooltip="{{localize 'TENEBRIS.Edit'}}" data-action="edit" data-item-id="{{spell.id}}" data-item-uuid="{{spell.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'TENEBRIS.Delete'}}" data-action="delete" data-item-id="{{spell.id}}" data-item-uuid="{{spell.uuid}}"><i class="fas fa-trash"></i></a>
</div>
{{/if}}
</div>
{{/each}}
</fieldset>
{{/if}}
</div>
<div class="opponent-droite">
<fieldset class="opponent-description">
<legend>{{localize "TENEBRIS.Label.description"}}</legend>
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true compact=true}}
</fieldset>
</div>
</div>
</section>

View File

@@ -26,26 +26,18 @@
<div class="field-section">
<span class="field-name">Range :</span>
<select name="range" data-tooltip-direction="UP">
{{selectOptions rangeChoices selected=range}}
</select>
</div>
<div class="field-section">
<span class="field-name">Aim :</span>
<select name="attackerAim" data-tooltip-direction="UP">
{{selectOptions attackerAimChoices selected=attackerAim}}
</select>
</div>
</fieldSet>
<fieldSet>
<legend>{{localize "LETHALFANTASY.Roll.visibility"}}</legend>
<select name="visibility">
{{selectOptions rollModes selected=visibility}}
{{selectOptions rollModes selected=visibility localize=true}}
</select>
</fieldSet>

View File

@@ -5,7 +5,8 @@
{{#if rollTarget.tokenId}}
<div class="dialog-save">
<a class="goto-token-button" data-action="gotoToken" data-token-id="{{rollTarget.tokenId}}">{{localize "LETHALFANTASY.Label.gotoToken"}} </a>
<a class="goto-token-button" data-action="gotoToken" data-token-id="{{rollTarget.tokenId}}">{{localize
"LETHALFANTASY.Label.gotoToken"}} </a>
</div>
{{/if}}
@@ -30,17 +31,37 @@
{{#if (match rollType "attack")}}
<div class="dialog-save">Add Granted Attack Dice
<input type="checkbox" data-action="selectGranted" name="granted" >
<input type="checkbox" data-action="selectGranted" name="granted">
</div>
{{#if rollTarget.weapon}}
{{#if (eq rollTarget.weapon.system.weaponType "melee")}}
{{else}}
<div class="dialog-save">Point Blank Range Attack
<input type="checkbox" data-action="selectPointBlank" name="pointBlankV">
</div>
<div class="dialog-save">Beyond Skill Range Attack
<input type="checkbox" data-action="selectBeyondSkill" name="beyondSkillV">
</div>
<div class="dialog-save">Let it Fly (Pure D20E)
<input type="checkbox" data-action="selectLetItFly" name="letItFlyV">
</div>
<div class="dialog-save">Aiming
<select name="attackerAim" data-tooltip-direction="UP">
{{selectOptions attackerAimChoices selected=attackerAim}}
</select>
</div>
{{/if}}
{{/if}}
{{/if}}
{{#if (match rollType "defense")}}
<div class="dialog-save">Add Granted Defense Dice
<input type="checkbox" data-action="selectGranted" name="granted" >
<input type="checkbox" data-action="selectGranted" name="granted">
</div>
{{/if}}
{{#if (match rollType "damage")}}
<div class="dialog-save">Add Granted Damage Dice
<input type="checkbox" data-action="selectGranted" name="granted" >
<input type="checkbox" data-action="selectGranted" name="granted">
</div>
{{/if}}
@@ -90,7 +111,7 @@
<fieldSet>
<legend>{{localize "LETHALFANTASY.Roll.visibility"}}</legend>
<select name="visibility">
{{selectOptions rollModes selected=visibility}}
{{selectOptions rollModes selected=visibility localize=true}}
</select>
</fieldSet>

View File

@@ -13,8 +13,8 @@
<fieldSet>
<legend>{{localize "LETHALFANTASY.Roll.visibility"}}</legend>
<select name="visibility">
{{selectOptions rollModes selected=visibility}}
{{selectOptions rollModes selected=visibility localize=true}}
</select>
</fieldSet>
</div>

View File

@@ -13,8 +13,8 @@
<fieldSet>
<legend>{{localize "LETHALFANTASY.Roll.visibility"}}</legend>
<select name="visibility">
{{selectOptions rollModes selected=visibility}}
{{selectOptions rollModes selected=visibility localize=true}}
</select>
</fieldSet>
</div>

View File

@@ -29,7 +29,7 @@
</div>
<div class="align-top">
<label>Destruction</label>
<!-- <label>Destruction</label>
<div class="shift-right">
{{formField systemFields.destruction.fields.bashing value=system.destruction.bashing}}
{{formField systemFields.destruction.fields.slashing value=system.destruction.slashing}}
@@ -41,7 +41,7 @@
{{formField systemFields.autodestruction.fields.bashing value=system.autodestruction.bashing}}
{{formField systemFields.autodestruction.fields.slashing value=system.autodestruction.slashing}}
{{formField systemFields.autodestruction.fields.piercing value=system.autodestruction.piercing}}
</div>
</div> -->
{{formField systemFields.equipped value=system.equipped}}