Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
a3c6509862 | |||
c2fe34e7a6 | |||
46176b2782 | |||
b7f13500a6 | |||
bd8b098b35 | |||
71d3f777bf | |||
157163672c | |||
a043117ec7 | |||
791a7d6b67 | |||
2ce5088471 | |||
ebb7bfe3d6 | |||
16959dd52e | |||
ccebf8dc1f | |||
a2364e1252 | |||
d961e130e0 |
20
README.md
20
README.md
@ -1,6 +1,20 @@
|
|||||||
|
|
||||||
<h2><em>Lethal Fantasy RPG</em> for Foundry Virtual TableTop</h2>
|
## Lethal Fantasy RPG for Foundry Virtual TableTop
|
||||||
|
|
||||||
<div align="center">
|
The Official game system for playing Lethal Fantasy TTRPG: The Role Playing Game on FoundryVTT. This fully functional system is the foundational framework to build your game.
|
||||||
|
|
||||||
</div>
|
This product's format, programming code, and presentation is copyrighted by Lethal Fantasy Games LLC.
|
||||||
|
|
||||||
|
This system & product are used with permission granted as part of the partnership agreement between Foundry Gaming LLC and Lethal Fantasy Games LLC. It uses the following trademarks and/or copyrights:
|
||||||
|
|
||||||
|
© 2025 Lethal Fantasy Games. Content copyright Ted McClintock, Lethal Fantasy Games LLC. All Rights Reserved. Lethal Fantasy® is a Registered Trademark of Lethal Fantasy Games LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
Lethal Fantasy Games is ©2025 Lethal Fantasy Games, LLC. All rights reserved. Lethal Fantasy, Lethal Fantasy Games, and their associated logos are trademarks of Lethal Fantasy Games, LLC. https://lethalfantasy.com/
|
||||||
|
|
||||||
|
For inquiries on developing content for this ruleset please contact Lethalted@lethalfantasy.com
|
||||||
|
|
||||||
|
## Community
|
||||||
|
|
||||||
|
Please join our Discord server Lethal Fantasy games https://discord.gg/UDvnnyvreV
|
||||||
|
|
||||||
|
It's the place to ask questions on how to use the system, make feature request and follow the development of the system.
|
1
assets/icons/broken-heart.svg
Normal file
1
assets/icons/broken-heart.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M373.47 25.5c-33.475-.064-67.614 13.444-94.44 43.156l37.22 145.156-33.437.032 35.343 132.093-116.718-188.375 50.03 5.375L202.5 47.312C120.437-1.43 4.756 40.396 8.5 158.156c4.402 138.44 191.196 184.6 247.406 331.625 59.376-147.035 251.26-184.33 246.656-331.624-2.564-82.042-64.6-132.532-129.093-132.656z" fill="#fff" fill-opacity="1"></path></g></svg>
|
After Width: | Height: | Size: 506 B |
@ -1951,6 +1951,18 @@ i.lethalfantasy {
|
|||||||
.lethalfantasy-roll-dialog fieldset {
|
.lethalfantasy-roll-dialog fieldset {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
|
.lethalfantasy-roll-dialog .goto-token-button {
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
max-width: 8rem;
|
||||||
|
background-color: var(--color-dark-6);
|
||||||
|
color: var(--color-dark-2);
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
.lethalfantasy-range-defense-dialog {
|
.lethalfantasy-range-defense-dialog {
|
||||||
width: 18rem;
|
width: 18rem;
|
||||||
}
|
}
|
||||||
@ -2058,22 +2070,39 @@ i.lethalfantasy {
|
|||||||
font-size: calc(var(--font-size-standard) * 1);
|
font-size: calc(var(--font-size-standard) * 1);
|
||||||
text-shadow: 0 0 10px var(--color-shadow-primary);
|
text-shadow: 0 0 10px var(--color-shadow-primary);
|
||||||
}
|
}
|
||||||
#lethalfantasy-application-manager {
|
#token-hud .hp-loss-wrap {
|
||||||
display: flex;
|
position: absolute;
|
||||||
font-family: var(--font-primary);
|
left: 75px;
|
||||||
font-size: calc(var(--font-size-standard) * 1);
|
display: none;
|
||||||
color: var(--color-dark-1);
|
top: 50%;
|
||||||
|
width: 48px;
|
||||||
|
text-align: start;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
#token-hud .hp-loss-wrap-col1 {
|
||||||
|
transform: translate(-200%, -50%);
|
||||||
|
}
|
||||||
|
#token-hud .hp-loss-wrap-col2 {
|
||||||
|
transform: translate(-300%, -50%);
|
||||||
|
}
|
||||||
|
#token-hud .hp-loss-wrap-col3 {
|
||||||
|
transform: translate(-400%, -50%);
|
||||||
|
}
|
||||||
|
#token-hud .hp-loss-hud-active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#token-hud .hp-loss-hud-disabled {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#token-hud .hud-loss-hp-button-select {
|
||||||
|
max-width: 40px;
|
||||||
background-image: var(--background-image-base);
|
background-image: var(--background-image-base);
|
||||||
background-repeat: no-repeat;
|
padding-top: 0;
|
||||||
background-size: 100% 100%;
|
padding-bottom: 0;
|
||||||
}
|
width: max-content;
|
||||||
#lethalfantasy-application-manager .lethalfantasy-table {
|
|
||||||
margin: 1rem;
|
|
||||||
background: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
#lethalfantasy-application-manager .lethalfantasy-table .player {
|
#token-hud .hp-loss-wrap .hud-loss-hp-button-select {
|
||||||
font-size: calc(var(--font-size-standard) * 1);
|
padding-left: 8px;
|
||||||
|
font-size: 0.7rem;
|
||||||
}
|
}
|
||||||
|
@ -281,6 +281,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Label": {
|
"Label": {
|
||||||
|
"gotoToken": "Go to token",
|
||||||
"combatAction": "Combat action",
|
"combatAction": "Combat action",
|
||||||
"currentAction": "Current ongoing action",
|
"currentAction": "Current ongoing action",
|
||||||
"selectAction": "Select an action",
|
"selectAction": "Select an action",
|
||||||
@ -288,6 +289,7 @@
|
|||||||
"spell-attack": "Spell - Attack",
|
"spell-attack": "Spell - Attack",
|
||||||
"miracle-power": "Miracle - Power",
|
"miracle-power": "Miracle - Power",
|
||||||
"miracle-attack": "Miracle - Attack",
|
"miracle-attack": "Miracle - Attack",
|
||||||
|
"spell": "Spell",
|
||||||
"will":"Will",
|
"will":"Will",
|
||||||
"dodge":"Dodge",
|
"dodge":"Dodge",
|
||||||
"toughness":"Toughness",
|
"toughness":"Toughness",
|
||||||
@ -489,11 +491,11 @@
|
|||||||
"rollTypeNotFound": "Roll type not found",
|
"rollTypeNotFound": "Roll type not found",
|
||||||
"skillNotFound": "Skill not found",
|
"skillNotFound": "Skill not found",
|
||||||
"messageProgressionOK": "{name} can perform his action !",
|
"messageProgressionOK": "{name} can perform his action !",
|
||||||
"messageLethargyOK": "Lethargy ended. <br>{name} can perform a new action !",
|
"messageLethargyOK": "{spellName} : Lethargy ended ( dice result {roll}). <br>{name} can perform a new action !",
|
||||||
"messageLethargyKO": "Lethargy stil ongoing ...",
|
"messageLethargyKO": "{spellName} : Lethargy still ongoing ... ( dice result : {roll} )",
|
||||||
"messageProgressionKO": "{name} can't attack this second.",
|
"messageProgressionKO": "{name} can't attack this second.",
|
||||||
"messageProgressionOKMonster": "{name} can attack this second with {weapon}.",
|
"messageProgressionOKMonster": "{name} can attack this second with {weapon}.",
|
||||||
"messageProgressionKOMonster": "{name} can't attack this second."
|
"messageProgressionKOMonster": "{name} can't attack this second (dice result {roll})."
|
||||||
},
|
},
|
||||||
"Opponent": {
|
"Opponent": {
|
||||||
"FIELDS": {}
|
"FIELDS": {}
|
||||||
|
@ -89,12 +89,13 @@ Hooks.once("init", function () {
|
|||||||
|
|
||||||
setupTextEnrichers()
|
setupTextEnrichers()
|
||||||
LethalFantasyUtils.registerHandlebarsHelpers()
|
LethalFantasyUtils.registerHandlebarsHelpers()
|
||||||
|
LethalFantasyUtils.setHookListeners( )
|
||||||
|
|
||||||
console.info("LETHAL FANTASY | System Initialized")
|
console.info("LETHAL FANTASY | System Initialized")
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform one-time configuration of system configuration objects.
|
* Perform one-time configuration of system configuration objects.f
|
||||||
*/
|
*/
|
||||||
function preLocalizeConfig() {
|
function preLocalizeConfig() {
|
||||||
const localizeConfigObject = (obj, keys) => {
|
const localizeConfigObject = (obj, keys) => {
|
||||||
@ -117,6 +118,7 @@ Hooks.once("ready", function () {
|
|||||||
if (!SYSTEM.DEV_MODE) {
|
if (!SYSTEM.DEV_MODE) {
|
||||||
registerWorldCount("lethalFantasy")
|
registerWorldCount("lethalFantasy")
|
||||||
}
|
}
|
||||||
|
|
||||||
_showUserGuide()
|
_showUserGuide()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,7 +131,12 @@ Hooks.once("ready", function () {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Hooks.on("renderChatMessage", (message, html, data) => {
|
// Test if version below 13
|
||||||
|
let hookName = "renderChatMessage"
|
||||||
|
if (foundry.utils.isNewerVersion(game.version, "12.0", )) {
|
||||||
|
hookName = "renderChatMessageHTML"
|
||||||
|
}
|
||||||
|
Hooks.on(hookName, (message, html, data) => {
|
||||||
const typeMessage = data.message.flags.lethalFantasy?.typeMessage
|
const typeMessage = data.message.flags.lethalFantasy?.typeMessage
|
||||||
// Message de demande de jet de dés
|
// Message de demande de jet de dés
|
||||||
if (typeMessage === "askRoll") {
|
if (typeMessage === "askRoll") {
|
||||||
@ -152,7 +159,7 @@ Hooks.on("renderChatMessage", (message, html, data) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Hooks.on("getCombatTrackerEntryContext", (html, options) => {
|
Hooks.on("getCombatTrackerEntryContext", (html, options) => {
|
||||||
LethalFantasyUtils.pushCombatOptions(html, options);
|
LethalFantasyUtils.pushCombatOptions(html, options);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -181,4 +188,4 @@ async function registerWorldCount(registerKey) {
|
|||||||
console.log("No usage log ")
|
console.log("No usage log ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -138,7 +138,6 @@ export class LethalFantasyCombat extends Combat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async nextRound() {
|
async nextRound() {
|
||||||
console.log('NEXT ROUND')
|
|
||||||
this.turnsDone = false
|
this.turnsDone = false
|
||||||
|
|
||||||
let turn = this.turn === null ? null : 0; // Preserve the fact that it's no-one's turn currently.
|
let turn = this.turn === null ? null : 0; // Preserve the fact that it's no-one's turn currently.
|
||||||
@ -162,13 +161,12 @@ export class LethalFantasyCombat extends Combat {
|
|||||||
|
|
||||||
for (let c of this.combatants) {
|
for (let c of this.combatants) {
|
||||||
if ( nextRound >= c.initiative) {
|
if ( nextRound >= c.initiative) {
|
||||||
c.update({ 'system.progressionCount': c.system.progressionCount + 1 });
|
|
||||||
let user = game.users.find(u => u.active && u.character && u.character.id === c.actor.id);
|
let user = game.users.find(u => u.active && u.character && u.character.id === c.actor.id);
|
||||||
if (user?.hasPlayerOwner) {
|
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 {
|
} else {
|
||||||
user = game.users.find(u => u.active && u.isGM);
|
user = game.users.find(u => u.active && u.isGM);
|
||||||
c.actor.system.rollProgressionDice(this.id, c.id, c.system.progressionCount+1);
|
c.actor.system.rollProgressionDice(this.id, c.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,6 +250,7 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
|
|||||||
|
|
||||||
async _onRoll(event, target) {
|
async _onRoll(event, target) {
|
||||||
if (this.isEditMode) return
|
if (this.isEditMode) return
|
||||||
|
console.log("Roll event", event)
|
||||||
const rollType = event.target.dataset.rollType
|
const rollType = event.target.dataset.rollType
|
||||||
let rollKey = event.target.dataset.rollKey;
|
let rollKey = event.target.dataset.rollKey;
|
||||||
let rollDice = event.target.dataset?.rollDice;
|
let rollDice = event.target.dataset?.rollDice;
|
||||||
|
@ -166,71 +166,8 @@ export default class LethalFantasyMonsterSheet extends LethalFantasyActorSheet {
|
|||||||
async _onRoll(event, target) {
|
async _onRoll(event, target) {
|
||||||
if (this.isEditMode) return
|
if (this.isEditMode) return
|
||||||
const rollType = event.target.dataset.rollType
|
const rollType = event.target.dataset.rollType
|
||||||
let rollTarget
|
|
||||||
let rollKey = event.target.dataset.rollKey
|
let rollKey = event.target.dataset.rollKey
|
||||||
switch (rollType) {
|
let rollDice = event.target.dataset?.rollDice || "0"
|
||||||
case "monster-attack":
|
this.actor.system.prepareMonsterRoll(rollType, rollKey, rollDice)
|
||||||
case "monster-defense":
|
|
||||||
case "monster-damage":
|
|
||||||
rollTarget = foundry.utils.duplicate(this.document.system.attacks[rollKey])
|
|
||||||
rollTarget.rollKey = rollKey
|
|
||||||
break
|
|
||||||
case "monster-skill":
|
|
||||||
rollTarget = foundry.utils.duplicate(this.document.system.resists[rollKey])
|
|
||||||
rollTarget.rollKey = rollKey
|
|
||||||
break
|
|
||||||
case "save":
|
|
||||||
rollTarget = foundry.utils.duplicate(this.document.system.saves[rollKey])
|
|
||||||
rollTarget.rollKey = rollKey
|
|
||||||
rollTarget.rollDice = event.target.dataset?.rollDice
|
|
||||||
break
|
|
||||||
case "weapon-damage-small":
|
|
||||||
case "weapon-damage-medium":
|
|
||||||
case "weapon-attack":
|
|
||||||
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())
|
|
||||||
if (skills.length > 0) {
|
|
||||||
skill = this.getBestWeaponClassSkill(skills, rollType, 1.0)
|
|
||||||
} else {
|
|
||||||
skills = this.actor.items.filter((i) => i.type === "skill" && i.name.toLowerCase().replace(" skill", "") === weapon.name.toLowerCase())
|
|
||||||
if (skills.length > 0) {
|
|
||||||
skill = this.getBestWeaponClassSkill(skills, rollType, 1.0)
|
|
||||||
} else {
|
|
||||||
skills = this.actor.items.filter((i) => i.type === "skill" && i.system.weaponClass === weapon.system.weaponClass)
|
|
||||||
if (skills.length > 0) {
|
|
||||||
skill = this.getBestWeaponClassSkill(skills, rollType, 0.5)
|
|
||||||
} else {
|
|
||||||
skills = this.actor.items.filter((i) => i.type === "skill" && i.system.weaponClass.includes(SYSTEM.WEAPON_CATEGORIES[weapon.system.weaponClass]))
|
|
||||||
if (skills.length > 0) {
|
|
||||||
skill = this.getBestWeaponClassSkill(skills, rollType, 0.25)
|
|
||||||
} else {
|
|
||||||
ui.notifications.warn(game.i18n.localize("LETHALFANTASY.Notifications.skillNotFound"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!weapon || !skill) {
|
|
||||||
console.error("Weapon or skill not found", weapon, skill)
|
|
||||||
ui.notifications.warn(game.i18n.localize("LETHALFANTASY.Notifications.skillNotFound"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rollTarget = skill
|
|
||||||
rollTarget.weapon = weapon
|
|
||||||
rollTarget.weaponSkillModifier = skill.weaponSkillModifier
|
|
||||||
rollTarget.rollKey = rollKey
|
|
||||||
rollTarget.combat = foundry.utils.duplicate(this.actor.system.combat)
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
ui.notifications.error(game.i18n.localize("LETHALFANTASY.Notifications.rollTypeNotFound") + String(rollType))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// In all cases
|
|
||||||
console.log(rollTarget)
|
|
||||||
await this.document.system.roll(rollType, rollTarget)
|
|
||||||
}
|
}
|
||||||
// #endregion
|
|
||||||
}
|
}
|
||||||
|
@ -53,10 +53,12 @@ export const MORTAL_CHOICES = {
|
|||||||
"shirefolk": {label: "Shire Folk", value: "Shire Folk", defenseBonus: 2},
|
"shirefolk": {label: "Shire Folk", value: "Shire Folk", defenseBonus: 2},
|
||||||
"Elf": {label: "Elf", value: "Elf", defenseBonus: 0},
|
"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},
|
||||||
|
"Half-Orc": {label: "Half-Orc", value: "Half-Orc", defenseBonus: 0},
|
||||||
"Dwarf": {label: "Dwarf", value: "Dwarf", defenseBonus: 0},
|
"Dwarf": {label: "Dwarf", value: "Dwarf", defenseBonus: 0},
|
||||||
"Half-elf": {label: "Half-Elf", value: "Half-Elf", defenseBonus: 0},
|
"Half-elf": {label: "Half-Elf", value: "Half-Elf", defenseBonus: 0},
|
||||||
"Gnome": {label: "Gnome", value: "Gnome", defenseBonus: 2},
|
"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},
|
||||||
|
"Shire folk": {label: "Shire Folk", value: "Shire Folk", defenseBonus: 2},
|
||||||
"Mankind": {label: "Human", value: "Human", defenseBonus: 0},
|
"Mankind": {label: "Human", value: "Human", defenseBonus: 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +98,7 @@ export const RANGE_CHOICES = {
|
|||||||
"extreme": {label: "Extreme (+20)", value: "+20"},
|
"extreme": {label: "Extreme (+20)", value: "+20"},
|
||||||
"beyondskill": {label: "Beyond Skill (+25)", value: "+25"}
|
"beyondskill": {label: "Beyond Skill (+25)", value: "+25"}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ATTACKER_AIM_CHOICES = {
|
export const ATTACKER_AIM_CHOICES = {
|
||||||
"simple": {label: "Simple (+0)", value: "0"},
|
"simple": {label: "Simple (+0)", value: "0"},
|
||||||
"careful": {label: "Careful (-4)", value: "-4"},
|
"careful": {label: "Careful (-4)", value: "-4"},
|
||||||
@ -119,7 +121,7 @@ export const INITIATIVE_DICE_CHOICES_PER_CLASS = {
|
|||||||
{ "name": "Aware of the enemy, can hear them but not see (2D4)", "value": "2D4" },
|
{ "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 and know exactly where the enemy is (2D3)", "value": "2D3" }
|
||||||
],
|
],
|
||||||
"fighter": [
|
"fighter": [
|
||||||
{ "name": "Asleep or totally distracted (1D12)", "value": "1D12" },
|
{ "name": "Asleep or totally distracted (1D12)", "value": "1D12" },
|
||||||
{ "name": "Awake but unsuspecting (1D8)", "value": "1D8" },
|
{ "name": "Awake but unsuspecting (1D8)", "value": "1D8" },
|
||||||
{ "name": "Declared Ready on Alert (1D6)", "value": "1D6" },
|
{ "name": "Declared Ready on Alert (1D6)", "value": "1D6" },
|
||||||
@ -163,7 +165,7 @@ export const CHAR_CLASSES = {
|
|||||||
"rogue": "Rogue",
|
"rogue": "Rogue",
|
||||||
"ranger": "Ranger",
|
"ranger": "Ranger",
|
||||||
"cleric": "Cleric",
|
"cleric": "Cleric",
|
||||||
"magicuser": "Magic User"
|
"magicuser": "Magic User"
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CHAR_CLASSES_DEFINES = {
|
export const CHAR_CLASSES_DEFINES = {
|
||||||
@ -176,7 +178,7 @@ export const CHAR_CLASSES_DEFINES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const DICE_VALUES = {
|
export const DICE_VALUES = {
|
||||||
"d3": "D3",
|
"d3": "D3",
|
||||||
"d4": "D4",
|
"d4": "D4",
|
||||||
"d6": "D6",
|
"d6": "D6",
|
||||||
"d8": "D8",
|
"d8": "D8",
|
||||||
@ -191,7 +193,8 @@ export const CHARACTERISTIC_DEFENSE = [ "int", "wis", "dex" ]
|
|||||||
export const CHARACTERISTIC_DAMAGE = [ "str" ]
|
export const CHARACTERISTIC_DAMAGE = [ "str" ]
|
||||||
|
|
||||||
export const DEFENSE_DICE_VALUES = {
|
export const DEFENSE_DICE_VALUES = {
|
||||||
"d3": "D3",
|
"0": "0",
|
||||||
|
"d3": "D3",
|
||||||
"d4": "D4",
|
"d4": "D4",
|
||||||
"d6": "D6",
|
"d6": "D6",
|
||||||
"d8": "D8",
|
"d8": "D8",
|
||||||
@ -280,7 +283,7 @@ export const SYSTEM = {
|
|||||||
id: SYSTEM_ID,
|
id: SYSTEM_ID,
|
||||||
CHARACTERISTICS: CHARACTER.CHARACTERISTICS,
|
CHARACTERISTICS: CHARACTER.CHARACTERISTICS,
|
||||||
CHARACTERISTICS_TABLES: CHARACTERISTICS.TABLES,
|
CHARACTERISTICS_TABLES: CHARACTERISTICS.TABLES,
|
||||||
CHARACTERISTICS_MAJOR: CHARACTERISTICS.MAJOR,
|
CHARACTERISTICS_MAJOR: CHARACTERISTICS.MAJOR,
|
||||||
MONSTER_CHARACTERISTICS: MONSTER.MONSTER_CHARACTERISTICS,
|
MONSTER_CHARACTERISTICS: MONSTER.MONSTER_CHARACTERISTICS,
|
||||||
MONSTER_RESIST: MONSTER.MONSTER_RESIST,
|
MONSTER_RESIST: MONSTER.MONSTER_RESIST,
|
||||||
MONSTER_SAVES: MONSTER.MONSTER_SAVES,
|
MONSTER_SAVES: MONSTER.MONSTER_SAVES,
|
||||||
|
@ -41,6 +41,7 @@ export default class LethalFantasyActor extends Actor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* *************************************************/
|
||||||
getBestWeaponClassSkill(skills, rollType, multiplier = 1.0) {
|
getBestWeaponClassSkill(skills, rollType, multiplier = 1.0) {
|
||||||
let maxValue = 0
|
let maxValue = 0
|
||||||
let goodSkill = skills[0]
|
let goodSkill = skills[0]
|
||||||
@ -68,6 +69,16 @@ export default class LethalFantasyActor extends Actor {
|
|||||||
return goodSkill
|
return goodSkill
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* *************************************************/
|
||||||
|
async applyDamage(hpLoss) {
|
||||||
|
let hp = this.system.hp.value + hpLoss
|
||||||
|
if (hp < 0) {
|
||||||
|
hp = 0
|
||||||
|
}
|
||||||
|
this.update({ "system.hp.value": hp })
|
||||||
|
}
|
||||||
|
|
||||||
|
/* *************************************************/
|
||||||
async prepareRoll(rollType, rollKey, rollDice ) {
|
async prepareRoll(rollType, rollKey, rollDice ) {
|
||||||
console.log("Preparing roll", rollType, rollKey, rollDice)
|
console.log("Preparing roll", rollType, rollKey, rollDice)
|
||||||
let rollTarget
|
let rollTarget
|
||||||
|
@ -221,9 +221,13 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
hasChangeDice = false
|
hasChangeDice = false
|
||||||
options.rollTarget.value = options.rollTarget.actorModifiers.levelSpellModifier + options.rollTarget.actorModifiers.intSpellModifier
|
options.rollTarget.value = options.rollTarget.actorModifiers.levelSpellModifier + options.rollTarget.actorModifiers.intSpellModifier
|
||||||
options.rollTarget.charModifier = options.rollTarget.actorModifiers.intSpellModifier
|
options.rollTarget.charModifier = options.rollTarget.actorModifiers.intSpellModifier
|
||||||
hasStaticModifier = true // options.rollType === "spell-power"
|
hasStaticModifier = options.rollType === "spell-power"
|
||||||
hasModifier = true //options.rollType !== "spell-attack"
|
//hasModifier = options.rollType !== "spell-attack"
|
||||||
options.rollTarget.staticModifier = options.rollTarget.actorLevel
|
if (hasStaticModifier) {
|
||||||
|
options.rollTarget.staticModifier = options.rollTarget.actorLevel
|
||||||
|
} else {
|
||||||
|
options.rollTarget.staticModifier = 0
|
||||||
|
}
|
||||||
|
|
||||||
} else if (options.rollType === "miracle" || options.rollType === "miracle-attack" || options.rollType === "miracle-power") {
|
} else if (options.rollType === "miracle" || options.rollType === "miracle-attack" || options.rollType === "miracle-power") {
|
||||||
hasD30 = true
|
hasD30 = true
|
||||||
@ -234,9 +238,13 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
hasChangeDice = false
|
hasChangeDice = false
|
||||||
options.rollTarget.value = options.rollTarget.actorModifiers.levelMiracleModifier + options.rollTarget.actorModifiers.chaMiracleModifier
|
options.rollTarget.value = options.rollTarget.actorModifiers.levelMiracleModifier + options.rollTarget.actorModifiers.chaMiracleModifier
|
||||||
options.rollTarget.charModifier = options.rollTarget.actorModifiers.chaMiracleModifier
|
options.rollTarget.charModifier = options.rollTarget.actorModifiers.chaMiracleModifier
|
||||||
hasStaticModifier = true // options.rollType === "spell-power"
|
hasStaticModifier = options.rollType === "miracle-power"
|
||||||
hasModifier = true // options.rollType !== "miracle-attack"
|
//hasModifier = options.rollType !== "miracle-attack"
|
||||||
options.rollTarget.staticModifier = options.rollTarget.actorLevel
|
if (hasStaticModifier) {
|
||||||
|
options.rollTarget.staticModifier = options.rollTarget.actorLevel
|
||||||
|
} else {
|
||||||
|
options.rollTarget.staticModifier = 0
|
||||||
|
}
|
||||||
|
|
||||||
} else if (options.rollType === "shield-roll") {
|
} else if (options.rollType === "shield-roll") {
|
||||||
hasD30 = false
|
hasD30 = false
|
||||||
@ -284,7 +292,10 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
hasModifier = false
|
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 = 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({
|
const fieldRollMode = new foundry.data.fields.StringField({
|
||||||
choices: rollModes,
|
choices: rollModes,
|
||||||
blank: false,
|
blank: false,
|
||||||
@ -302,6 +313,7 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
rollType: options.rollType,
|
rollType: options.rollType,
|
||||||
rollTarget: options.rollTarget,
|
rollTarget: options.rollTarget,
|
||||||
rollName: options.rollName,
|
rollName: options.rollName,
|
||||||
|
actorName: options.actorName,
|
||||||
rollModes,
|
rollModes,
|
||||||
hasModifier,
|
hasModifier,
|
||||||
hasFavor,
|
hasFavor,
|
||||||
@ -322,16 +334,19 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
}
|
}
|
||||||
const content = await renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-dialog.hbs", dialogContext)
|
const content = await renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-dialog.hbs", dialogContext)
|
||||||
|
|
||||||
const title = LethalFantasyRoll.createTitle(options.rollType, options.rollTarget)
|
let position = game.user.getFlag(SYSTEM.id, "roll-dialog-pos") || { top: -1, left: -1 }
|
||||||
const label = game.i18n.localize("LETHALFANTASY.Roll.roll")
|
const label = game.i18n.localize("LETHALFANTASY.Roll.roll")
|
||||||
const rollContext = await foundry.applications.api.DialogV2.wait({
|
const rollContext = await foundry.applications.api.DialogV2.wait({
|
||||||
window: { title: title },
|
window: { title: "Roll dialog" },
|
||||||
classes: ["lethalfantasy"],
|
classes: ["lethalfantasy"],
|
||||||
content,
|
content,
|
||||||
|
position,
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
label: label,
|
label: label,
|
||||||
callback: (event, button, dialog) => {
|
callback: (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) => {
|
const output = Array.from(button.form.elements).reduce((obj, input) => {
|
||||||
if (input.name) obj[input.name] = input.value
|
if (input.name) obj[input.name] = input.value
|
||||||
return obj
|
return obj
|
||||||
@ -343,6 +358,15 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
actions: {
|
actions: {
|
||||||
"selectGranted": (event, button, dialog) => {
|
"selectGranted": (event, button, dialog) => {
|
||||||
hasGrantedDice = true
|
hasGrantedDice = true
|
||||||
|
},
|
||||||
|
"gotoToken" : (event, button, dialog) => {
|
||||||
|
let tokenId = $(button).data("tokenId")
|
||||||
|
let token = canvas.tokens?.get(tokenId)
|
||||||
|
if (token) {
|
||||||
|
canvas.animatePan({ x: token.x, y: token.y, duration: 200 })
|
||||||
|
canvas.tokens.releaseAll();
|
||||||
|
token.control({ releaseOthers: true });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rejectClose: false // Click on Close button will not launch an error
|
rejectClose: false // Click on Close button will not launch an error
|
||||||
@ -373,7 +397,7 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
if (hasStaticModifier) {
|
if (hasStaticModifier) {
|
||||||
modifierFormula += ` + ${options.rollTarget.staticModifier}`
|
modifierFormula += ` + ${options.rollTarget.staticModifier}`
|
||||||
}
|
}
|
||||||
modifierFormula += ` + ${options.rollTarget.charModifier}`
|
// modifierFormula += ` + ${options.rollTarget.charModifier}`
|
||||||
let sign = fullModifier < 0 ? "-" : "+"
|
let sign = fullModifier < 0 ? "-" : "+"
|
||||||
if (hasExplode) {
|
if (hasExplode) {
|
||||||
titleFormula = `${dice}E ${sign} ${modifierFormula}`
|
titleFormula = `${dice}E ${sign} ${modifierFormula}`
|
||||||
@ -543,6 +567,7 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
return rollBase
|
return rollBase
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ***********************************************************/
|
||||||
static async promptInitiative(options = {}) {
|
static async promptInitiative(options = {}) {
|
||||||
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||||
const fieldRollMode = new foundry.data.fields.StringField({
|
const fieldRollMode = new foundry.data.fields.StringField({
|
||||||
@ -603,6 +628,7 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ***********************************************************/
|
||||||
static async promptCombatAction(options = {}) {
|
static async promptCombatAction(options = {}) {
|
||||||
|
|
||||||
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||||
@ -619,6 +645,8 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
}
|
}
|
||||||
let currentAction = combatant.getFlag(SYSTEM.id, "currentAction")
|
let currentAction = combatant.getFlag(SYSTEM.id, "currentAction")
|
||||||
|
|
||||||
|
let position = game.user.getFlag(SYSTEM.id, "combat-action-dialog-pos") || { top: -1, left: -1 }
|
||||||
|
|
||||||
let dialogContext = {
|
let dialogContext = {
|
||||||
progressionDiceId: "",
|
progressionDiceId: "",
|
||||||
fieldRollMode,
|
fieldRollMode,
|
||||||
@ -636,33 +664,45 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
action: "roll",
|
action: "roll",
|
||||||
label: "Roll progression dice",
|
label: "Roll progression dice",
|
||||||
callback: (event, button, dialog) => {
|
callback: (event, button, dialog) => {
|
||||||
|
let pos = $('#combat-action-dialog').position()
|
||||||
|
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", pos)
|
||||||
return "rollProgressionDice"
|
return "rollProgressionDice"
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
} else if (currentAction.type === "spell" || currentAction.type === "miracle") {
|
} else if (currentAction.type === "spell" || currentAction.type === "miracle") {
|
||||||
let label = ""
|
let label = ""
|
||||||
if ( currentAction.spellStatus === "castingTime") {
|
if (currentAction.spellStatus === "castingTime") {
|
||||||
|
let pos = $('#combat-action-dialog').position()
|
||||||
|
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", pos)
|
||||||
label = "Wait casting time"
|
label = "Wait casting time"
|
||||||
}
|
}
|
||||||
if ( currentAction.spellStatus === "toBeCasted") {
|
if (currentAction.spellStatus === "toBeCasted") {
|
||||||
|
let pos = $('#combat-action-dialog').position()
|
||||||
|
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", pos)
|
||||||
label = "Cast spell/miracle"
|
label = "Cast spell/miracle"
|
||||||
}
|
}
|
||||||
if ( currentAction.spellStatus === "lethargy") {
|
if (currentAction.spellStatus === "lethargy") {
|
||||||
|
let pos = $('#combat-action-dialog').position()
|
||||||
|
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", pos)
|
||||||
label = "Roll lethargy dice"
|
label = "Roll lethargy dice"
|
||||||
}
|
}
|
||||||
buttons.push({
|
buttons.push({
|
||||||
action: "roll",
|
action: "roll",
|
||||||
label: label,
|
label: label,
|
||||||
callback: (event, button, dialog) => {
|
callback: (event, button, dialog) => {
|
||||||
return "rollLethargyDice"
|
let pos = $('#combat-action-dialog').position()
|
||||||
},
|
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", foundry.utils.duplicate(pos))
|
||||||
})
|
return "rollLethargyDice"
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buttons.push({
|
buttons.push({
|
||||||
action: "roll",
|
action: "roll",
|
||||||
label: "Select action",
|
label: "Select action",
|
||||||
callback: (event, button, dialog) => {
|
callback: (event, button, dialog) => {
|
||||||
|
let pos = $('#combat-action-dialog').position()
|
||||||
|
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", foundry.utils.duplicate(pos))
|
||||||
const output = Array.from(button.form.elements).reduce((obj, input) => {
|
const output = Array.from(button.form.elements).reduce((obj, input) => {
|
||||||
if (input.name) obj[input.name] = input.value
|
if (input.name) obj[input.name] = input.value
|
||||||
return obj
|
return obj
|
||||||
@ -676,13 +716,17 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
action: "cancel",
|
action: "cancel",
|
||||||
label: "Other action, not listed here",
|
label: "Other action, not listed here",
|
||||||
callback: (event, button, dialog) => {
|
callback: (event, button, dialog) => {
|
||||||
|
let pos = $('#combat-action-dialog').position()
|
||||||
|
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", foundry.utils.duplicate(pos))
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let rollContext = await foundry.applications.api.DialogV2.wait({
|
let rollContext = await foundry.applications.api.DialogV2.wait({
|
||||||
window: { title: "Combat Action Dialog" },
|
window: { title: "Combat Action Dialog" },
|
||||||
|
id: "combat-action-dialog",
|
||||||
classes: ["lethalfantasy"],
|
classes: ["lethalfantasy"],
|
||||||
|
position,
|
||||||
content,
|
content,
|
||||||
buttons,
|
buttons,
|
||||||
rejectClose: false // Click on Close button will not launch an error
|
rejectClose: false // Click on Close button will not launch an error
|
||||||
@ -723,7 +767,7 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
actionItem.spellStatus = "castingTime"
|
actionItem.spellStatus = "castingTime"
|
||||||
// Set the flag on the combatant
|
// Set the flag on the combatant
|
||||||
await combatant.setFlag(SYSTEM.id, "currentAction", actionItem)
|
await combatant.setFlag(SYSTEM.id, "currentAction", actionItem)
|
||||||
let message = `${combatant.name} action : ${selectedItem.name}, start rolling progression dice`
|
let message = `${combatant.name} action : ${selectedItem.name}, start rolling progression dice or casting time`
|
||||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
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
|
currentAction = actionItem
|
||||||
@ -731,15 +775,16 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
|
|
||||||
if (currentAction) {
|
if (currentAction) {
|
||||||
if (rollContext === "rollLethargyDice") {
|
if (rollContext === "rollLethargyDice") {
|
||||||
if ( currentAction.spellStatus === "castingTime") {
|
if (currentAction.spellStatus === "castingTime") {
|
||||||
if ( currentAction.castingTime < currentAction.system.castingTime) {
|
let time = currentAction.type === "spell" ? currentAction.system.castingTime : currentAction.system.prayerTime
|
||||||
let message = `Casting time : ${currentAction.name}, count : ${currentAction.castingTime}/${currentAction.system.castingTime}`
|
if (currentAction.castingTime < time) {
|
||||||
|
let message = `Casting time : ${currentAction.name}, count : ${currentAction.castingTime}/${time}`
|
||||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
||||||
currentAction.castingTime += 1
|
currentAction.castingTime += 1
|
||||||
await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction))
|
await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction))
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
let message = `Spell ${currentAction.name} ready to be cast on next second !`
|
let message = `Spell/Miracle ${currentAction.name} ready to be cast on next second !`
|
||||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
||||||
currentAction.castingTime = 1
|
currentAction.castingTime = 1
|
||||||
currentAction.spellStatus = "toBeCasted"
|
currentAction.spellStatus = "toBeCasted"
|
||||||
@ -747,8 +792,8 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( currentAction.spellStatus === "toBeCasted") {
|
if (currentAction.spellStatus === "toBeCasted") {
|
||||||
combatant.actor.prepareRoll( (currentAction.type === "spell") ? "spell-attack" : "miracle-attack" , currentAction._id)
|
combatant.actor.prepareRoll((currentAction.type === "spell") ? "spell-attack" : "miracle-attack", currentAction._id)
|
||||||
if (currentAction.type === "spell") {
|
if (currentAction.type === "spell") {
|
||||||
currentAction.spellStatus = "lethargy"
|
currentAction.spellStatus = "lethargy"
|
||||||
await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction))
|
await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction))
|
||||||
@ -758,26 +803,29 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ( currentAction.spellStatus === "lethargy") {
|
if (currentAction.spellStatus === "lethargy") {
|
||||||
// Roll lethargy dice
|
// Roll lethargy dice
|
||||||
let dice = LethalFantasyUtils.getLethargyDice(currentAction.system.level)
|
let dice = LethalFantasyUtils.getLethargyDice(currentAction.system.level)
|
||||||
let roll = new Roll(dice)
|
let roll = new Roll(dice)
|
||||||
await roll.evaluate()
|
await roll.evaluate()
|
||||||
|
if (game?.dice3d) {
|
||||||
|
await game.dice3d.showForRoll(roll)
|
||||||
|
}
|
||||||
let max = roll.dice[0].faces - 1
|
let max = roll.dice[0].faces - 1
|
||||||
let toCompare = Math.min(options.rollProgressionCount, max)
|
let toCompare = Math.min(currentAction.progressionCount, max)
|
||||||
if (roll.total <= toCompare) {
|
if (roll.total <= toCompare) {
|
||||||
// Notify that the player can act now with a chat message
|
// Notify that the player can act now with a chat message
|
||||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageLethargyOK", { name: combatant.actor.name, weapon: currentAction.name, roll: roll.total })
|
let message = game.i18n.format("LETHALFANTASY.Notifications.messageLethargyOK", { name: combatant.actor.name, spellName: currentAction.name, roll: roll.total })
|
||||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
||||||
// Update the combatant progression count
|
// Update the combatant progression count
|
||||||
await combatant.setFlag(SYSTEM.id, "currentAction", "")
|
await combatant.setFlag(SYSTEM.id, "currentAction", "")
|
||||||
// Display the action selection window again
|
// Display the action selection window again
|
||||||
combatant.actor.system.rollProgressionDice(options.combatId, options.combatantId )
|
combatant.actor.system.rollProgressionDice(options.combatId, options.combatantId)
|
||||||
} else {
|
} else {
|
||||||
// Notify that the player cannot act now with a chat message
|
// Notify that the player cannot act now with a chat message
|
||||||
currentAction.progressionCount += 1
|
currentAction.progressionCount += 1
|
||||||
combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction))
|
await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction))
|
||||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageLethargyKO", { name: combatant.actor.name, weapon: currentAction.name, roll: roll.total })
|
let message = game.i18n.format("LETHALFANTASY.Notifications.messageLethargyKO", { name: combatant.actor.name, spellName: currentAction.name, roll: roll.total })
|
||||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -839,178 +887,7 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ***********************************************************/
|
||||||
static async promptProgressionDice(options = {}) {
|
|
||||||
|
|
||||||
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 = {
|
|
||||||
progressionDiceId: "",
|
|
||||||
fieldRollMode,
|
|
||||||
rollModes,
|
|
||||||
...options
|
|
||||||
}
|
|
||||||
|
|
||||||
const content = await renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-progression-dice-dialog.hbs", dialogContext)
|
|
||||||
|
|
||||||
const label = game.i18n.localize("LETHALFANTASY.Label.rollProgressionDice")
|
|
||||||
const rollContext = await foundry.applications.api.DialogV2.wait({
|
|
||||||
window: { title: "Progression Roll" },
|
|
||||||
classes: ["lethalfantasy"],
|
|
||||||
content,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
action: "roll",
|
|
||||||
label: "Roll Progression Dice or Continue Loading",
|
|
||||||
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
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: "cast",
|
|
||||||
label: "Cast a spell",
|
|
||||||
callback: (event, button, dialog) => {
|
|
||||||
return "casting"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: "cancel",
|
|
||||||
label: "Other action, no progression dice",
|
|
||||||
callback: (event, button, dialog) => {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
rejectClose: false // Click on Close button will not launch an error
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log("RollContext", dialogContext, rollContext)
|
|
||||||
let combat = game.combats.get(options.combatId)
|
|
||||||
let actor = game.actors.get(options.actorId)
|
|
||||||
|
|
||||||
if (rollContext === "casting") {
|
|
||||||
combat.setCasting(options.combatantId)
|
|
||||||
let message = `Starting casting a spell !`
|
|
||||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rollContext === null || !rollContext?.progressionDiceId) {
|
|
||||||
c.resetCasting(options.combatantId)
|
|
||||||
combat.resetProgression(options.combatantId)
|
|
||||||
let message = `${actor.name} : Other action, progression reset`
|
|
||||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Get the weapons from the actor items
|
|
||||||
let rangedMode
|
|
||||||
let searchId = rollContext.progressionDiceId
|
|
||||||
if (searchId.match("simpleAim")) {
|
|
||||||
searchId = searchId.replace("simpleAim", "")
|
|
||||||
rangedMode = "simpleAim"
|
|
||||||
}
|
|
||||||
if (searchId.match("carefulAim")) {
|
|
||||||
searchId = searchId.replace("carefulAim", "")
|
|
||||||
rangedMode = "carefulAim"
|
|
||||||
}
|
|
||||||
if (searchId.match("focusedAim")) {
|
|
||||||
searchId = searchId.replace("focusedAim", "")
|
|
||||||
rangedMode = "focusedAim"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchId.match("spell")) {
|
|
||||||
searchId = searchId.replace("spell", "")
|
|
||||||
let spell = actor.items.find(i => i.type === "spell" && i.id === searchId)
|
|
||||||
let dice = LethalFantasyUtils.getLethargyDice(spell.system.level)
|
|
||||||
if (combat.isCasting(options.combatantId)) {
|
|
||||||
if (options.rollProgressionCount <= spell.system.castingTime) {
|
|
||||||
let message = `Spell casting time : ${spell.name}, count : ${options.rollProgressionCount}/${spell.system.castingTime}`
|
|
||||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (options.rollProgressionCount > spell.system.castingTime) {
|
|
||||||
let message = `Spell ${spell.name} has been cast !`
|
|
||||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
|
||||||
combat.resetCasting(options.combatantId)
|
|
||||||
combat.resetProgression(options.combatantId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let formula = dice
|
|
||||||
let roll = new Roll(formula)
|
|
||||||
await roll.evaluate()
|
|
||||||
let max = roll.dice[0].faces - 1
|
|
||||||
let toCompare = Math.min(options.rollProgressionCount, max)
|
|
||||||
let message
|
|
||||||
if (roll.total > toCompare) {
|
|
||||||
message = `Spell Lethargy ongoing ... (${roll.total}/${toCompare}, spell level ${spell.system.level})`
|
|
||||||
} else {
|
|
||||||
combat.resetProgression(options.combatantId)
|
|
||||||
message = `Spell Lethargy ended ! (${roll.total}/${toCompare}, spell level ${spell.system.level})<br>${actor.name} can return to normal actions.`
|
|
||||||
}
|
|
||||||
let msg = await roll.toMessage({ flavor: message }, { rollMode: rollContext.visibility })
|
|
||||||
if (game?.dice3d) {
|
|
||||||
await game.dice3d.waitFor3DAnimationByMessageID(msg.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let weapon = actor.items.find(i => i.type === "weapon" && i.id === searchId)
|
|
||||||
let formula = weapon.system.combatProgressionDice
|
|
||||||
|
|
||||||
let rangedLoad
|
|
||||||
if (rangedMode) {
|
|
||||||
let toSplit = weapon.system.speed[rangedMode]
|
|
||||||
let split = toSplit.split("+")
|
|
||||||
rangedLoad = Number(split[0]) || 0
|
|
||||||
formula = split[1]
|
|
||||||
console.log("Ranged Mode", rangedMode, rangedLoad, formula, options.rollProgressionCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rangedLoad && options.rollProgressionCount <= rangedLoad) {
|
|
||||||
let message = `Ranged weapon ${weapon.name} is loading, loading count : ${options.rollProgressionCount}/${rangedLoad}`
|
|
||||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let isMonster = actor.type === "monster"
|
|
||||||
// Get the dice and roll it if
|
|
||||||
let roll = new Roll(formula)
|
|
||||||
await roll.evaluate()
|
|
||||||
|
|
||||||
let max = roll.dice[0].faces - 1
|
|
||||||
max = Math.min(options.rollProgressionCount, max)
|
|
||||||
let msg = await roll.toMessage({ flavor: `Progression Roll for ${weapon.name}, progression count : ${options.rollProgressionCount}/${max}` }, { rollMode: rollContext.visibility })
|
|
||||||
if (game?.dice3d) {
|
|
||||||
await game.dice3d.waitFor3DAnimationByMessageID(msg.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (roll.total <= max) {
|
|
||||||
// Notify that the player can act now with a chat message
|
|
||||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageProgressionOK", { isMonster, name: actor.name, weapon: weapon.name, roll: roll.total })
|
|
||||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
|
||||||
// Update the combatant progression count
|
|
||||||
let combat = game.combats.get(options.combatId)
|
|
||||||
let combatant = combat.combatants.get(options.combatantId)
|
|
||||||
combatant.update({ 'system.progressionCount': 0 })
|
|
||||||
} else {
|
|
||||||
// Notify that the player cannot act now with a chat message
|
|
||||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageProgressionKO", { isMonster, name: actor.name, weapon: weapon.name, roll: roll.total })
|
|
||||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async promptRangedDefense(rollTarget) {
|
static async promptRangedDefense(rollTarget) {
|
||||||
|
|
||||||
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||||
|
@ -298,8 +298,17 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod
|
|||||||
if (this.biodata.magicUser || this.biodata.clericUser) {
|
if (this.biodata.magicUser || this.biodata.clericUser) {
|
||||||
let spells = this.parent.items.filter(i => i.type === "spell" || i.type === "miracle")
|
let spells = this.parent.items.filter(i => i.type === "spell" || i.type === "miracle")
|
||||||
for (let s of spells) {
|
for (let s of spells) {
|
||||||
let dice = LethalFantasyUtils.getLethargyDice(s.system.level)
|
let title = ""
|
||||||
weaponsChoices.push({ id: s.id, name: `${s.name} (Time: ${s.system.castingTime}, Lethargy: ${dice})`, combatProgressionDice: `${s.system.castingTime}+${dice}` })
|
let formula = ""
|
||||||
|
if (s.type === "spell") {
|
||||||
|
let dice = LethalFantasyUtils.getLethargyDice(s.system.level)
|
||||||
|
title = `${s.name} (Casting time: ${s.system.castingTime}, Lethargy: ${dice})`
|
||||||
|
formula = `${s.system.castingTime}+${dice}`
|
||||||
|
} else {
|
||||||
|
title = `${s.name} (Prayer time: ${s.system.prayerTime})`
|
||||||
|
formula = `${s.system.prayerTime}`
|
||||||
|
}
|
||||||
|
weaponsChoices.push({ id: s.id, name: title, combatProgressionDice: formula })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,12 +76,16 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
|||||||
}
|
}
|
||||||
return new fields.SchemaField(schema, { label })
|
return new fields.SchemaField(schema, { label })
|
||||||
}
|
}
|
||||||
// Add 4 attackFields in an attack schema
|
// Add 4 attackFields in an attack schema
|
||||||
schema.attacks = new fields.SchemaField({
|
schema.attacks = new fields.SchemaField({
|
||||||
attack1: attackField("1"),
|
attack1: attackField("1"),
|
||||||
attack2: attackField("2"),
|
attack2: attackField("2"),
|
||||||
attack3: attackField("3"),
|
attack3: attackField("3"),
|
||||||
attack4: attackField("4"),
|
attack4: attackField("4"),
|
||||||
|
attack5: attackField("5"),
|
||||||
|
attack6: attackField("6"),
|
||||||
|
attack7: attackField("7"),
|
||||||
|
attack8: attackField("8")
|
||||||
})
|
})
|
||||||
|
|
||||||
schema.perception = new fields.SchemaField({
|
schema.perception = new fields.SchemaField({
|
||||||
@ -145,6 +149,74 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
|||||||
await roll.toMessage({}, { rollMode: roll.options.rollMode })
|
await roll.toMessage({}, { rollMode: roll.options.rollMode })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async prepareMonsterRoll(rollType, rollKey, rollDice = undefined, tokenId = undefined) {
|
||||||
|
let rollTarget
|
||||||
|
switch (rollType) {
|
||||||
|
case "monster-attack":
|
||||||
|
case "monster-defense":
|
||||||
|
case "monster-damage":
|
||||||
|
rollTarget = foundry.utils.duplicate(this.attacks[rollKey])
|
||||||
|
rollTarget.rollKey = rollKey
|
||||||
|
break
|
||||||
|
case "monster-skill":
|
||||||
|
rollTarget = foundry.utils.duplicate(this.resists[rollKey])
|
||||||
|
rollTarget.rollKey = rollKey
|
||||||
|
break
|
||||||
|
case "save":
|
||||||
|
rollTarget = foundry.utils.duplicate(this.saves[rollKey])
|
||||||
|
rollTarget.rollKey = rollKey
|
||||||
|
rollTarget.rollDice = rollDice
|
||||||
|
break
|
||||||
|
case "weapon-damage-small":
|
||||||
|
case "weapon-damage-medium":
|
||||||
|
case "weapon-attack":
|
||||||
|
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())
|
||||||
|
if (skills.length > 0) {
|
||||||
|
skill = this.getBestWeaponClassSkill(skills, rollType, 1.0)
|
||||||
|
} else {
|
||||||
|
skills = this.actor.items.filter((i) => i.type === "skill" && i.name.toLowerCase().replace(" skill", "") === weapon.name.toLowerCase())
|
||||||
|
if (skills.length > 0) {
|
||||||
|
skill = this.getBestWeaponClassSkill(skills, rollType, 1.0)
|
||||||
|
} else {
|
||||||
|
skills = this.actor.items.filter((i) => i.type === "skill" && i.system.weaponClass === weapon.system.weaponClass)
|
||||||
|
if (skills.length > 0) {
|
||||||
|
skill = this.getBestWeaponClassSkill(skills, rollType, 0.5)
|
||||||
|
} else {
|
||||||
|
skills = this.actor.items.filter((i) => i.type === "skill" && i.system.weaponClass.includes(SYSTEM.WEAPON_CATEGORIES[weapon.system.weaponClass]))
|
||||||
|
if (skills.length > 0) {
|
||||||
|
skill = this.getBestWeaponClassSkill(skills, rollType, 0.25)
|
||||||
|
} else {
|
||||||
|
ui.notifications.warn(game.i18n.localize("LETHALFANTASY.Notifications.skillNotFound"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!weapon || !skill) {
|
||||||
|
console.error("Weapon or skill not found", weapon, skill)
|
||||||
|
ui.notifications.warn(game.i18n.localize("LETHALFANTASY.Notifications.skillNotFound"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rollTarget = skill
|
||||||
|
rollTarget.weapon = weapon
|
||||||
|
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))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// In all cases
|
||||||
|
rollTarget.tokenId = tokenId
|
||||||
|
console.log(rollTarget)
|
||||||
|
await this.roll(rollType, rollTarget)
|
||||||
|
}
|
||||||
|
|
||||||
async rollInitiative(combatId = undefined, combatantId = undefined) {
|
async rollInitiative(combatId = undefined, combatantId = undefined) {
|
||||||
const hasTarget = false
|
const hasTarget = false
|
||||||
|
|
||||||
@ -164,7 +236,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
|||||||
await roll.toMessage({}, { rollMode: roll.options.rollMode })
|
await roll.toMessage({}, { rollMode: roll.options.rollMode })
|
||||||
}
|
}
|
||||||
|
|
||||||
async rollProgressionDice(combatId, combatantId, rollProgressionCount) {
|
async rollProgressionDice(combatId, combatantId) {
|
||||||
|
|
||||||
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||||
const fieldRollMode = new foundry.data.fields.StringField({
|
const fieldRollMode = new foundry.data.fields.StringField({
|
||||||
@ -175,7 +247,8 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
|||||||
|
|
||||||
let roll = new Roll("1D8")
|
let roll = new Roll("1D8")
|
||||||
await roll.evaluate()
|
await roll.evaluate()
|
||||||
let max = rollProgressionCount
|
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) {
|
if (game?.dice3d) {
|
||||||
await game.dice3d.waitFor3DAnimationByMessageID(msg.id)
|
await game.dice3d.waitFor3DAnimationByMessageID(msg.id)
|
||||||
@ -188,14 +261,19 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
|||||||
hasAttack = true
|
hasAttack = true
|
||||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageProgressionOKMonster", { isMonster: true, name: this.parent.name, weapon: attack.name, roll: roll.total })
|
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 }) })
|
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});
|
||||||
|
return canvas.animatePan(token.object.center);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!hasAttack) {
|
if (!hasAttack) {
|
||||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageProgressionKOMonster", { isMonster: true, name: this.parent.name, roll: roll.total })
|
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 }) })
|
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: this.parent }) })
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ export default class LethalFantasyShield extends foundry.abstract.TypeDataModel
|
|||||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||||
schema.defense = new fields.StringField({required: true, initial: "d4", choices: SYSTEM.SHIELD_DEFENSE_DICE})
|
schema.defense = new fields.StringField({required: true, initial: "d4", choices: SYSTEM.SHIELD_DEFENSE_DICE})
|
||||||
schema.movementreduction = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
schema.movementreduction = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||||
schema.hascover = new fields.BooleanField({ required: true, initial: false })
|
schema.hascover = new fields.BooleanField({ required: true, initial: false })
|
||||||
|
|
||||||
schema.standing = new fields.SchemaField({
|
schema.standing = new fields.SchemaField({
|
||||||
min: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
min: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||||
|
@ -9,33 +9,33 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
|
|||||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||||
schema.weaponType = new fields.StringField({ required: true, initial: "melee", choices: SYSTEM.WEAPON_TYPE })
|
schema.weaponType = new fields.StringField({ required: true, initial: "melee", choices: SYSTEM.WEAPON_TYPE })
|
||||||
schema.weaponClass = new fields.StringField({ required: true, initial: "shortblade", choices: SYSTEM.WEAPON_CLASS })
|
schema.weaponClass = new fields.StringField({ required: true, initial: "shortblade", choices: SYSTEM.WEAPON_CLASS })
|
||||||
|
|
||||||
schema.damageType = new fields.SchemaField({
|
schema.damageType = new fields.SchemaField({
|
||||||
typeP: new fields.BooleanField(),
|
typeP: new fields.BooleanField(),
|
||||||
typeB: new fields.BooleanField(),
|
typeB: new fields.BooleanField(),
|
||||||
typeS: new fields.BooleanField()
|
typeS: new fields.BooleanField()
|
||||||
})
|
})
|
||||||
schema.damage = new fields.SchemaField({
|
schema.damage = new fields.SchemaField({
|
||||||
damageS: new fields.StringField({required: true, initial: ""}),
|
damageS: new fields.StringField({required: true, initial: ""}),
|
||||||
damageM: new fields.StringField({required: true, initial: ""})
|
damageM: new fields.StringField({required: true, initial: ""})
|
||||||
})
|
})
|
||||||
schema.applyStrengthDamageBonus = new fields.BooleanField({ required: true, initial: true })
|
schema.applyStrengthDamageBonus = new fields.BooleanField({ required: true, initial: true })
|
||||||
|
|
||||||
schema.hands = new fields.StringField({ required: true, initial: "1", choices: {"1": "1", "2": "2"} })
|
schema.hands = new fields.StringField({ required: true, initial: "1", choices: {"1": "1", "2": "2"} })
|
||||||
schema.isAgile = new fields.BooleanField({ required: true, initial: false })
|
schema.isAgile = new fields.BooleanField({ required: true, initial: false })
|
||||||
|
|
||||||
schema.defenseMax = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
schema.defenseMax = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||||
schema.secondsToAttack = new fields.StringField({required: true, initial: ""})
|
schema.secondsToAttack = new fields.StringField({required: true, initial: ""})
|
||||||
schema.combatProgressionDice = new fields.StringField({required: true, initial: "d4", choices: SYSTEM.COMBAT_PROGRESSION_DICE})
|
schema.combatProgressionDice = new fields.StringField({required: true, initial: "d4", choices: SYSTEM.COMBAT_PROGRESSION_DICE})
|
||||||
|
|
||||||
schema.speed = new fields.SchemaField({
|
schema.speed = new fields.SchemaField({
|
||||||
simpleAim: new fields.StringField({required: true, initial: ""}),
|
simpleAim: new fields.StringField({required: true, initial: ""}),
|
||||||
carefulAim: new fields.StringField({required: true, initial: ""}),
|
carefulAim: new fields.StringField({required: true, initial: ""}),
|
||||||
focusedAim: new fields.StringField({required: true, initial: ""})
|
focusedAim: new fields.StringField({required: true, initial: ""})
|
||||||
})
|
})
|
||||||
|
|
||||||
schema.defense = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
schema.defense = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||||
schema.weaponRange = new fields.SchemaField({
|
schema.weaponRange = new fields.SchemaField({
|
||||||
pointBlank: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
pointBlank: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||||
short: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
short: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||||
medium: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
medium: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||||
@ -44,7 +44,7 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
|
|||||||
outOfSkill: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
outOfSkill: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||||
})
|
})
|
||||||
|
|
||||||
schema.bonuses = new fields.SchemaField({
|
schema.bonuses = new fields.SchemaField({
|
||||||
attackBonus: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
attackBonus: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||||
damageBonus: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
damageBonus: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||||
defenseBonus: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
defenseBonus: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||||
|
@ -18,6 +18,51 @@ export default class LethalFantasyUtils {
|
|||||||
options.push({ name: "Reset Progression", condition: true, icon: '<i class="fas fa-rotate-right"></i>', callback: target => { game.combat.resetProgression(target.data('combatant-id')); } })
|
options.push({ name: "Reset Progression", condition: true, icon: '<i class="fas fa-rotate-right"></i>', callback: target => { game.combat.resetProgression(target.data('combatant-id')); } })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
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) => {
|
||||||
|
event.preventDefault();
|
||||||
|
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');
|
||||||
|
} 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('.loss-hp-hud-click').click((event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
let hpLoss = event.currentTarget.dataset.hpValue;
|
||||||
|
if (token) {
|
||||||
|
let tokenFull = canvas.tokens.placeables.find( t => t.id === token._id);
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
static handleSocketEvent(msg = {}) {
|
static handleSocketEvent(msg = {}) {
|
||||||
console.log(`handleSocketEvent !`, msg)
|
console.log(`handleSocketEvent !`, msg)
|
||||||
let actor
|
let actor
|
||||||
|
Binary file not shown.
BIN
packs-system/lf-equipment/000302.ldb
Normal file
BIN
packs-system/lf-equipment/000302.ldb
Normal file
Binary file not shown.
@ -1 +1 @@
|
|||||||
MANIFEST-000219
|
MANIFEST-000303
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
2025/04/21-17:09:30.765172 7f5dceffd6c0 Recovering log #217
|
2025/05/06-10:52:19.288970 7fc4e7fff6c0 Recovering log #300
|
||||||
2025/04/21-17:09:30.774995 7f5dceffd6c0 Delete type=3 #215
|
2025/05/06-10:52:19.300271 7fc4e7fff6c0 Delete type=3 #298
|
||||||
2025/04/21-17:09:30.775106 7f5dceffd6c0 Delete type=0 #217
|
2025/05/06-10:52:19.300323 7fc4e7fff6c0 Delete type=0 #300
|
||||||
2025/04/21-17:40:19.481504 7f5dcd3ff6c0 Level-0 table #222: started
|
2025/05/06-10:53:10.017977 7fc4e73ff6c0 Level-0 table #306: started
|
||||||
2025/04/21-17:40:19.481549 7f5dcd3ff6c0 Level-0 table #222: 0 bytes OK
|
2025/05/06-10:53:10.018020 7fc4e73ff6c0 Level-0 table #306: 0 bytes OK
|
||||||
2025/04/21-17:40:19.518709 7f5dcd3ff6c0 Delete type=0 #220
|
2025/05/06-10:53:10.024080 7fc4e73ff6c0 Delete type=0 #304
|
||||||
2025/04/21-17:40:19.572101 7f5dcd3ff6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!znm6T1ef4qQI8BX7' @ 0 : 0; will stop at (end)
|
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/04/21-17:40:19.634424 7f5dcd3ff6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!znm6T1ef4qQI8BX7' @ 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)
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
2025/04/17-17:21:12.564483 7f5c837fe6c0 Recovering log #213
|
2025/05/06-10:45:53.342160 7fc4ecbf86c0 Recovering log #296
|
||||||
2025/04/17-17:21:12.575284 7f5c837fe6c0 Delete type=3 #211
|
2025/05/06-10:45:53.353010 7fc4ecbf86c0 Delete type=3 #294
|
||||||
2025/04/17-17:21:12.575342 7f5c837fe6c0 Delete type=0 #213
|
2025/05/06-10:45:53.353081 7fc4ecbf86c0 Delete type=0 #296
|
||||||
2025/04/17-17:34:42.493086 7f5c81bff6c0 Level-0 table #218: started
|
2025/05/06-10:51:12.708848 7fc4e73ff6c0 Level-0 table #301: started
|
||||||
2025/04/17-17:34:42.493111 7f5c81bff6c0 Level-0 table #218: 0 bytes OK
|
2025/05/06-10:51:12.714248 7fc4e73ff6c0 Level-0 table #301: 213746 bytes OK
|
||||||
2025/04/17-17:34:42.499036 7f5c81bff6c0 Delete type=0 #216
|
2025/05/06-10:51:12.720525 7fc4e73ff6c0 Delete type=0 #299
|
||||||
2025/04/17-17:34:42.518959 7f5c81bff6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!znm6T1ef4qQI8BX7' @ 0 : 0; will stop at (end)
|
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/04/17-17:34:42.519032 7f5c81bff6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!znm6T1ef4qQI8BX7' @ 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)
|
||||||
|
Binary file not shown.
BIN
packs-system/lf-equipment/MANIFEST-000303
Normal file
BIN
packs-system/lf-equipment/MANIFEST-000303
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs-system/lf-gifts/000301.ldb
Normal file
BIN
packs-system/lf-gifts/000301.ldb
Normal file
Binary file not shown.
@ -1 +1 @@
|
|||||||
MANIFEST-000218
|
MANIFEST-000302
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
2025/04/21-17:09:30.778463 7f5dcdffb6c0 Recovering log #216
|
2025/05/06-10:52:19.304583 7fc4ed3f96c0 Recovering log #299
|
||||||
2025/04/21-17:09:30.789411 7f5dcdffb6c0 Delete type=3 #214
|
2025/05/06-10:52:19.314806 7fc4ed3f96c0 Delete type=3 #297
|
||||||
2025/04/21-17:09:30.789468 7f5dcdffb6c0 Delete type=0 #216
|
2025/05/06-10:52:19.314910 7fc4ed3f96c0 Delete type=0 #299
|
||||||
2025/04/21-17:40:19.406720 7f5dcd3ff6c0 Level-0 table #221: started
|
2025/05/06-10:53:10.030599 7fc4e73ff6c0 Level-0 table #305: started
|
||||||
2025/04/21-17:40:19.406774 7f5dcd3ff6c0 Level-0 table #221: 0 bytes OK
|
2025/05/06-10:53:10.030635 7fc4e73ff6c0 Level-0 table #305: 0 bytes OK
|
||||||
2025/04/21-17:40:19.446347 7f5dcd3ff6c0 Delete type=0 #219
|
2025/05/06-10:53:10.036964 7fc4e73ff6c0 Delete type=0 #303
|
||||||
2025/04/21-17:40:19.572073 7f5dcd3ff6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
|
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/04/21-17:40:19.572119 7f5dcd3ff6c0 Manual compaction at level-1 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)
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
2025/04/17-17:21:12.578876 7f5c82ffd6c0 Recovering log #212
|
2025/05/06-10:45:53.355849 7fc4edbfa6c0 Recovering log #295
|
||||||
2025/04/17-17:21:12.589060 7f5c82ffd6c0 Delete type=3 #210
|
2025/05/06-10:45:53.366571 7fc4edbfa6c0 Delete type=3 #293
|
||||||
2025/04/17-17:21:12.589120 7f5c82ffd6c0 Delete type=0 #212
|
2025/05/06-10:45:53.366637 7fc4edbfa6c0 Delete type=0 #295
|
||||||
2025/04/17-17:34:42.486913 7f5c81bff6c0 Level-0 table #217: started
|
2025/05/06-10:51:12.732133 7fc4e73ff6c0 Level-0 table #300: started
|
||||||
2025/04/17-17:34:42.486964 7f5c81bff6c0 Level-0 table #217: 0 bytes OK
|
2025/05/06-10:51:12.736129 7fc4e73ff6c0 Level-0 table #300: 15304 bytes OK
|
||||||
2025/04/17-17:34:42.492952 7f5c81bff6c0 Delete type=0 #215
|
2025/05/06-10:51:12.742079 7fc4e73ff6c0 Delete type=0 #298
|
||||||
2025/04/17-17:34:42.518936 7f5c81bff6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
|
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/04/17-17:34:42.519016 7f5c81bff6c0 Manual compaction at level-1 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)
|
||||||
|
Binary file not shown.
BIN
packs-system/lf-gifts/MANIFEST-000302
Normal file
BIN
packs-system/lf-gifts/MANIFEST-000302
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs-system/lf-skills/000301.ldb
Normal file
BIN
packs-system/lf-skills/000301.ldb
Normal file
Binary file not shown.
@ -1 +1 @@
|
|||||||
MANIFEST-000218
|
MANIFEST-000302
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
2025/04/21-17:09:30.749204 7f5dce7fc6c0 Recovering log #216
|
2025/05/06-10:52:19.275594 7fc4ecbf86c0 Recovering log #299
|
||||||
2025/04/21-17:09:30.759893 7f5dce7fc6c0 Delete type=3 #214
|
2025/05/06-10:52:19.285984 7fc4ecbf86c0 Delete type=3 #297
|
||||||
2025/04/21-17:09:30.760044 7f5dce7fc6c0 Delete type=0 #216
|
2025/05/06-10:52:19.286069 7fc4ecbf86c0 Delete type=0 #299
|
||||||
2025/04/21-17:40:19.292988 7f5dcd3ff6c0 Level-0 table #221: started
|
2025/05/06-10:53:10.024277 7fc4e73ff6c0 Level-0 table #305: started
|
||||||
2025/04/21-17:40:19.293026 7f5dcd3ff6c0 Level-0 table #221: 0 bytes OK
|
2025/05/06-10:53:10.024336 7fc4e73ff6c0 Level-0 table #305: 0 bytes OK
|
||||||
2025/04/21-17:40:19.329102 7f5dcd3ff6c0 Delete type=0 #219
|
2025/05/06-10:53:10.030435 7fc4e73ff6c0 Delete type=0 #303
|
||||||
2025/04/21-17:40:19.406586 7f5dcd3ff6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
|
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/04/21-17:40:19.406620 7f5dcd3ff6c0 Manual compaction at level-1 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)
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
2025/04/17-17:21:12.549824 7f5c827fc6c0 Recovering log #212
|
2025/05/06-10:45:53.317135 7fc4e7fff6c0 Recovering log #295
|
||||||
2025/04/17-17:21:12.560061 7f5c827fc6c0 Delete type=3 #210
|
2025/05/06-10:45:53.339293 7fc4e7fff6c0 Delete type=3 #293
|
||||||
2025/04/17-17:21:12.560203 7f5c827fc6c0 Delete type=0 #212
|
2025/05/06-10:45:53.339350 7fc4e7fff6c0 Delete type=0 #295
|
||||||
2025/04/17-17:34:42.505447 7f5c81bff6c0 Level-0 table #217: started
|
2025/05/06-10:51:12.783010 7fc4e73ff6c0 Level-0 table #300: started
|
||||||
2025/04/17-17:34:42.505471 7f5c81bff6c0 Level-0 table #217: 0 bytes OK
|
2025/05/06-10:51:12.787977 7fc4e73ff6c0 Level-0 table #300: 154604 bytes OK
|
||||||
2025/04/17-17:34:42.518767 7f5c81bff6c0 Delete type=0 #215
|
2025/05/06-10:51:12.794741 7fc4e73ff6c0 Delete type=0 #298
|
||||||
2025/04/17-17:34:42.518998 7f5c81bff6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
|
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/04/17-17:34:42.519066 7f5c81bff6c0 Manual compaction at level-1 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)
|
||||||
|
Binary file not shown.
BIN
packs-system/lf-skills/MANIFEST-000302
Normal file
BIN
packs-system/lf-skills/MANIFEST-000302
Normal file
Binary file not shown.
BIN
packs-system/lf-spells-miracles/000005.ldb
Normal file
BIN
packs-system/lf-spells-miracles/000005.ldb
Normal file
Binary file not shown.
1
packs-system/lf-spells-miracles/CURRENT
Normal file
1
packs-system/lf-spells-miracles/CURRENT
Normal file
@ -0,0 +1 @@
|
|||||||
|
MANIFEST-000002
|
0
packs-system/lf-spells-miracles/LOCK
Normal file
0
packs-system/lf-spells-miracles/LOCK
Normal file
5
packs-system/lf-spells-miracles/LOG
Normal file
5
packs-system/lf-spells-miracles/LOG
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
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)
|
BIN
packs-system/lf-spells-miracles/MANIFEST-000002
Normal file
BIN
packs-system/lf-spells-miracles/MANIFEST-000002
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs-system/lf-vulnerabilities/000301.ldb
Normal file
BIN
packs-system/lf-vulnerabilities/000301.ldb
Normal file
Binary file not shown.
0
packs-system/lf-vulnerabilities/000304.log
Normal file
0
packs-system/lf-vulnerabilities/000304.log
Normal file
@ -1 +1 @@
|
|||||||
MANIFEST-000218
|
MANIFEST-000302
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
2025/04/21-17:09:30.792733 7f5dcf7fe6c0 Recovering log #216
|
2025/05/06-10:52:19.317853 7fc4edbfa6c0 Recovering log #299
|
||||||
2025/04/21-17:09:30.802787 7f5dcf7fe6c0 Delete type=3 #214
|
2025/05/06-10:52:19.327788 7fc4edbfa6c0 Delete type=3 #297
|
||||||
2025/04/21-17:09:30.802873 7f5dcf7fe6c0 Delete type=0 #216
|
2025/05/06-10:52:19.327923 7fc4edbfa6c0 Delete type=0 #299
|
||||||
2025/04/21-17:40:19.329256 7f5dcd3ff6c0 Level-0 table #221: started
|
2025/05/06-10:53:10.037095 7fc4e73ff6c0 Level-0 table #305: started
|
||||||
2025/04/21-17:40:19.329290 7f5dcd3ff6c0 Level-0 table #221: 0 bytes OK
|
2025/05/06-10:53:10.037121 7fc4e73ff6c0 Level-0 table #305: 0 bytes OK
|
||||||
2025/04/21-17:40:19.360850 7f5dcd3ff6c0 Delete type=0 #219
|
2025/05/06-10:53:10.044101 7fc4e73ff6c0 Delete type=0 #303
|
||||||
2025/04/21-17:40:19.406600 7f5dcd3ff6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
|
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/04/21-17:40:19.406634 7f5dcd3ff6c0 Manual compaction at level-1 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)
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
2025/04/17-17:21:12.592168 7f5c83fff6c0 Recovering log #212
|
2025/05/06-10:45:53.369722 7fc4ed3f96c0 Recovering log #295
|
||||||
2025/04/17-17:21:12.602692 7f5c83fff6c0 Delete type=3 #210
|
2025/05/06-10:45:53.379868 7fc4ed3f96c0 Delete type=3 #293
|
||||||
2025/04/17-17:21:12.602743 7f5c83fff6c0 Delete type=0 #212
|
2025/05/06-10:45:53.379989 7fc4ed3f96c0 Delete type=0 #295
|
||||||
2025/04/17-17:34:42.499156 7f5c81bff6c0 Level-0 table #217: started
|
2025/05/06-10:51:12.720972 7fc4e73ff6c0 Level-0 table #300: started
|
||||||
2025/04/17-17:34:42.499188 7f5c81bff6c0 Level-0 table #217: 0 bytes OK
|
2025/05/06-10:51:12.724909 7fc4e73ff6c0 Level-0 table #300: 20719 bytes OK
|
||||||
2025/04/17-17:34:42.505329 7f5c81bff6c0 Delete type=0 #215
|
2025/05/06-10:51:12.731912 7fc4e73ff6c0 Delete type=0 #298
|
||||||
2025/04/17-17:34:42.518977 7f5c81bff6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
|
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/04/17-17:34:42.519047 7f5c81bff6c0 Manual compaction at level-1 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)
|
||||||
|
Binary file not shown.
BIN
packs-system/lf-vulnerabilities/MANIFEST-000302
Normal file
BIN
packs-system/lf-vulnerabilities/MANIFEST-000302
Normal file
Binary file not shown.
@ -1,21 +0,0 @@
|
|||||||
#lethalfantasy-application-manager {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
font-family: var(--font-primary);
|
|
||||||
font-size: calc(var(--font-size-standard) * 1);
|
|
||||||
color: var(--color-dark-1);
|
|
||||||
background-image: var(--background-image-base);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
|
|
||||||
.lethalfantasy-table {
|
|
||||||
margin: 1rem;
|
|
||||||
background: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
text-align: center;
|
|
||||||
.player {
|
|
||||||
font-size: calc(var(--font-size-standard) * 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -10,7 +10,7 @@
|
|||||||
@import "weapon.less";
|
@import "weapon.less";
|
||||||
@import "armor.less";
|
@import "armor.less";
|
||||||
@import "spell.less";
|
@import "spell.less";
|
||||||
@import "vulnerability.less";
|
@import "vulnerability.less";
|
||||||
@import "chat.less";
|
@import "chat.less";
|
||||||
@import "equipment.less";
|
@import "equipment.less";
|
||||||
@import "shield.less";
|
@import "shield.less";
|
||||||
@ -18,4 +18,4 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@import "roll.less";
|
@import "roll.less";
|
||||||
@import "application-manager.less";
|
@import "hud.less";
|
||||||
|
43
styles/hud.less
Normal file
43
styles/hud.less
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#token-hud .hp-loss-wrap {
|
||||||
|
position: absolute;
|
||||||
|
left: 75px;
|
||||||
|
display: none;
|
||||||
|
top: 50%;
|
||||||
|
width: 48px;
|
||||||
|
text-align: start;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#token-hud .hp-loss-wrap-col1 {
|
||||||
|
transform: translate(-200%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#token-hud .hp-loss-wrap-col2 {
|
||||||
|
transform: translate(-300%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#token-hud .hp-loss-wrap-col3 {
|
||||||
|
transform: translate(-400%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#token-hud .hp-loss-hud-active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#token-hud .hp-loss-hud-disabled {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#token-hud .hud-loss-hp-button-select {
|
||||||
|
max-width: 40px;
|
||||||
|
background-image: var(--background-image-base);
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
width: max-content;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#token-hud .hp-loss-wrap .hud-loss-hp-button-select {
|
||||||
|
padding-left: 8px;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
}
|
@ -13,6 +13,19 @@
|
|||||||
fieldset {
|
fieldset {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
|
.goto-token-button {
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
max-width: 8rem;
|
||||||
|
background-color: var(--color-dark-6);
|
||||||
|
color: var(--color-dark-2);
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.lethalfantasy-range-defense-dialog {
|
.lethalfantasy-range-defense-dialog {
|
||||||
@ -24,7 +37,7 @@
|
|||||||
select {
|
select {
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
max-width: 10rem;
|
max-width: 10rem;
|
||||||
}
|
}
|
||||||
.field-section {
|
.field-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -34,13 +47,13 @@
|
|||||||
.field-name {
|
.field-name {
|
||||||
width:4rem;
|
width:4rem;
|
||||||
min-width: 4rem;
|
min-width: 4rem;
|
||||||
max-width: 4rem;
|
max-width: 4rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.dialog-form {
|
.dialog-form {
|
||||||
.form-footer {
|
.form-footer {
|
||||||
button {
|
button {
|
||||||
min-width: 14rem;
|
min-width: 14rem;
|
||||||
min-height: 3.2rem;
|
min-height: 3.2rem;
|
||||||
|
@ -82,6 +82,14 @@
|
|||||||
"system": "fvtt-lethal-fantasy",
|
"system": "fvtt-lethal-fantasy",
|
||||||
"path": "packs-system/lf-vulnerabilities",
|
"path": "packs-system/lf-vulnerabilities",
|
||||||
"type": "Item"
|
"type": "Item"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lf-spells-miracles",
|
||||||
|
"banner": "",
|
||||||
|
"label": "Spells & Miracles",
|
||||||
|
"system": "fvtt-lethal-fantasy",
|
||||||
|
"path": "packs-system/lf-spells-miracles",
|
||||||
|
"type": "Item"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"flags": {
|
"flags": {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<div class="lethalfantasy-combat-action-dialog">
|
<div class="lethalfantasy-combat-action-dialog">
|
||||||
|
|
||||||
<fieldSet class="">
|
<fieldSet class="">
|
||||||
<legend>{{localize "LETHALFANTASY.Label.combatAction"}}</legend>
|
<legend>{{localize "LETHALFANTASY.Label.combatAction"}} for {{actorName}}</legend>
|
||||||
|
|
||||||
{{#if currentAction}}
|
{{#if currentAction}}
|
||||||
<label>{{localize "LETHALFANTASY.Label.currentAction"}} : {{currentAction.name}}</label>
|
<label>{{localize "LETHALFANTASY.Label.currentAction"}} : {{currentAction.name}}</label>
|
||||||
|
29
templates/loss-hp-hud.hbs
Normal file
29
templates/loss-hp-hud.hbs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<div class="control-icon" data-action="lethal-loss-hp-hud">
|
||||||
|
<img class="lethal-hp-loss-hud" src="systems/fvtt-lethal-fantasy/assets/icons/broken-heart.svg"
|
||||||
|
width="36" height="36" title="Open token journal" />
|
||||||
|
|
||||||
|
<div class="hp-loss-wrap hp-loss-wrap-col1 hp-loss-hud-disabled">
|
||||||
|
{{#for -10 0 1}}
|
||||||
|
<button class="hud-loss-hp-button-select loss-hp-hud-click " data-hp-value="{{this}}" >
|
||||||
|
<span class="">{{this}}</span>
|
||||||
|
</button>
|
||||||
|
{{/for}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hp-loss-wrap hp-loss-wrap-col2 hp-loss-hud-disabled">
|
||||||
|
{{#for -20 -10 1}}
|
||||||
|
<button class="hud-loss-hp-button-select loss-hp-hud-click " data-hp-value="{{this}}" >
|
||||||
|
<span class="">{{this}}</span>
|
||||||
|
</button>
|
||||||
|
{{/for}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hp-loss-wrap hp-loss-wrap-col3 hp-loss-hud-disabled">
|
||||||
|
{{#for -30 -20 1}}
|
||||||
|
<button class="hud-loss-hp-button-select loss-hp-hud-click " data-hp-value="{{this}}" >
|
||||||
|
<span class="">{{this}}</span>
|
||||||
|
</button>
|
||||||
|
{{/for}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
@ -1,13 +1,19 @@
|
|||||||
<div class="lethalfantasy-roll-dialog">
|
<div class="lethalfantasy-roll-dialog">
|
||||||
|
|
||||||
<fieldSet class="">
|
<fieldSet class="">
|
||||||
<legend>{{localize (concat "LETHALFANTASY.Label." rollType)}}</legend>
|
<legend>{{localize (concat "LETHALFANTASY.Label." rollType)}} - {{actorName}}</legend>
|
||||||
|
|
||||||
|
{{#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>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if (match rollType "attack")}}
|
{{#if (match rollType "attack")}}
|
||||||
<div class="dialog-save">Attack roll !</div>
|
<div class="dialog-save">Attack roll ! - {{rollTarget.name}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (match rollType "defense")}}
|
{{#if (match rollType "defense")}}
|
||||||
<div class="dialog-save">Defense roll !</div>
|
<div class="dialog-save">Defense roll ! - {{rollTarget.name}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if hasModifier}}
|
{{#if hasModifier}}
|
||||||
@ -19,7 +25,7 @@
|
|||||||
<div class="dialog-save">{{localize "LETHALFANTASY.Label.baseModifier"}} : {{rollTarget.charModifier}}</div>
|
<div class="dialog-save">{{localize "LETHALFANTASY.Label.baseModifier"}} : {{rollTarget.charModifier}}</div>
|
||||||
<div class="dialog-save">{{localize "LETHALFANTASY.Label.weapon"}} : {{rollTarget.weapon.name}}</div>
|
<div class="dialog-save">{{localize "LETHALFANTASY.Label.weapon"}} : {{rollTarget.weapon.name}}</div>
|
||||||
<div class="dialog-save">{{localize "LETHALFANTASY.Label.skill"}} : {{rollTarget.name}}</div>
|
<div class="dialog-save">{{localize "LETHALFANTASY.Label.skill"}} : {{rollTarget.name}}</div>
|
||||||
<div class="dialog-save">{{localize "LETHALFANTASY.Label.skillBonus"}} : {{rollTarget.weaponSkillModifier}}</div>
|
<div class="dialog-save">{{localize "LETHALFANTASY.Label.skillBonus"}} : {{rollTarget.weaponSkillModifier}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if (match rollType "attack")}}
|
{{#if (match rollType "attack")}}
|
||||||
@ -29,16 +35,16 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (match rollType "defense")}}
|
{{#if (match rollType "defense")}}
|
||||||
<div class="dialog-save">Add Granted Defense Dice
|
<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>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (match rollType "damage")}}
|
{{#if (match rollType "damage")}}
|
||||||
<div class="dialog-save">Add Granted Damage Dice
|
<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>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if rollTarget.staticModifier}}
|
{{#if rollTarget.staticModifier}}
|
||||||
<div class="dialog-save">Static modifier : +{{rollTarget.staticModifier}}</div>
|
<div class="dialog-save">Static modifier : +{{rollTarget.staticModifier}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
@ -87,4 +93,6 @@
|
|||||||
{{selectOptions rollModes selected=visibility}}
|
{{selectOptions rollModes selected=visibility}}
|
||||||
</select>
|
</select>
|
||||||
</fieldSet>
|
</fieldSet>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
Reference in New Issue
Block a user