diff --git a/css/fvtt-lethal-fantasy.css b/css/fvtt-lethal-fantasy.css index a111df4..e342338 100644 --- a/css/fvtt-lethal-fantasy.css +++ b/css/fvtt-lethal-fantasy.css @@ -566,8 +566,33 @@ i.lethalfantasy { } .lethalfantasy .tab.character-spells .spells .spell { display: flex; + align-items: center; gap: 10px; } +.lethalfantasy .tab.character-spells .spells .spell .item-img { + width: 32px; + height: 32px; +} +.lethalfantasy .tab.character-spells .spells .spell .name { + min-width: 12rem; +} +.lethalfantasy .tab.character-spells .miracles { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 10px; +} +.lethalfantasy .tab.character-spells .miracles .miracle { + display: flex; + align-items: center; + gap: 10px; +} +.lethalfantasy .tab.character-spells .miracles .miracle .item-img { + width: 32px; + height: 32px; +} +.lethalfantasy .tab.character-spells .miracles .miracle .name { + min-width: 12rem; +} .lethalfantasy .tab.character-spells .appris { font-weight: bold; } diff --git a/lang/en.json b/lang/en.json index b38fabe..efe6793 100644 --- a/lang/en.json +++ b/lang/en.json @@ -478,6 +478,10 @@ "Platinums": "Platinum" }, "Label": { + "rangeDefenseDialog": "Range defense dialog", + "rangeDefenseRoll": "Range defense roll", + "rangedAttackDefense": "Ranged attack defense", + "miracles": "Miracles", "biodata": "Biodata", "titleChallenge": "Challenge", "titleSave": "Save", diff --git a/module/applications/sheets/character-sheet.mjs b/module/applications/sheets/character-sheet.mjs index 7e978c4..35b5c47 100644 --- a/module/applications/sheets/character-sheet.mjs +++ b/module/applications/sheets/character-sheet.mjs @@ -1,4 +1,5 @@ import LethalFantasyActorSheet from "./base-actor-sheet.mjs" +import LethalFantasyRoll from "../../documents/roll.mjs" export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet { /** @override */ @@ -13,6 +14,7 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet }, actions: { createEquipment: LethalFantasyCharacterSheet.#onCreateEquipment, + rangedAttackDefense: LethalFantasyCharacterSheet.#onRangedAttackDefense, }, } @@ -48,12 +50,15 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet * @returns {Record>} */ #getTabs() { - const tabs = { + let tabs = { skills: { id: "skills", group: "sheet", icon: "fa-solid fa-shapes", label: "LETHALFANTASY.Label.skills" }, weapons: { id: "weapons", group: "sheet", icon: "fa-solid fa-swords", label: "LETHALFANTASY.Label.weapons" }, - spells: { id: "spells", group: "sheet", icon: "fa-sharp-duotone fa-solid fa-wand-magic-sparkles", label: "LETHALFANTASY.Label.spells" }, biography: { id: "biography", group: "sheet", icon: "fa-solid fa-book", label: "LETHALFANTASY.Label.biography" }, } + if (this.actor.system.biodata.magicUser) { + tabs.spells = { id: "spells", group: "sheet", icon: "fa-sharp-duotone fa-solid fa-wand-magic-sparkles", label: "LETHALFANTASY.Label.spells" } + } + for (const v of Object.values(tabs)) { v.active = this.tabGroups[v.group] === v.id v.cssClass = v.active ? "active" : "" @@ -95,6 +100,7 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet case "spells": context.tab = context.tabs.spells context.spells = doc.itemTypes.spell + context.miracles = doc.itemTypes.miracle context.hasSpells = context.spells.length > 0 break case "weapons": @@ -135,21 +141,20 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet await this.document.addPath(item) } + static async #onRangedAttackDefense(event, target) { + const hasTarget = false + let roll = await LethalFantasyRoll.promptRangedDefense({ + actorId: this.actor.id, + actorName: this.actor.name, + actorImage: this.actor.img + }) + if (!roll) return null + + await roll.toMessage({}, { rollMode: roll.options.rollMode }) + } + - /** - * Creates a new attack item directly from the sheet and embeds it into the document. - * @param {Event} event The initiating click event. - * @param {HTMLElement} target The current target of the event listener. - */ static #onCreateEquipment(event, target) { - // Création d'une armure - if (event.shiftKey) { - this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("LETHALFANTASY.Label.newArmor"), type: "armor" }]) - } - // Création d'une arme - else { - this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("LETHALFANTASY.Label.newWeapon"), type: "weapon" }]) - } } getBestWeaponClassSkill(skills, rollType, multiplier = 1.0) { @@ -168,7 +173,7 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet goodSkill = s } } - if (rollType.includes("weapon-damage") ) { + if (rollType.includes("weapon-damage")) { if (s.system.weaponBonus.damage > maxValue) { maxValue = Number(s.system.weaponBonus.damage) goodSkill = s @@ -209,6 +214,14 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet rollTarget.rollKey = rollKey rollTarget.rollDice = event.target.dataset?.rollDice break + case "spell": + rollTarget = this.actor.items.find((i) => i.type === "spell" && i.id === rollKey) + rollTarget.rollKey = rollKey + break + case "miracle": + rollTarget = this.actor.items.find((i) => i.type === "miracle" && i.id === rollKey) + rollTarget.rollKey = rollKey + break case "skill": rollTarget = this.actor.items.find((i) => i.type === "skill" && i.id === rollKey) rollTarget.rollKey = rollKey @@ -260,6 +273,11 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet ui.notifications.error(game.i18n.localize("LETHALFANTASY.Notifications.rollTypeNotFound") + String(rollType)) break } + + // In all cases + rollTarget.magicUser = this.actor.system.biodata.magicUser + rollTarget.actorModifiers = foundry.utils.duplicate(this.actor.system.modifiers) + await this.document.system.roll(rollType, rollTarget) } // #endregion diff --git a/module/config/system.mjs b/module/config/system.mjs index 41adebc..107afb4 100644 --- a/module/config/system.mjs +++ b/module/config/system.mjs @@ -42,6 +42,43 @@ export const MONEY = { } } +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"} +} + +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"} +} + +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"} +} + +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"} +} + +export const ATTACKER_AIM_CHOICES = { + "simple": {label: "Simple (+0)", value: "0"}, + "careful": {label: "Careful (-4)", value: "-4"}, + "focused": {label: "Focused (-8)", value: "-8"} +} + export const DICE_VALUES = { "d3": "D3", "d4": "D4", @@ -151,4 +188,9 @@ export const SYSTEM = { CHOICE_MODIFIERS, CHOICE_DICE, DEV_MODE, + MOVEMENT_CHOICES, + MOVE_DIRECTION_CHOICES, + SIZE_CHOICES, + RANGE_CHOICES, + ATTACKER_AIM_CHOICES } diff --git a/module/documents/roll.mjs b/module/documents/roll.mjs index 714aed6..cd8cdee 100644 --- a/module/documents/roll.mjs +++ b/module/documents/roll.mjs @@ -88,6 +88,10 @@ export default class LethalFantasyRoll extends Roll { return this.options.rollTarget } + get D30result() { + return this.options.D30result + } + /** * Prompt the user with a dialog to configure and execute a roll. * @@ -112,8 +116,11 @@ export default class LethalFantasyRoll extends Roll { let modifierFormula = "1d0" let hasModifier = true let hasChangeDice = false + let hasD30 = false + if (options.rollType === "challenge" || options.rollType === "save") { options.rollName = options.rollTarget.rollKey + hasD30 = options.rollType === "save" if (options.rollTarget.rollKey === "dying") { dice = options.rollTarget.value maxValue = Number(options.rollTarget.value.match(/\d+/)[0]) @@ -123,6 +130,7 @@ export default class LethalFantasyRoll extends Roll { dice = "1D20" maxValue = 20 } + } else if (options.rollType === "skill") { options.rollName = options.rollTarget.name dice = "1D100" @@ -131,7 +139,9 @@ export default class LethalFantasyRoll extends Roll { hasModifier = true hasChangeDice = false options.rollTarget.value = options.rollTarget.system.skillTotal + } else if (options.rollType === "weapon-attack" || options.rollType === "weapon-defense") { + hasD30 = true options.rollName = options.rollTarget.name dice = "1D20" baseFormula = "D20" @@ -145,6 +155,29 @@ export default class LethalFantasyRoll extends Roll { options.rollTarget.value = options.rollTarget.combat.defenseModifier + options.rollTarget.weaponSkillModifier options.rollTarget.charModifier = options.rollTarget.combat.defenseModifier } + + } else if (options.rollType === "spell") { + hasD30 = true + 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 + options.rollTarget.charModifier = options.rollTarget.actorModifiers.intSpellModifier + + } else if (options.rollType === "miracle") { + hasD30 = true + options.rollName = options.rollTarget.name + dice = "1D20" + baseFormula = "D20" + maxValue = 20 + hasModifier = true + hasChangeDice = false + options.rollTarget.value = options.rollTarget.actorModifiers.levelMiracleModifier + options.rollTarget.actorModifiers.chaMiracleModifier + options.rollTarget.charModifier = options.rollTarget.actorModifiers.chaMiracleModifier + } else if (options.rollType.includes("weapon-damage")) { options.rollName = options.rollTarget.name hasModifier = true @@ -174,7 +207,6 @@ export default class LethalFantasyRoll extends Roll { default: "public", }) - const choiceModifier = SYSTEM.CHOICE_MODIFIERS const choiceDice = SYSTEM.CHOICE_DICE @@ -197,6 +229,7 @@ export default class LethalFantasyRoll extends Roll { dice, hasTarget: options.hasTarget, modifier, + saveSpell: false, targetName } console.log("dialogContext", dialogContext) @@ -230,8 +263,10 @@ export default class LethalFantasyRoll extends Roll { let titleFormula = "" dice = rollContext.changeDice || dice if (hasModifier) { - let bonus = Number(options.rollTarget.value) + let bonus = Number(options.rollTarget.value) fullModifier = rollContext.modifier === "" ? 0 : parseInt(rollContext.modifier, 10) + bonus + fullModifier += (rollContext.saveSpell) ? options.rollTarget.actorModifiers.saveModifier : 0 + if (fullModifier === 0) { modifierFormula = "0" } else { @@ -282,13 +317,18 @@ export default class LethalFantasyRoll extends Roll { if (Hooks.call("fvtt-lethal-fantasy.preRoll", options, rollData) === false) return const rollBase = new this(baseFormula, options.data, rollData) - await rollBase.evaluate() const rollModifier = new Roll(modifierFormula, options.data, rollData) - await rollModifier.evaluate() + rollModifier.evaluate() + await rollBase.evaluate() + if (hasD30) { + let rollD30 = await new Roll("1D30").evaluate() + options.D30result = rollD30.total + } let rollTotal = -1 let diceResults = [] let resultType + let diceResult = rollBase.dice[0].results[0].result diceResults.push({ dice: `${dice}`, value: diceResult }) let diceSum = diceResult @@ -314,6 +354,7 @@ export default class LethalFantasyRoll extends Roll { rollBase.options.diceResults = diceResults rollBase.options.rollTarget = options.rollTarget rollBase.options.titleFormula = titleFormula + rollBase.options.D30result = options.D30result /** * A hook event that fires after the roll has been made. @@ -329,6 +370,130 @@ export default class LethalFantasyRoll extends Roll { return rollBase } + static async promptRangedDefense(rollTarget) { + + const rollModes = 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, + default: "public", + }) + + let dialogContext = { + movementChoices : SYSTEM.MOVEMENT_CHOICES, + moveDirectionChoices : SYSTEM.MOVE_DIRECTION_CHOICES, + sizeChoices : SYSTEM.SIZE_CHOICES, + rangeChoices : SYSTEM.RANGE_CHOICES, + attackerAimChoices : SYSTEM.ATTACKER_AIM_CHOICES, + movement: "none", + moveDirection: "none", + size: "medium", + range: "short", + attackerAim: "simple", + fieldRollMode, + rollModes + } + console.log("CTX", dialogContext) + + const content = await 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({ + window: { title: "Range Defense" }, + classes: ["lethalfantasy"], + content, + buttons: [ + { + label: label, + callback: (event, button, dialog) => { + const output = Array.from(button.form.elements).reduce((obj, input) => { + if (input.name) obj[input.name] = input.value + return obj + }, {}) + return output + }, + }, + ], + rejectClose: false // Click on Close button will not launch an error + }) + + console.log("RollContext", rollContext) + // Build the final modifier + let fullModifier = Number(rollContext.moveDirection) + + Number(rollContext.size) + + Number(rollContext.range) + + Number(rollContext.attackerAim) + console.log("Modifier", fullModifier) + + let modifierFormula + if (fullModifier === 0) { + modifierFormula = "0" + } else { + let modAbs = Math.abs(fullModifier) + 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" + + const rollBase = new this(rollContext.movement, options.data, rollData) + const rollModifier = new Roll(modifierFormula, options.data, rollData) + rollModifier.evaluate() + await rollBase.evaluate() + let rollD30 = await new Roll("1D30").evaluate() + options.D30result = rollD30.total + + let dice = rollContext.movement + let maxValue = Number(dice.match(/\d+$/)[0]) // Update the max value agains + let rollTotal = -1 + let diceResults = [] + let resultType + + let diceResult = rollBase.dice[0].results[0].result + diceResults.push({ dice: `${dice}`, value: diceResult }) + let diceSum = diceResult + while (diceResult === maxValue) { + let r = await new Roll(baseFormula).evaluate() + diceResult = r.dice[0].results[0].result + diceResults.push({ dice: `${dice}-1`, value: diceResult - 1 }) + diceSum += (diceResult - 1) + } + if (fullModifier !== 0) { + diceResults.push({ dice: `${rollModifier.formula}`, value: rollModifier.total }) + if (fullModifier < 0) { + rollTotal = Math.max(diceSum - rollModifier.total, 0) + } else { + rollTotal = diceSum + rollModifier.total + } + } else { + rollTotal = diceSum + } + + rollBase.options.resultType = resultType + rollBase.options.rollTotal = rollTotal + rollBase.options.diceResults = diceResults + rollBase.options.rollTarget = options.rollTarget + rollBase.options.titleFormula = `${dice}E + ${modifierFormula}` + rollBase.options.D30result = options.D30result + rollBase.options.rollName = "Ranged Defense" + + /** + * A hook event that fires after the roll has been made. + * @function + * @memberof hookEvents + * @param {Object} options Options for the roll. + * @param {Object} rollData All data related to the roll. + @param {LethalFantasyRoll} roll The resulting roll. + * @returns {boolean} Explicitly return `false` to prevent roll to be made. + */ + + return rollBase + } + /** * Creates a title based on the given type. * @@ -352,6 +517,8 @@ export default class LethalFantasyRoll extends Roll { return `${game.i18n.localize("LETHALFANTASY.Label.weapon-damage-small")}` case "weapon-damage-medium": return `${game.i18n.localize("LETHALFANTASY.Label.weapon-damage-medium")}` + case "spell": + return `${game.i18n.localize("LETHALFANTASY.Label.spell")}` default: return game.i18n.localize("LETHALFANTASY.Label.titleStandard") } @@ -409,6 +576,7 @@ export default class LethalFantasyRoll extends Roll { hasTarget: this.hasTarget, targetName: this.targetName, targetArmor: this.targetArmor, + D30result: this.D30result, isPrivate: isPrivate } cardData.cssClass = cardData.css.join(" ") diff --git a/module/models/character.mjs b/module/models/character.mjs index 1374df4..d14bee4 100644 --- a/module/models/character.mjs +++ b/module/models/character.mjs @@ -90,8 +90,18 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod age: new fields.NumberField({ ...requiredInteger, initial: 15, min: 6 }), height: new fields.NumberField({ ...requiredInteger, initial: 170, min: 50 }), eyes: new fields.StringField({ required: true, nullable: false, initial: "" }), - hair: new fields.StringField({ required: true, nullable: false, initial: "" }) + hair: new fields.StringField({ required: true, nullable: false, initial: "" }), + magicUser: new fields.BooleanField({ initial: false }), }) + + schema.modifiers = new fields.SchemaField({ + levelSpellModifier: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), + saveModifier: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), + levelMiracleModifier: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), + intSpellModifier: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), + chaMiracleModifier: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), + }) + schema.developmentPoints = new fields.SchemaField({ total: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), remaining: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) @@ -133,25 +143,36 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod grit += this.characteristics[c].value } } + + this.modifiers.saveModifier = Math.floor((Number(this.biodata.level) / 5)) + this.modifiers.levelSpellModifier = Math.floor((Number(this.biodata.level) / 5)) + this.modifiers.levelMiracleModifier = Math.floor((Number(this.biodata.level) / 5)) + this.grit.starting = Math.round(grit / 6) let strDef = SYSTEM.CHARACTERISTICS_TABLES.str.find(s => s.value === this.characteristics.str.value) this.challenges.str.value = strDef.challenge + let intDef = SYSTEM.CHARACTERISTICS_TABLES.int.find(s => s.value === this.characteristics.int.value) + this.modifiers.intSpellModifier = intDef.arkane_casting_mod + let dexDef = SYSTEM.CHARACTERISTICS_TABLES.dex.find(s => s.value === this.characteristics.dex.value) this.challenges.agility.value = dexDef.challenge - this.saves.dodge.value = dexDef.dodge + this.saves.dodge.value = dexDef.dodge + this.modifiers.saveModifier let wisDef = SYSTEM.CHARACTERISTICS_TABLES.wis.find(s => s.value === this.characteristics.wis.value) - this.saves.will.value = wisDef.willpower_save + this.saves.will.value = wisDef.willpower_save + this.modifiers.saveModifier + + let chaDef = SYSTEM.CHARACTERISTICS_TABLES.cha.find(s => s.value === this.characteristics.cha.value) + this.modifiers.chaMiracleModifier = chaDef.divine_miracle_bonus let conDef = SYSTEM.CHARACTERISTICS_TABLES.con.find(s => s.value === this.characteristics.con.value) - this.saves.pain.value = conDef.pain_save - this.saves.toughness.value = conDef.toughness_save - this.challenges.dying.value = conDef.stabilization_dice + this.saves.pain.value = conDef.pain_save + this.modifiers.saveModifier + this.saves.toughness.value = conDef.toughness_save + this.modifiers.saveModifier + this.challenges.dying.value = conDef.stabilization_dice - this.saves.contagion.value = this.characteristics.con.value - this.saves.poison.value = this.characteristics.con.value + this.saves.contagion.value = this.characteristics.con.value + this.modifiers.saveModifier + this.saves.poison.value = this.characteristics.con.value + this.modifiers.saveModifier this.combat.attackModifier = 0 for (let chaKey of SYSTEM.CHARACTERISTIC_ATTACK) { diff --git a/packs/lf-equipment/000080.log b/packs/lf-equipment/000084.log similarity index 100% rename from packs/lf-equipment/000080.log rename to packs/lf-equipment/000084.log diff --git a/packs/lf-equipment/CURRENT b/packs/lf-equipment/CURRENT index e347af6..50e566e 100644 --- a/packs/lf-equipment/CURRENT +++ b/packs/lf-equipment/CURRENT @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cee53aaddae873a3860a7adc38b49c3e5efc19026a0aeda2694c61ba44cc3d82 +oid sha256:6e94d01a544f0d82551f19e973a5ac9feb5f9d9984cb5eea8eb4dca0fc55610b size 16 diff --git a/packs/lf-equipment/LOG b/packs/lf-equipment/LOG index 9d40a64..b58316c 100644 --- a/packs/lf-equipment/LOG +++ b/packs/lf-equipment/LOG @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4fd1ddd89e964ce225bcb8c5aaca9954c6feb97d9f38b36874b97b41160d6aad +oid sha256:9980dccdbf09ce54290dc77e11ed5b9ddf57630c073d6a1ead154df1e503c3bd size 736 diff --git a/packs/lf-equipment/LOG.old b/packs/lf-equipment/LOG.old index 43657a3..9d40a64 100644 --- a/packs/lf-equipment/LOG.old +++ b/packs/lf-equipment/LOG.old @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fcd88208cb15880cb62d7ea70f46fe42f8439ef6c8b8280c2193f5594d6a28ad +oid sha256:4fd1ddd89e964ce225bcb8c5aaca9954c6feb97d9f38b36874b97b41160d6aad size 736 diff --git a/packs/lf-equipment/MANIFEST-000078 b/packs/lf-equipment/MANIFEST-000078 deleted file mode 100644 index 4c4685c..0000000 --- a/packs/lf-equipment/MANIFEST-000078 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3039215ef7cf75ba7e107f8de6438ad0be65474e24b9f45f4f61742afce5aba4 -size 137 diff --git a/packs/lf-equipment/MANIFEST-000082 b/packs/lf-equipment/MANIFEST-000082 new file mode 100644 index 0000000..786a529 --- /dev/null +++ b/packs/lf-equipment/MANIFEST-000082 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1fe1bb1d3c8a9b5d69d4283ac8273b3632ada56001796acc0b348adacb3968db +size 137 diff --git a/packs/lf-skills/000080.log b/packs/lf-gifts/000080.log similarity index 100% rename from packs/lf-skills/000080.log rename to packs/lf-gifts/000080.log diff --git a/packs/lf-gifts/CURRENT b/packs/lf-gifts/CURRENT index bc7db31..e347af6 100644 --- a/packs/lf-gifts/CURRENT +++ b/packs/lf-gifts/CURRENT @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:024bce9abfe7d00d97ad0fc14d171098b288dab87035739cb32e49f9ffd10edc +oid sha256:cee53aaddae873a3860a7adc38b49c3e5efc19026a0aeda2694c61ba44cc3d82 size 16 diff --git a/packs/lf-gifts/LOG b/packs/lf-gifts/LOG index acc977f..aac65c6 100644 --- a/packs/lf-gifts/LOG +++ b/packs/lf-gifts/LOG @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:671b77888ba0f1769acaa2b76c59b6d1680ae089784435bd0ecc903f679d9cf7 +oid sha256:70547da069cef8cdd801fb36c4a38a95a73c70151e9523561db76b0daa188314 size 732 diff --git a/packs/lf-gifts/LOG.old b/packs/lf-gifts/LOG.old index 11fa5d2..acc977f 100644 --- a/packs/lf-gifts/LOG.old +++ b/packs/lf-gifts/LOG.old @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bee9b05b1f704df7af1f210d5ac6f31c4da0cdd2100dbe5575cdebaa05410f50 +oid sha256:671b77888ba0f1769acaa2b76c59b6d1680ae089784435bd0ecc903f679d9cf7 size 732 diff --git a/packs/lf-gifts/MANIFEST-000074 b/packs/lf-gifts/MANIFEST-000074 deleted file mode 100644 index eec3e7d..0000000 --- a/packs/lf-gifts/MANIFEST-000074 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:66062cd25d128c332061723ae5bc9ef2e0339616c09f3b99fcdbc8b1ad2d2f91 -size 137 diff --git a/packs/lf-gifts/MANIFEST-000078 b/packs/lf-gifts/MANIFEST-000078 new file mode 100644 index 0000000..0d394f9 --- /dev/null +++ b/packs/lf-gifts/MANIFEST-000078 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e11bdf979f658b698726e2f31577f3e8a08da15684d37c9f6d81edbfd21aa35 +size 137 diff --git a/packs/lf-gifts/000076.log b/packs/lf-skills/000084.log similarity index 100% rename from packs/lf-gifts/000076.log rename to packs/lf-skills/000084.log diff --git a/packs/lf-skills/CURRENT b/packs/lf-skills/CURRENT index e347af6..50e566e 100644 --- a/packs/lf-skills/CURRENT +++ b/packs/lf-skills/CURRENT @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cee53aaddae873a3860a7adc38b49c3e5efc19026a0aeda2694c61ba44cc3d82 +oid sha256:6e94d01a544f0d82551f19e973a5ac9feb5f9d9984cb5eea8eb4dca0fc55610b size 16 diff --git a/packs/lf-skills/LOG b/packs/lf-skills/LOG index 26c5d02..8385a96 100644 --- a/packs/lf-skills/LOG +++ b/packs/lf-skills/LOG @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7256970f4f2c3c4fd326e2c3bfd6b722e88c46db71f40807a4edbb743bcace9 +oid sha256:a95a671147e9d9742163a237d44628d28ec3200a83eb65830d27954428dde8a8 size 736 diff --git a/packs/lf-skills/LOG.old b/packs/lf-skills/LOG.old index 1fa00cd..26c5d02 100644 --- a/packs/lf-skills/LOG.old +++ b/packs/lf-skills/LOG.old @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e83edeb26c0607bcb5b1d36b6a3106b46d53dc7f4cd0e87b90c4d215dee408d4 +oid sha256:d7256970f4f2c3c4fd326e2c3bfd6b722e88c46db71f40807a4edbb743bcace9 size 736 diff --git a/packs/lf-skills/MANIFEST-000078 b/packs/lf-skills/MANIFEST-000078 deleted file mode 100644 index 204372f..0000000 --- a/packs/lf-skills/MANIFEST-000078 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a20a223d0e1f323addaadf2746380c5a39381f123cbc250fbedd651f0958976a -size 137 diff --git a/packs/lf-skills/MANIFEST-000082 b/packs/lf-skills/MANIFEST-000082 new file mode 100644 index 0000000..290b427 --- /dev/null +++ b/packs/lf-skills/MANIFEST-000082 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3549b1d778fffbdbb6f7361e4629435ce34c8ff3ec0cdd4b14e8b8848420294a +size 137 diff --git a/packs/lf-vulnerabilities/000076.log b/packs/lf-vulnerabilities/000080.log similarity index 100% rename from packs/lf-vulnerabilities/000076.log rename to packs/lf-vulnerabilities/000080.log diff --git a/packs/lf-vulnerabilities/CURRENT b/packs/lf-vulnerabilities/CURRENT index bc7db31..e347af6 100644 --- a/packs/lf-vulnerabilities/CURRENT +++ b/packs/lf-vulnerabilities/CURRENT @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:024bce9abfe7d00d97ad0fc14d171098b288dab87035739cb32e49f9ffd10edc +oid sha256:cee53aaddae873a3860a7adc38b49c3e5efc19026a0aeda2694c61ba44cc3d82 size 16 diff --git a/packs/lf-vulnerabilities/LOG b/packs/lf-vulnerabilities/LOG index 428c6ce..36fda00 100644 --- a/packs/lf-vulnerabilities/LOG +++ b/packs/lf-vulnerabilities/LOG @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a36ff5ee75d69bd979cebe4a5a3ca648f055f7700d8ce47d564c3446f9e00d0e +oid sha256:08949d829db0f0db347d5ebdec2173a15a32072cd34b9bc831d8b1175fc2a3d4 size 732 diff --git a/packs/lf-vulnerabilities/LOG.old b/packs/lf-vulnerabilities/LOG.old index 7da86d6..428c6ce 100644 --- a/packs/lf-vulnerabilities/LOG.old +++ b/packs/lf-vulnerabilities/LOG.old @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e23f047b5805b7ff43eb9edc7f640967f7605fb13b4fe666f4d7de16d26be43 +oid sha256:a36ff5ee75d69bd979cebe4a5a3ca648f055f7700d8ce47d564c3446f9e00d0e size 732 diff --git a/packs/lf-vulnerabilities/MANIFEST-000074 b/packs/lf-vulnerabilities/MANIFEST-000074 deleted file mode 100644 index 6f8b511..0000000 --- a/packs/lf-vulnerabilities/MANIFEST-000074 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e0ad290b8fe44d7f1471fda0ae5998561257b79f51d8f48f391c00e67c488f84 -size 137 diff --git a/packs/lf-vulnerabilities/MANIFEST-000078 b/packs/lf-vulnerabilities/MANIFEST-000078 new file mode 100644 index 0000000..16c5e2c --- /dev/null +++ b/packs/lf-vulnerabilities/MANIFEST-000078 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:56680da4e7c4d4d4b6e0ebb4a5d048776a9cbff6a341bf5d06c77bd162f89388 +size 137 diff --git a/styles/character.less b/styles/character.less index 0a41bbe..7eefb1f 100644 --- a/styles/character.less +++ b/styles/character.less @@ -476,7 +476,33 @@ gap: 10px; .spell { display: flex; + align-items: center; gap: 10px; + .item-img { + width: 32px; + height: 32px; + } + .name { + min-width: 12rem; + } + } + } + + .miracles { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 10px; + .miracle { + display: flex; + align-items: center; + gap: 10px; + .item-img { + width: 32px; + height: 32px; + } + .name { + min-width: 12rem; + } } } diff --git a/templates/character-biography.hbs b/templates/character-biography.hbs index 1436ee3..8064246 100644 --- a/templates/character-biography.hbs +++ b/templates/character-biography.hbs @@ -35,6 +35,25 @@ Hair {{formInput systemFields.biodata.fields.hair value=system.biodata.hair }} +
+ Magic User + {{formInput systemFields.biodata.fields.magicUser value=system.biodata.magicUser }} +
+
+ Save bonus (1/5levels) + {{formInput systemFields.modifiers.fields.saveModifier value=system.modifiers.saveModifier disabled=true}} +
+ + {{#if system.biodata.magicUser}} +
+ Spell bonus (1/5levels) + {{formInput systemFields.modifiers.fields.levelSpellModifier value=system.modifiers.levelSpellModifier disabled=true}} +
+
+ Miracle bonus (1/5levels) + {{formInput systemFields.modifiers.fields.levelMiracleModifier value=system.modifiers.levelMiracleModifier disabled=true}} +
+ {{/if}} diff --git a/templates/character-spells.hbs b/templates/character-spells.hbs index 0f47d3f..14b786b 100644 --- a/templates/character-spells.hbs +++ b/templates/character-spells.hbs @@ -6,11 +6,38 @@ data-action="createSpell">{{/if}}
{{#each spells as |item|}} - {{!log 'weapon' this}} -
-
+
+ + +
+ + +
+
+ {{/each}} +
+ + +
+ {{localize "LETHALFANTASY.Label.miracles"}}{{#if isEditMode}}{{/if}} +
+ {{#each miracles as |item|}} +
+ +
+ +
{{localize "LETHALFANTASY.Label.weapons"}} -
{{#each weapons as |item|}} \ No newline at end of file diff --git a/templates/chat-fortune.hbs b/templates/chat-fortune.hbs deleted file mode 100644 index 3909cac..0000000 --- a/templates/chat-fortune.hbs +++ /dev/null @@ -1,17 +0,0 @@ -{{!log 'chat-fortune' this}} -
-
- {{#if (ne actingCharImg "icons/svg/mystery-man.svg")}} -
- -
- {{/if}} -
-

{{localize "TENEBRIS.Chat.askFortune" name=name}}

-
-
- {{#if isGM}} - - - {{/if}} -
\ No newline at end of file diff --git a/templates/chat-message.hbs b/templates/chat-message.hbs index dff5a6e..027ad32 100644 --- a/templates/chat-message.hbs +++ b/templates/chat-message.hbs @@ -45,9 +45,16 @@ {{/if}}
{{/if}} + {{#unless isPrivate}}

{{total}}

+ {{#if D30result}} +
+

D30 result: {{D30result}}

+
+ {{/if}} + {{/unless}}
diff --git a/templates/range-defense-dialog.hbs b/templates/range-defense-dialog.hbs new file mode 100644 index 0000000..7a08e4a --- /dev/null +++ b/templates/range-defense-dialog.hbs @@ -0,0 +1,35 @@ +
+ +
+ {{localize "LETHALFANTASY.Label.rangeDefenseDialog"}} + + + + + + + + + + + +
+ +
+ {{localize "LETHALFANTASY.Roll.visibility"}} + +
+ +
\ No newline at end of file diff --git a/templates/roll-dialog.hbs b/templates/roll-dialog.hbs index 64c2413..801774f 100644 --- a/templates/roll-dialog.hbs +++ b/templates/roll-dialog.hbs @@ -1,4 +1,3 @@ -{{log "roll-dialog" this}}
@@ -16,12 +15,22 @@ {{/if}}
+ {{#if hasModifier}}
{{localize "LETHALFANTASY.Roll.modifierBonusMalus"}} + + {{#if (eq rollType "save")}} + {{#if rollTarget.magicUser}} +
+ Save against spell (+{{rollTarget.actorModifiers.saveModifier}}) ? + +
+ {{/if}} + {{/if}}
{{/if}}