Various items fixes and enhancements
This commit is contained in:
@ -9,4 +9,6 @@ export { default as LethalFantasyArmorSheet } from "./sheets/armor-sheet.mjs"
|
||||
export { default as LethalFantasySpellSheet } from "./sheets/spell-sheet.mjs"
|
||||
export { default as LethalFantasyEquipmentSheet } from "./sheets/equipment-sheet.mjs"
|
||||
export { default as LethalFantasyShieldSheet } from "./sheets/shield-sheet.mjs"
|
||||
export { default as LethalFantasyMiracleSheet } from "./sheets/miracle-sheet.mjs"
|
||||
export { default as LethalFantasyManager } from "./manager.mjs"
|
||||
|
||||
|
@ -23,10 +23,16 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
|
||||
template: "systems/fvtt-lethal-fantasy/templates/character-main.hbs",
|
||||
},
|
||||
tabs: {
|
||||
template: "systems/fvtt-lethal-fantasy/templates/generic/tab-navigation.hbs",
|
||||
template: "templates/generic/tab-navigation.hbs",
|
||||
},
|
||||
items: {
|
||||
template: "systems/fvtt-lethal-fantasy/templates/character-items.hbs",
|
||||
skills: {
|
||||
template: "systems/fvtt-lethal-fantasy/templates/character-skills.hbs",
|
||||
},
|
||||
weapons: {
|
||||
template: "systems/fvtt-lethal-fantasy/templates/character-weapons.hbs",
|
||||
},
|
||||
spells: {
|
||||
template: "systems/fvtt-lethal-fantasy/templates/character-spells.hbs",
|
||||
},
|
||||
biography: {
|
||||
template: "systems/fvtt-lethal-fantasy/templates/character-biography.hbs",
|
||||
@ -35,7 +41,7 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
sheet: "items",
|
||||
sheet: "skills",
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,8 +50,10 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
|
||||
*/
|
||||
#getTabs() {
|
||||
const tabs = {
|
||||
items: { id: "items", group: "sheet", icon: "fa-solid fa-shapes", label: "LETHALFANTASY.Character.Label.details" },
|
||||
biography: { id: "biography", group: "sheet", icon: "fa-solid fa-book", label: "LETHALFANTASY.Character.Label.biography" },
|
||||
skills: { id: "skills", group: "sheet", icon: "fa-solid fa-shapes", label: "LETHALFANTASY.Label.skills" },
|
||||
weapons: { id: "weapons", group: "sheet", icon: "fa-solid fa-swords", label: "LETHALFANTASY.Label.weapons" },
|
||||
spells: { id: "spells", group: "sheet", icon: "fa-sharp-duotone fa-solid fa-wand-magic-sparkles", label: "LETHALFANTASY.Label.spells" },
|
||||
biography: { id: "biography", group: "sheet", icon: "fa-solid fa-book", label: "LETHALFANTASY.Label.biography" },
|
||||
}
|
||||
for (const v of Object.values(tabs)) {
|
||||
v.active = this.tabGroups[v.group] === v.id
|
||||
@ -78,15 +86,24 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
|
||||
const doc = this.document
|
||||
switch (partId) {
|
||||
case "main":
|
||||
context.enrichedBiens = await TextEditor.enrichHTML(doc.system.biens, { async: true })
|
||||
break
|
||||
case "items":
|
||||
context.tab = context.tabs.items
|
||||
context.weapons = doc.itemTypes.weapon
|
||||
context.armors = doc.itemTypes.armor
|
||||
case "skills":
|
||||
context.tab = context.tabs.skills
|
||||
context.skills = doc.itemTypes.skill
|
||||
context.gifts = doc.itemTypes.gifts
|
||||
context.vulnerabilities = doc.itemTypes.vulnerability
|
||||
break
|
||||
case "spells":
|
||||
context.tab = context.tabs.spells
|
||||
context.spells = doc.itemTypes.spell
|
||||
context.hasSpells = context.spells.length > 0
|
||||
break
|
||||
case "weapons":
|
||||
context.tab = context.tabs.weapons
|
||||
context.weapons = doc.itemTypes.weapon
|
||||
context.armors = doc.itemTypes.armor
|
||||
context.equipments = doc.itemTypes.equipment
|
||||
break
|
||||
case "biography":
|
||||
context.tab = context.tabs.biography
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
|
||||
@ -111,11 +128,7 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
|
||||
switch (data.type) {
|
||||
case "Item":
|
||||
const item = await fromUuid(data.uuid)
|
||||
if (!["path", "weapon", "armor", "spell"].includes(item.type)) return
|
||||
if (item.type === "path") return this.#onDropPathItem(item)
|
||||
if (item.type === "weapon") return super._onDropItem(item)
|
||||
if (item.type === "armor") return this._onDropItem(item)
|
||||
if (item.type === "spell") return this._onDropItem(item)
|
||||
return this._onDropItem(item)
|
||||
}
|
||||
}
|
||||
|
||||
|
21
module/applications/sheets/miracle-sheet.mjs
Normal file
21
module/applications/sheets/miracle-sheet.mjs
Normal file
@ -0,0 +1,21 @@
|
||||
import LethalFantasyItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class LethalFantasyMiracleSheet extends LethalFantasyItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["miracle"],
|
||||
position: {
|
||||
width: 450,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["miracle-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-lethal-fantasy/templates/miracle.hbs",
|
||||
},
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
export const CHARACTERISTICS = Object.freeze({
|
||||
str: {
|
||||
id: "str",
|
||||
label: "LETHALFANTASY.Character.str.label"
|
||||
label: "LETHALFANTASY.Label.str"
|
||||
},
|
||||
int: {
|
||||
id: "int",
|
||||
@ -23,6 +23,10 @@ export const CHARACTERISTICS = Object.freeze({
|
||||
id: "cha",
|
||||
label: "LETHALFANTASY.Character.cha.label"
|
||||
},
|
||||
luc: {
|
||||
id: "luc",
|
||||
label: "LETHALFANTASY.Character.luc.label"
|
||||
},
|
||||
app: {
|
||||
id: "app",
|
||||
label: "LETHALFANTASY.Character.app.label"
|
||||
|
1293
module/config/characteristic-tables.mjs
Normal file
1293
module/config/characteristic-tables.mjs
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,20 +4,11 @@ import * as ARMOR from "./armor.mjs"
|
||||
import * as SPELL from "./spell.mjs"
|
||||
import * as SKILL from "./skill.mjs"
|
||||
import * as EQUIPMENT from "./equipment.mjs"
|
||||
import * as CHARACTERISTICS from "./characteristic-tables.mjs"
|
||||
|
||||
export const SYSTEM_ID = "fvtt-lethal-fantasy"
|
||||
export const DEV_MODE = false
|
||||
|
||||
export const DICE_VALUE = Object.freeze({
|
||||
D4: "d4",
|
||||
D6: "d6",
|
||||
D8: "d8",
|
||||
D10: "d10",
|
||||
D12: "d12",
|
||||
})
|
||||
|
||||
export const DICE_VALUES = ["0", "d4", "d6", "d8", "d10", "d12"]
|
||||
|
||||
export const ROLL_TYPE = Object.freeze({
|
||||
SAVE: "save",
|
||||
RESOURCE: "resource",
|
||||
@ -77,15 +68,15 @@ export const ASCII = `
|
||||
export const SYSTEM = {
|
||||
id: SYSTEM_ID,
|
||||
CHARACTERISTICS: CHARACTER.CHARACTERISTICS,
|
||||
RESOURCES: CHARACTER.RESOURCES,
|
||||
CHARACTERISTICS_TABLES: CHARACTERISTICS.TABLES,
|
||||
CHARACTERISTICS_MAJOR: CHARACTERISTICS.MAJOR,
|
||||
SAVES: CHARACTER.SAVES,
|
||||
SKILL_CATEGORY: SKILL.CATEGORY,
|
||||
WEAPON_CATEGORY: WEAPON.CATEGORY,
|
||||
WEAPON_DAMAGE: WEAPON.DAMAGE,
|
||||
ARMOR_TYPE: ARMOR.TYPE,
|
||||
EQUIPMENT_CATEGORY: EQUIPMENT.CATEGORY,
|
||||
SPELL_RANGE: SPELL.RANGE,
|
||||
WEAPON_TYPE: WEAPON.WEAPON_TYPE,
|
||||
WEAPON_CLASS: WEAPON.WEAPON_CLASS,
|
||||
MONEY,
|
||||
ASCII,
|
||||
ROLL_TYPE,
|
||||
|
@ -1,35 +1,20 @@
|
||||
export const CATEGORY = Object.freeze({
|
||||
mains: {
|
||||
id: "mains",
|
||||
label: "LETHALFANTASY.Weapon.Category.main",
|
||||
},
|
||||
improvisee: {
|
||||
id: "improvisee",
|
||||
label: "LETHALFANTASY.Weapon.Category.improvisee",
|
||||
},
|
||||
courte: {
|
||||
id: "courte",
|
||||
label: "LETHALFANTASY.Weapon.Category.courte",
|
||||
},
|
||||
longue: {
|
||||
id: "longue",
|
||||
label: "LETHALFANTASY.Weapon.Category.longue",
|
||||
},
|
||||
lourde: {
|
||||
id: "lourde",
|
||||
label: "LETHALFANTASY.Weapon.Category.lourde",
|
||||
},
|
||||
})
|
||||
|
||||
export const WEAPON_TYPE = {
|
||||
"melee": "LETHALFANTASY.Weapon.WeaponType.melee",
|
||||
"ranged": "LETHALFANTASY.Weapon.WeaponType.ranged"
|
||||
}
|
||||
|
||||
export const DAMAGE = Object.freeze({
|
||||
UN: "1",
|
||||
D4: "d4",
|
||||
D6: "d6",
|
||||
D8: "d8",
|
||||
D10: "d10",
|
||||
})
|
||||
export const WEAPON_CLASS = {
|
||||
"longblade": "LETHALFANTASY.Weapon.WeaponClass.longblade",
|
||||
"shortblade": "LETHALFANTASY.Weapon.WeaponClass.shortblade",
|
||||
"mediumblade": "LETHALFANTASY.Weapon.WeaponClass.mediumblade",
|
||||
"axe": "LETHALFANTASY.Weapon.WeaponClass.axe",
|
||||
"hammer": "LETHALFANTASY.Weapon.WeaponClass.hammer",
|
||||
"mace": "LETHALFANTASY.Weapon.WeaponClass.mace",
|
||||
"flail": "LETHALFANTASY.Weapon.WeaponClass.flail",
|
||||
"bow": "LETHALFANTASY.Weapon.WeaponClass.bow",
|
||||
"sling": "LETHALFANTASY.Weapon.WeaponClass.sling",
|
||||
"thrown": "LETHALFANTASY.Weapon.WeaponClass.thrown",
|
||||
"polearm": "LETHALFANTASY.Weapon.WeaponClass.polearm",
|
||||
"unarmed" : "LETHALFANTASY.Weapon.WeaponClass.unarmed"
|
||||
}
|
@ -1 +1,19 @@
|
||||
export default class LethalFantasyItem extends Item {}
|
||||
export const defaultItemImg = {
|
||||
weapon: "systems/fvtt-lethal-fantasy/assets/icons/icon_weapon.webp",
|
||||
armor: "systems/fvtt-lethal-fantasy/assets/icons/icon_armor.webp",
|
||||
equipment: "systems/fvtt-lethal-fantasy/assets/icons/icon_equipment.webp",
|
||||
skill: "systems/fvtt-lethal-fantasy/assets/icons/icon_skill.webp",
|
||||
gift: "systems/fvtt-lethal-fantasy/assets/icons/icon_gift.webp",
|
||||
invulnerability: "systems/fvtt-lethal-fantasy/assets/icons/icon_invulnerability.webp",
|
||||
shield: "systems/fvtt-lethal-fantasy/assets/icons/icon_shield.webp",
|
||||
spell: "systems/fvtt-lethal-fantasy/assets/icons/icon_spell.webp"
|
||||
}
|
||||
|
||||
export default class LethalFantasyItem extends Item {
|
||||
constructor(data, context) {
|
||||
if (!data.img) {
|
||||
data.img = defaultItemImg[data.type];
|
||||
}
|
||||
super(data, context);
|
||||
}
|
||||
}
|
||||
|
@ -9,3 +9,4 @@ export { default as LethalFantasyGift } from "./gift.mjs"
|
||||
export { default as LethalFantasyVulnerability } from "./vulnerability.mjs"
|
||||
export { default as LethalFantasySave } from "./save.mjs"
|
||||
export { default as LethalFantasyEquipment } from "./equipment.mjs"
|
||||
export { default as LethalFantasyMiracle } from "./miracle.mjs"
|
||||
|
@ -52,6 +52,7 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
})
|
||||
schema.grit = new fields.SchemaField({
|
||||
starting: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
earned: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
current: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
})
|
||||
@ -87,6 +88,17 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod
|
||||
/** @override */
|
||||
static LOCALIZATION_PREFIXES = ["LETHALFANTASY.Character"]
|
||||
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData();
|
||||
let grit = 0
|
||||
for (let c in this.characteristics) {
|
||||
if (SYSTEM.CHARACTERISTICS_MAJOR[c.id]) {
|
||||
grit += this.characteristics[c].value
|
||||
}
|
||||
}
|
||||
this.grit.starting = Math.round(grit / 6)
|
||||
}
|
||||
|
||||
/**
|
||||
* Rolls a dice for a character.
|
||||
* @param {("save"|"resource|damage")} rollType The type of the roll.
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
import { CATEGORY } from "../config/weapon.mjs"
|
||||
|
||||
export default class LethalFantasyEquipment extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
|
38
module/models/miracle.mjs
Normal file
38
module/models/miracle.mjs
Normal file
@ -0,0 +1,38 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
export default class LethalFantasyMiracle extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
const schema = {}
|
||||
|
||||
schema.description = new fields.HTMLField({
|
||||
required: false,
|
||||
blank: true,
|
||||
initial: "",
|
||||
textSearch: true,
|
||||
})
|
||||
schema.level = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
initial: 1,
|
||||
min: 1,
|
||||
max: 20,
|
||||
})
|
||||
schema.components = new fields.SchemaField({
|
||||
verbal: new fields.BooleanField(),
|
||||
somatic: new fields.BooleanField(),
|
||||
material: new fields.BooleanField(),
|
||||
catalyst: new fields.BooleanField(),
|
||||
religious: new fields.BooleanField()
|
||||
})
|
||||
schema.prayerTime = new fields.StringField({ required: true, initial: "" })
|
||||
schema.miracleRange = new fields.StringField({ required: true, initial: "" })
|
||||
schema.areaAffected = new fields.StringField({ required: true, initial: "" })
|
||||
schema.duration = new fields.StringField({ required: true, initial: "" })
|
||||
schema.savingThrow = new fields.StringField({ required: true, initial: "" })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static LOCALIZATION_PREFIXES = ["LETHALFANTASY.Miracle"]
|
||||
}
|
@ -12,6 +12,13 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
|
||||
schema.bonus = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
schema.cost = new fields.NumberField({ ...requiredInteger,required: true, initial: 0, min: 0 })
|
||||
|
||||
schema.weaponClass = new fields.StringField({ required: true, initial: "shortblade", choices: SYSTEM.WEAPON_CLASS })
|
||||
schema.weaponBonus = new fields.SchemaField({
|
||||
attack: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
defense: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
damage: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
})
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
@ -21,10 +28,30 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
|
||||
get skillCategory() {
|
||||
return game.i18n.localize(CATEGORY[this.category].label)
|
||||
}
|
||||
|
||||
validate(options) {
|
||||
let isError = super.validate(options)
|
||||
console.log(this)
|
||||
let bonus = this._source.weaponBonus.attack + this._source.weaponBonus.defense + this._source.weaponBonus.damage
|
||||
console.log(bonus, this._source.skillTotal)
|
||||
if ( bonus > Math.floor(this._source.skillTotal / 10) ) {
|
||||
ui.notifications.error(game.i18n.localize("LETHALFANTASY.Skill.error.weaponBonus"))
|
||||
isError = true
|
||||
}
|
||||
return isError
|
||||
}
|
||||
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData();
|
||||
this.skillTotal = this.computeBase();
|
||||
if( this.category === "weapon" ) {
|
||||
this.totalBonus = this.weaponBonus.attack + this.weaponBonus.defense + this.weaponBonus.damage;
|
||||
if ( Number(this.skillTotal) ) {
|
||||
this.availableBonus = Math.max( Math.floor(this.skillTotal / 10) - 1, 0 )
|
||||
} else {
|
||||
this.availableBonus = "N/A"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
computeBase() {
|
||||
@ -47,7 +74,7 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
|
||||
maxStat = statValue;
|
||||
}
|
||||
}
|
||||
return maxStat;
|
||||
return maxStat + this.bonus
|
||||
} else {
|
||||
// Split with + calculate the total
|
||||
baseSplit = base.split("+");
|
||||
@ -59,9 +86,9 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
|
||||
const statValue = actor.system.characteristics[stat.toLowerCase()]?.value || 0;
|
||||
total += statValue;
|
||||
}
|
||||
return total
|
||||
return total + this.bonus
|
||||
}
|
||||
}
|
||||
return `${this.base } + ${ String(this.bonus)}`;
|
||||
return `${this.base} + ${String(this.bonus)}`;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ export default class LethalFantasySpell extends foundry.abstract.TypeDataModel {
|
||||
material: new fields.BooleanField(),
|
||||
})
|
||||
schema.castingTime = new fields.StringField({ required: true, initial: "" })
|
||||
schema.range = new fields.StringField({ required: true, initial: "" })
|
||||
schema.spellRange = new fields.StringField({ required: true, initial: "" })
|
||||
schema.areaAffected = new fields.StringField({ required: true, initial: "" })
|
||||
schema.duration = new fields.StringField({ required: true, initial: "" })
|
||||
schema.savingThrow = new fields.StringField({ required: true, initial: "" })
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
import { CATEGORY } from "../config/weapon.mjs"
|
||||
|
||||
export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
@ -8,6 +8,8 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
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.damageType = new fields.SchemaField({
|
||||
typeP: new fields.BooleanField(),
|
||||
typeB: new fields.BooleanField(),
|
||||
@ -29,7 +31,7 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
|
||||
})
|
||||
|
||||
schema.defense = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
schema.range = new fields.SchemaField({
|
||||
schema.weaponRange = new fields.SchemaField({
|
||||
pointBlank: 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 }),
|
||||
@ -49,6 +51,6 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
|
||||
static LOCALIZATION_PREFIXES = ["LETHALFANTASY.Weapon"]
|
||||
|
||||
get weaponCategory() {
|
||||
return game.i18n.localize(CATEGORY[this.category].label)
|
||||
return game.i18n.localize(CATEGORY[this.weaponType].label)
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,13 @@
|
||||
import { DICE_VALUES } from "./config/system.mjs"
|
||||
|
||||
export default class LethalFantasyUtils {
|
||||
// Return the maximum damage limited by the maximum damage of the character
|
||||
static maxDamage(damage, damageMax) {
|
||||
const damageIndex = DICE_VALUES.indexOf(damage)
|
||||
const damageMaxIndex = DICE_VALUES.indexOf(damageMax)
|
||||
|
||||
// If damage exceeds damageMax, return damageMax
|
||||
if (damageIndex > damageMaxIndex) {
|
||||
return damageMax
|
||||
}
|
||||
|
||||
// Otherwise, return damage (as it is less than or equal to damageMax)
|
||||
return damage
|
||||
return 0
|
||||
}
|
||||
|
||||
// Used when a ressource is lost to find the next lower dice
|
||||
static findLowerDice(dice) {
|
||||
let index = DICE_VALUES.indexOf(dice)
|
||||
return DICE_VALUES[index - 1]
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user