9 Commits

Author SHA1 Message Date
4d96c15066 Add compendium data
All checks were successful
Release Creation / build (release) Successful in 1m2s
2025-06-30 21:11:23 +02:00
fb5c408bbd Enhance CSS
All checks were successful
Release Creation / build (release) Successful in 54s
2025-06-17 00:40:51 +02:00
eea83aa10e Various fixes
All checks were successful
Release Creation / build (release) Successful in 51s
2025-06-15 16:32:47 +02:00
d03c5f2c1e Various fixes
All checks were successful
Release Creation / build (release) Successful in 1m40s
2025-06-15 09:37:08 +02:00
1f2d82bd0b Last fixes from tests 2025-06-14 23:45:05 +02:00
151312b994 Fix success/failure computation
All checks were successful
Release Creation / build (release) Successful in 1m0s
2025-05-30 18:27:37 +02:00
10e668bc71 Fix success/failure computation
All checks were successful
Release Creation / build (release) Successful in 58s
2025-05-30 09:54:58 +02:00
0ee42aef99 Various changes
All checks were successful
Release Creation / build (release) Successful in 58s
2025-05-29 22:41:15 +02:00
ee3a5764f0 Add maintain/duration for maleficas
All checks were successful
Release Creation / build (release) Successful in 59s
2025-05-26 21:01:07 +02:00
46 changed files with 546 additions and 128 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 KiB

BIN
assets/tarots/13_Death.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -212,6 +212,10 @@ i.fvtt-hellborn {
flex-direction: column;
gap: 5px;
}
.fvtt-hellborn .character-main .character-pc .character-right .character-definition .character-definition-pronouns input {
min-width: 21.2rem;
max-width: 21.2rem;
}
.fvtt-hellborn .character-main .character-pc .character-right .character-definition .form-group {
display: flex;
align-items: center;
@@ -558,6 +562,10 @@ i.fvtt-hellborn {
min-width: 4.5rem;
max-width: 4.5rem;
}
.fvtt-hellborn .tab.character-equipment .main-div .weapons .weapon .ammoQuantity {
min-width: 3rem;
max-width: 3rem;
}
.fvtt-hellborn .tab.character-equipment .main-div .weapons .weapon .type {
min-width: 3rem;
max-width: 3rem;
@@ -703,6 +711,29 @@ i.fvtt-hellborn {
height: 24px;
margin: 4px 0 0 0;
}
.fvtt-hellborn .tab.character-biography .main-div .aliases {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 4px;
margin-left: 4px;
}
.fvtt-hellborn .tab.character-biography .main-div .aliases .form-group {
display: flex;
flex-direction: row;
align-items: center;
gap: 4px;
margin-left: 4px;
}
.fvtt-hellborn .tab.character-biography .main-div .aliases .form-group label {
min-width: 6rem;
max-width: 6rem;
}
.fvtt-hellborn .tab.character-biography .main-div .aliases input {
text-align: left;
min-width: 41rem;
max-width: 41rem;
}
.fvtt-hellborn .tab.character-biography .main-div .biodata {
display: grid;
grid-template-columns: repeat(3, 1fr);
@@ -1302,6 +1333,28 @@ i.fvtt-hellborn {
height: 24px;
margin: 4px 0 0 0;
}
.fvtt-hellborn .tab.enemy-traits .main-div .ailments {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 4px;
}
.fvtt-hellborn .tab.enemy-traits .main-div .ailments .ailment {
display: flex;
align-items: center;
gap: 4px;
margin-left: 4px;
min-width: 8rem;
max-width: 8rem;
}
.fvtt-hellborn .tab.enemy-traits .main-div .ailments .ailment label {
min-width: 5rem;
max-width: 5rem;
}
.fvtt-hellborn .tab.enemy-traits .main-div .ailments .ailment .item-img {
width: 24px;
height: 24px;
margin: 4px 0 0 0;
}
.fvtt-hellborn .tab.enemy-traits .main-div .maleficas {
display: grid;
grid-template-columns: repeat(1, 1fr);
@@ -1916,6 +1969,9 @@ i.fvtt-hellborn {
.fvtt-hellborn .tarot-content fieldset {
margin-top: 8px;
}
.fvtt-hellborn .tarot-content fieldset legend {
margin-top: 1rem;
}
.fvtt-hellborn .tarot-content fieldset .form-group {
display: flex;
align-items: center;
@@ -1933,6 +1989,17 @@ i.fvtt-hellborn {
min-width: 12rem;
max-width: 12rem;
}
.fvtt-hellborn .tarot-content fieldset .flexrow,
.fvtt-hellborn .tarot-content fieldset .scrollable-content {
align-items: flex-start;
}
.fvtt-hellborn .tarot-content fieldset .tarot-pic {
margin-left: 1rem;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
.fvtt-hellborn .tarot-content .header {
display: flex;
}
@@ -2392,11 +2459,40 @@ i.fvtt-hellborn {
justify-content: center;
align-items: center;
}
.item-to-chat ul .tarot-spacing {
margin-top: 0.5rem;
}
.item-to-chat ul li {
margin: 0 10px;
font-family: var(--font-primary);
font-size: calc(var(--font-size-standard) * 1);
}
.item-to-chat ul li p {
margin: 0;
}
.flavor-text-damage {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2);
color: var(--color-dark-2);
margin-top: 0px;
align-items: center;
}
.flavor-text-damage .chat-damage-type {
font-weight: bold;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 0.5rem;
}
.flavor-text-damage h2 {
text-align: center;
margin-top: 4px;
margin-left: 4px;
margin-bottom: 0px;
font-family: var(--font-title);
font-size: calc(var(--font-size-standard) * 1.1);
color: var(--title-color);
}
.dice-roll {
flex-direction: column;
}
@@ -2419,6 +2515,14 @@ i.fvtt-hellborn {
display: flex;
flex-direction: row;
}
.dice-roll .intro-chat h2 {
margin-top: 10px;
margin-left: 10px;
margin-bottom: 4px;
font-family: var(--font-title);
font-size: calc(var(--font-size-standard) * 1.4);
color: var(--title-color);
}
.dice-roll .intro-chat .intro-img {
padding: 4px;
max-width: 80px;
@@ -2442,6 +2546,12 @@ i.fvtt-hellborn {
font-family: var(--font-primary);
font-size: calc(var(--font-size-standard) * 1);
}
.dice-roll .intro-chat .intro-right ul .chat-roll-label {
margin-right: 2rem;
}
.dice-roll .intro-chat .intro-right ul .chat-results-spacing {
margin-bottom: 0.5rem;
}
.dice-roll .intro-chat .intro-right ul .nudge-roll {
font-size: calc(var(--font-size-standard) * 1);
margin-left: 4rem;

View File

@@ -30,6 +30,11 @@ Hooks.once("init", function () {
documents,
}
CONFIG.Combat.initiative = {
formula: '3d6 + @stats.mind.value',
decimals: 0
};
CONFIG.Actor.documentClass = documents.HellbornActor
CONFIG.Actor.dataModels = {
character: models.HellbornCharacter,

View File

@@ -64,6 +64,9 @@
"age": {
"label": "Age"
},
"aliases": {
"label": "Aliases"
},
"birthplace": {
"label": "Birthplace"
},
@@ -76,6 +79,9 @@
"hair": {
"label": "Hair"
},
"dod": {
"label": "Date of Death"
},
"height": {
"label": "Height"
},
@@ -386,10 +392,10 @@
"combat": "Combat",
"Counters": "Counters",
"creature": "Creature",
"fiendishSuccess": "Fiendish Failure",
"fiendishFailure": "Fiendish Failure",
"satanicSuccess": "Satanic Success",
"bonus": "Bonus",
"penalty": "Penalty",
"bonus": "Upright XP Trigger",
"penalty": "Reversed XP Trigger",
"quote": "Quote",
"current": "Curr.",
"damage": "Damage",
@@ -476,6 +482,12 @@
"duration": {
"label": "Duration"
},
"maintain": {
"label": "Maintain"
},
"choiceMaintainDuration": {
"label": "Maintain/Duration"
},
"description": {
"label": "Description"
},
@@ -568,7 +580,10 @@
"Tarot": {
"FIELDS": {
"bonus": {
"label": "Bonus"
"label": "Upright XP Trigger"
},
"penalty": {
"label": "Reversed XP Trigger"
},
"description": {
"label": "Description"
@@ -631,9 +646,18 @@
},
"Weapon": {
"FIELDS": {
"stat": {
"label": "Stat"
},
"damageStat": {
"label": "Damage Stat"
},
"ammo": {
"label": "Ammo"
},
"ammoQuantity": {
"label": "Ammo Quantity"
},
"cost": {
"label": "Cost"
},

View File

@@ -19,6 +19,7 @@ export default class HellbornCharacterSheet extends HellbornActorSheet {
createMalefica: HellbornCharacterSheet.#onCreateMalefica,
createRitual: HellbornCharacterSheet.#onCreateRitual,
createPerk: HellbornCharacterSheet.#onCreatePerk,
modifyAmmo: HellbornCharacterSheet.#onModifyAmmo,
},
}
@@ -169,6 +170,18 @@ export default class HellbornCharacterSheet extends HellbornActorSheet {
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HELLBORN.Label.newPerk"), type: "perk" }])
}
static async #onModifyAmmo(event, target) {
const quantity = parseInt($(event.target).data("quantity"))
const itemId = $(event.target).data("item-id")
const item = this.document.items.get(itemId)
if (!item) {
console.warn(`HellbornCharacterSheet: Item with ID ${itemId} not found`)
return
}
const currentAmmo = item.system.ammoQuantity || 0
const newAmmo = Math.max(0, currentAmmo + quantity) // Ensure ammo doesn't go below 0
await item.update({ "system.ammoQuantity": newAmmo })
}
/**
* Handles the roll action triggered by user interaction.

View File

@@ -53,25 +53,24 @@ export const CHOICE_ADVANTAGES_DISADVANTAGES ={
export const PERK_ROLES = {
"abbetor": { id: "abbetor", label: "Abbetor" },
"blade": { id: "blade", label: "Blade" },
"brawler": { id: "brawler", label: "Brawler" },
"gunslinger": { id: "gunslinger", label: "Gunslinger" },
"malefic": { id: "malefic", label: "Malefic" },
"mastermind": { id: "mastermind", label: "Mastermind" },
"sentinel": { id: "sentinel", label: "Sentinel" },
"slayer": { id: "slayer", label: "Slayer" },
"wretch": { id: "wretch", label: "Wretch" },
"other": { id: "other", label: "Other" },
}
export const MALEFICA_DOMAINS = {
"adfectus": { id: "adfectus", label: "Adfectus" },
"animalis": { id: "animalis", label: "Animalis" },
"carnes ": { id: "carnes", label: "Carnes" },
"divinus": { id: "divinus", label: "Divinus" },
"ignis": { id: "ignis", label: "Ignis" },
"iunctio": { id: "iunctio", label: "Iunctio" },
"speculo": { id: "speculo", label: "Speculo" },
"vinculum": { id: "vinculum", label: "Vinculum" },
"vita": { id: "vita", label: "Vita" },
"other": { id: "other", label: "Other" },
}
export const PERK_LEVELS = {

View File

@@ -84,29 +84,30 @@ export default class HellbornRoll extends Roll {
static async prompt(options = {}) {
let formula = `3D6 + 0D6KH - 0D6KH + ${options?.rollItem?.value}`
let actor = game.actors.get(options.actorId)
switch (options.rollType) {
case "stat":
break
case "damage":
{
let formula = options.rollItem.system.damage
if (options.rollItem?.system?.damageStat && options.rollItem.system.damageStat !== "none" && options.rollItem.system.damageStat !== "") {
let statKey = options.rollItem.system?.damageStat.toLowerCase()
let statValue = actor.system.stats[statKey].value
formula = `${formula} + ${statValue}`
}
let damageRoll = new Roll(formula)
await damageRoll.evaluate()
await damageRoll.toMessage({
flavor: `${options.rollItem.name} - Damage Roll - ${options.rollItem.system.damageType}`,
flavor: `<div class="flavor-text-damage"><h2>${options.rollItem.name}</h2>
<BR><span class="chat-damage-type"><span>${options.rollItem.system.damageType}</span></span></div>`,
});
return
}
case "weapon":
{
let actor = game.actors.get(options.actorId)
options.weapon = foundry.utils.duplicate(options.rollItem)
let statKey = "skin"
if (options.weapon.system.weaponType === "melee") {
if ( options.weapon.system.properties.toLowerCase().match("heavy") || options.weapon.system.properties.toLowerCase().match("oversized")) {
statKey = "flesh"
}
}
let statKey = options.weapon.system.stat.toLowerCase()
options.rollItem = actor.system.stats[statKey]
}
break
@@ -199,7 +200,17 @@ export default class HellbornRoll extends Roll {
options.nbAdvantages = Number(options.nbAdvantages)
options.nbDisadvantages = Number(options.nbDisadvantages)
let diceFormula = `3D6 + ${options.nbAdvantages}D6kh - ${options.nbDisadvantages}D6kh + ${options.rollItem.value}`
let dice = 3;
let keep = ""
if ( (options.nbAdvantages !== options.nbDisadvantages) && options.nbAdvantages > 0 || options.nbDisadvantages > 0) {
dice = 4;
if ( options.nbAdvantages > options.nbDisadvantages) {
keep = "kh3"
} else if (options.nbAdvantages < options.nbDisadvantages) {
keep = "kl3"
}
}
let diceFormula = `${dice}D6${keep} + ${options.rollItem.value}`
const roll = new this(diceFormula, options.data, rollData)
await roll.evaluate()
console.log("Roll", rollData, roll)
@@ -219,22 +230,30 @@ export default class HellbornRoll extends Roll {
} else if (this.total >= options.difficulty) {
resultType = "success"
}
// Compute the result quality
this.options.satanicSuccess = false
this.options.fiendishFailure = false
this.options.rollData = foundry.utils.duplicate(rollData)
if (resultType === "success") {
let nb6 = roll.terms[0].results.filter(r => r.result === 6).length
nb6 += roll.terms[3].total === 6 ? 1 : 0
this.options.satanicSuccess = nb6 >= 3
// Check if all results are equal
let workResults = foundry.utils.duplicate(roll.terms[0].results)
// Get the most common result of the roll
let commonResult = workResults.reduce((acc, r) => {
acc[r.result] = (acc[r.result] || 0) + 1
return acc
}, {})
commonResult = Object.entries(commonResult).reduce((a, b) => (a[1] > b[1]) ? a : b)[0]
let nbEqual = workResults.filter(r => Number(r.result) === Number(commonResult)).length
if (commonResult >= 4 && nbEqual >= 3) {
this.options.satanicSuccess = true
if (this.options.satanicSuccess) {
resultType = "success"
}
}
if (resultType === "failure") {
let nb1 = roll.terms[0].results.filter(r => r.result === 1).length
nb1 += roll.terms[5].total === 1 ? 1 : 0
this.options.fiendishFailure = nb1 >= 3
if (commonResult <= 3 && nbEqual >= 3) {
this.options.fiendishFailure = true
if (this.options.fiendishFailure) {
resultType = "failure"
}
@@ -242,6 +261,7 @@ export default class HellbornRoll extends Roll {
this.options.resultType = resultType
this.options.isSuccess = resultType === "success"
this.options.isFailure = resultType === "failure"
this.options.results = roll.terms[0].results
}
/**

View File

@@ -112,16 +112,16 @@ export default class HellbornActor extends foundry.abstract.TypeDataModel {
})
schema.biodata = new fields.SchemaField({
age: new fields.NumberField({ ...requiredInteger, initial: 15, min: 6 }),
age: new fields.StringField({ required: true, nullable: false, initial: "" }),
gender: new fields.StringField({ required: true, nullable: false, initial: "" }),
height: new fields.NumberField({ ...requiredInteger, initial: 170, min: 50 }),
height: new fields.StringField({ required: true, nullable: false, initial: "" }),
eyes: new fields.StringField({ required: true, nullable: false, initial: "" }),
birthplace: new fields.StringField({ required: true, nullable: false, initial: "" }),
hair: new fields.StringField({ required: true, nullable: false, initial: "" }),
home: new fields.StringField({ required: true, nullable: false, initial: "" }),
weight: new fields.NumberField({ ...requiredInteger, initial: 70, min: 1 }),
apparentAge: new fields.NumberField({ ...requiredInteger, initial: 20, min: 1 }),
chronologicalAge: new fields.NumberField({ ...requiredInteger, initial: 20, min: 1 }),
weight: new fields.StringField({ required: true, nullable: false, initial: "" }),
apparentAge: new fields.StringField({ required: true, nullable: false, initial: "" }),
chronologicalAge: new fields.StringField({ required: true, nullable: false, initial: "" }),
dod: new fields.StringField({ required: true, nullable: false, initial: "" }),
soul: new fields.StringField({ required: true, nullable: false, initial: "" }),
aliases: new fields.StringField({ required: true, nullable: false, initial: "" })

View File

@@ -42,6 +42,21 @@ export default class HellbornEnemy extends foundry.abstract.TypeDataModel {
value: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }),
})
// Ailments
const ailmentField = (label) => {
const schema = {
enabled: new fields.BooleanField({ required: true, initial: false }),
label: new fields.StringField({ required: true, initial: label })
}
return new fields.SchemaField(schema, { label })
}
schema.ailments = new fields.SchemaField(
Object.values(SYSTEM.AILMENTS).reduce((obj, ailment) => {
obj[ailment.id] = ailmentField(ailment.label)
return obj
}, {}),
)
schema.defense = new fields.SchemaField({
base: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
bonus: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),

View File

@@ -11,7 +11,11 @@ export default class HellbornMalefica extends foundry.abstract.TypeDataModel {
schema.domain = new fields.StringField({ required: true, nullable: false, choices: SYSTEM.MALEFICA_DOMAINS, initial: "adfectus" })
schema.level = new fields.StringField({ required: true, nullable: false, choices: SYSTEM.MALEFICA_LEVELS, initial: "1" })
schema.time = new fields.StringField({ required: true, initial : "" })
schema.choiceMaintainDuration = new fields.StringField({ required: true, initial : "maintain", choices: {"maintain": "Maintain", "duration": "Duration"} })
schema.duration = new fields.StringField({ required: true, initial : "" })
schema.maintain = new fields.StringField({ required: true, initial : "" })
schema.hasDamage = new fields.BooleanField({ required: true, initial: false })
schema.damage = new fields.StringField({ required: false, initial : "" })
schema.damageType = new fields.StringField({ required: false, initial : "" })

View File

@@ -9,7 +9,7 @@ export default class HellbornTarot extends foundry.abstract.TypeDataModel {
schema.bonus = new fields.StringField({ required: true, nullable: false, initial: "" });
schema.penalty = new fields.StringField({ required: true, nullable: false, initial: "" });
schema.orientation = new fields.StringField({ required: true, initial: "Upright", choices: {"Upright": {label: "Upright"}, "Downright": {label: "Downright"}} });
schema.orientation = new fields.StringField({ required: true, initial: "Upright", choices: {"Upright": {label: "Upright"}, "Downright": {label: "Reversed"}} });
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.positiveEffect = new fields.HTMLField({ required: true, textSearch: true })
schema.negativeEffect = new fields.HTMLField({ required: true, textSearch: true })

View File

@@ -7,15 +7,18 @@ export default class HellbornWeapon extends foundry.abstract.TypeDataModel {
const requiredInteger = { required: true, nullable: false, integer: true }
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.stat = new fields.StringField({ required: true, initial: "skin", choices: {"skin": "Skin", "flesh": "Flesh" }})
schema.weaponType = new fields.StringField({ required: true, initial: "melee", choices: SYSTEM.WEAPON_TYPES })
schema.subType = new fields.StringField({ required: false, initial: "pistols", choices: SYSTEM.RANGED_SUBTYPES })
schema.properties = new fields.StringField({required: true, initial: ""})
schema.damage = new fields.StringField({required: true, initial: "1d6"})
schema.damageStat = new fields.StringField({ required: true, initial: "none", choices: {"none": "None", "skin": "Skin", "flesh": "Flesh", "heart": "Heart", "mind": "Mind", "soul": "Soul" }})
schema.damageType = new fields.StringField({ required: false, initial : "Physical" })
schema.ammo = new fields.StringField({ required: false, initial: "" })
schema.ammoQuantity = new fields.NumberField({ required: true, initial: 0, min: 0 })
schema.range = new fields.StringField({ required: false, initial: "" })
schema.cost = new fields.NumberField({ required: true, initial: 0, min: 0 })
@@ -25,4 +28,14 @@ export default class HellbornWeapon extends foundry.abstract.TypeDataModel {
/** @override */
static LOCALIZATION_PREFIXES = ["HELLBORN.Weapon"]
prepareDerivedData() {
super.prepareDerivedData();
let actor = this.parent?.actor;
if (actor) {
this.damageFormula = this.damage + (this.damageStat !== "none" ? `+${actor.system.stats[this.damageStat].value}` : "");
} else {
this.damageFormula = this.damage;
}
}
}

Binary file not shown.

View File

@@ -0,0 +1 @@
MANIFEST-000010

View File

View File

@@ -0,0 +1,15 @@
2025/06/30-20:37:58.108400 7f0798bfa6c0 Recovering log #8
2025/06/30-20:37:58.118139 7f0798bfa6c0 Delete type=3 #6
2025/06/30-20:37:58.118202 7f0798bfa6c0 Delete type=0 #8
2025/06/30-21:11:07.629621 7f07923ff6c0 Level-0 table #13: started
2025/06/30-21:11:07.632961 7f07923ff6c0 Level-0 table #13: 19920 bytes OK
2025/06/30-21:11:07.639130 7f07923ff6c0 Delete type=0 #11
2025/06/30-21:11:07.658870 7f07923ff6c0 Manual compaction at level-0 from '!folders!0d8PWsAGxiRfOlkP' @ 72057594037927935 : 1 .. '!items!zCOHBP3SYlGAY6zI' @ 0 : 0; will stop at (end)
2025/06/30-21:11:07.675316 7f07923ff6c0 Manual compaction at level-1 from '!folders!0d8PWsAGxiRfOlkP' @ 72057594037927935 : 1 .. '!items!zCOHBP3SYlGAY6zI' @ 0 : 0; will stop at '!items!xiuPJDuvpdMEtiPe' @ 284 : 1
2025/06/30-21:11:07.675323 7f07923ff6c0 Compacting 1@1 + 1@2 files
2025/06/30-21:11:07.680513 7f07923ff6c0 Generated table #14@1: 267 keys, 115927 bytes
2025/06/30-21:11:07.680536 7f07923ff6c0 Compacted 1@1 + 1@2 files => 115927 bytes
2025/06/30-21:11:07.686716 7f07923ff6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
2025/06/30-21:11:07.686840 7f07923ff6c0 Delete type=2 #5
2025/06/30-21:11:07.686988 7f07923ff6c0 Delete type=2 #13
2025/06/30-21:11:07.693807 7f07923ff6c0 Manual compaction at level-1 from '!items!xiuPJDuvpdMEtiPe' @ 284 : 1 .. '!items!zCOHBP3SYlGAY6zI' @ 0 : 0; will stop at (end)

View File

@@ -0,0 +1,8 @@
2025/06/30-19:11:32.088394 7f0792ffd6c0 Recovering log #4
2025/06/30-19:11:32.165054 7f0792ffd6c0 Delete type=3 #2
2025/06/30-19:11:32.165125 7f0792ffd6c0 Delete type=0 #4
2025/06/30-19:18:30.163563 7f07923ff6c0 Level-0 table #9: started
2025/06/30-19:18:30.163654 7f07923ff6c0 Level-0 table #9: 0 bytes OK
2025/06/30-19:18:30.170671 7f07923ff6c0 Delete type=0 #7
2025/06/30-19:18:30.184576 7f07923ff6c0 Manual compaction at level-0 from '!folders!0d8PWsAGxiRfOlkP' @ 72057594037927935 : 1 .. '!items!zCOHBP3SYlGAY6zI' @ 0 : 0; will stop at (end)
2025/06/30-19:18:30.184606 7f07923ff6c0 Manual compaction at level-1 from '!folders!0d8PWsAGxiRfOlkP' @ 72057594037927935 : 1 .. '!items!zCOHBP3SYlGAY6zI' @ 0 : 0; will stop at (end)

Binary file not shown.

View File

@@ -65,12 +65,18 @@
gap: 5px;
.character-definition {
.character-definition-pronouns {
input {
min-width: 21.2rem;
max-width: 21.2rem;
}
}
.form-group {
display: flex;
align-items: center;
margin-bottom: 4px;
}
.splitted {
.splitted {
display: flex;
flex-direction: row;
gap: 4px;
@@ -183,15 +189,15 @@
align-items: center;
gap: 4px;
margin-left: 4px;
.characteristics-label{
.characteristics-label {
color: grey;
font-size:small;
font-size: small;
}
label {
min-width: 4rem;
max-width: 4rem;
}
.spaced-left{
.spaced-left {
margin-left: 0.8rem;
}
input {
@@ -432,6 +438,10 @@
min-width: 4.5rem;
max-width: 4.5rem;
}
.ammoQuantity {
min-width: 3rem;
max-width: 3rem;
}
.type {
min-width: 3rem;
max-width: 3rem;
@@ -585,6 +595,29 @@
}
}
}
.aliases {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 4px;
margin-left: 4px;
.form-group {
label {
min-width: 6rem;
max-width: 6rem;
}
display: flex;
flex-direction: row;
align-items: center;
gap: 4px;
margin-left: 4px;
}
input {
text-align: left;
min-width: 41rem;
max-width: 41rem;
}
}
.biodata {
display: grid;
grid-template-columns: repeat(3, 1fr);

View File

@@ -70,7 +70,7 @@
align-items: center;
margin-bottom: 4px;
}
.splitted {
.splitted {
display: flex;
flex-direction: row;
gap: 4px;
@@ -165,7 +165,7 @@
}
}
.enemy-column {
display:flex;
display: flex;
flex-direction: row;
gap: 4px;
fieldset {
@@ -191,9 +191,9 @@
align-items: center;
gap: 4px;
margin-left: 4px;
.characteristics-label{
.characteristics-label {
color: grey;
font-size:small;
font-size: small;
label {
min-width: 3.5rem;
max-width: 3.5rem;
@@ -207,7 +207,7 @@
min-width: 4rem;
max-width: 4rem;
}
.spaced-left{
.spaced-left {
margin-left: 0.8rem;
}
input {
@@ -247,7 +247,7 @@
}
}
}
.equipments {
.equipments {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 4px;
@@ -279,6 +279,29 @@
}
}
.ailments {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 4px;
.ailment {
display: flex;
align-items: center;
gap: 4px;
margin-left: 4px;
min-width: 8rem;
max-width: 8rem;
label {
min-width: 5rem;
max-width: 5rem;
}
.item-img {
width: 24px;
height: 24px;
margin: 4px 0 0 0;
}
}
}
.maleficas {
display: grid;
grid-template-columns: repeat(1, 1fr);
@@ -374,7 +397,6 @@
}
}
}
}
.tab.enemy-biography .main-div {

View File

@@ -57,7 +57,7 @@
.item-to-chat {
h2 {
margin-top: 10px;
margin-left:10px;
margin-left: 10px;
margin-bottom: 4px;
font-family: var(--font-title);
font-size: calc(var(--font-size-standard) * 1.4);
@@ -69,14 +69,44 @@
margin: 0;
justify-content: center;
align-items: center;
.tarot-spacing {
margin-top: 0.5rem;
}
li {
margin: 0 10px;
font-family: var(--font-primary);
font-size: calc(var(--font-size-standard) * 1);
p {
margin: 0;
}
}
}
}
.flavor-text-damage {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2);
color: var(--color-dark-2);
margin-top: 0px;
align-items: center;
.chat-damage-type {
font-weight: bold;
display: flex;
justify-content: center;
align-items: center;
margin-bottom:0.5rem;
}
h2 {
text-align: center;
margin-top: 4px;
margin-left: 4px;
margin-bottom: 0px;
font-family: var(--font-title);
font-size: calc(var(--font-size-standard) * 1.1);
color: var(--title-color);
}
}
&.dice-roll {
flex-direction: column;
@@ -98,10 +128,19 @@
border-radius: 20px;
display: flex;
flex-direction: row;
h2 {
margin-top: 10px;
margin-left: 10px;
margin-bottom: 4px;
font-family: var(--font-title);
font-size: calc(var(--font-size-standard) * 1.4);
color: var(--title-color);
}
.intro-img {
padding: 4px;
max-width: 80px;
min-width : 80px;
min-width: 80px;
align-self: top;
text-align: center;
}
@@ -119,6 +158,12 @@
font-family: var(--font-primary);
font-size: calc(var(--font-size-standard) * 1);
}
.chat-roll-label {
margin-right: 2rem;
}
.chat-results-spacing {
margin-bottom: 0.5rem;
}
.nudge-roll {
font-size: calc(var(--font-size-standard) * 1);
margin-left: 4rem;
@@ -158,6 +203,7 @@
}
}
}
.result {
display: flex;
flex-direction: column;

View File

@@ -4,6 +4,9 @@
fieldset {
margin-top: 8px;
legend {
margin-top: 1rem;
}
.form-group {
display: flex;
align-items: center;
@@ -21,8 +24,18 @@
min-width: 12rem;
max-width: 12rem;
}
.flexrow,
.scrollable-content {
align-items: flex-start;
}
.tarot-pic {
margin-left: 1rem;
display: flex;
flex-direction: column;
justify-content: flex-start; // aligne le contenu en haut
align-items: center; // ce }
}
}
.header {
display: flex;
img {

View File

@@ -49,6 +49,14 @@
}
},
"packs": [
{
"name": "hellborn-quickstart",
"banner": "systems/fvtt-hellborn/assets/ui/banner_compendium.png",
"label": "Hellborn - Quickstart",
"system": "fvtt-hellborn",
"path": "packs-system/hellborn-quickstart",
"type": "Item"
}
],
"grid": {
"distance": 10,

View File

@@ -17,34 +17,42 @@
</div>
</fieldset>
<fieldset class="biodata">
<fieldset >
<legend>{{localize "HELLBORN.Label.biodata"}}</legend>
<div class="experience">
{{formField systemFields.biodata.fields.gender value=system.biodata.gender rootId=partId disabled=isPlayMode}}
<div class="aliases">
{{formField systemFields.biodata.fields.aliases value=system.biodata.aliases rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.age value=system.biodata.age rootId=partId disabled=isPlayMode}}
<div class="biodata">
<div class="experience">
{{formField systemFields.biodata.fields.gender value=system.biodata.gender rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.age value=system.biodata.age rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.height value=system.biodata.height rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.weight value=system.biodata.weight rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.eyes value=system.biodata.eyes rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.hair value=system.biodata.hair rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.home value=system.biodata.home rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.birthplace value=system.biodata.birthplace rootId=partId
disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.dod value=system.biodata.dod rootId=partId
disabled=isPlayMode}}
</div>
</div>
<div class="experience">
{{formField systemFields.biodata.fields.height value=system.biodata.height rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.weight value=system.biodata.weight rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.eyes value=system.biodata.eyes rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.hair value=system.biodata.hair rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.home value=system.biodata.home rootId=partId disabled=isPlayMode}}
</div>
<div class="experience">
{{formField systemFields.biodata.fields.birthplace value=system.biodata.birthplace rootId=partId
disabled=isPlayMode}}
</div>
</fieldset>
<fieldset>

View File

@@ -10,20 +10,25 @@
{{#each weapons as |item|}}
<div class="weapon item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}} - {{upperFirst item.system.weaponType}}" />
<i class="fa-regular fa-dice"></i>
<div class="name rollable" data-roll-type="weapon" data-tooltip="{{{item.system.description}}}">
{{item.name}}
</div>
<span class="type" data-tooltip="Type">{{upperFirst item.system.weaponType}}</span>
<!-- <span class="type" data-tooltip="Type">{{upperFirst item.system.weaponType}}</span> -->
<span class="properties" data-tooltip="Properties">{{upperFirst item.system.properties}}</span>
<span class="range" data-tooltip="Range">{{upperFirst item.system.range}}</span>
<span class="ammo" data-tooltip="Ammo">{{upperFirst item.system.ammo}}</span>
<span class="ammoQuantity" data-tooltip="ammoQuantity">
<i class="fa-solid fa-octagon-plus" data-action="modifyAmmo" data-quantity="1" data-item-id="{{item.id}}"></i>
{{item.system.ammoQuantity}}
<i class="fa-solid fa-octagon-minus" data-action="modifyAmmo" data-quantity="-1" data-item-id="{{item.id}}"></i>
</span>
<a class="damage rollable" data-tooltip="Damage" data-item-id="{{item.id}}" data-action="roll"
data-roll-type="damage" data-roll-value="{{item.system.damage}}">
data-roll-type="damage" data-roll-value="{{item.system.damageFormula}}">
<i class="fa-regular fa-dice"></i>
{{item.system.damage}}</a>
{{item.system.damageFormula}}</a>
<div class="controls">
<a data-tooltip="{{localize 'HELLBORN.Edit'}}" data-action="edit" data-item-id="{{item.id}}"

View File

@@ -19,11 +19,11 @@
</div>
<fieldset class="character-definition">
<div class="flexcol character-definition-pronouns">
{{formField systemFields.pronouns value=system.pronouns rootId=partId disabled=isPlayMode}}
</div>
<div class="splitted">
<div>
<div class="flexcol">
{{formField systemFields.pronouns value=system.pronouns rootId=partId disabled=isPlayMode}}
</div>
<div class="flexcol">
{{formField systemFields.species value=system.species rootId=partId disabled=isPlayMode}}
</div>
@@ -56,7 +56,7 @@
</div>
<div class="flexrow">
<div class="form-group">
<label><a data-action="toChat" data-item-uuid="{{upright.uuid}}">Reversed</a></label>
<label><a data-action="toChat" data-item-uuid="{{downright.uuid}}">Reversed</a></label>
<input class="trait" type="text" value="{{downright.name}}" disabled >
<div class="controls">
<a data-tooltip="{{localize 'HELLBORN.Edit'}}" data-action="edit" data-item-id="{{downright.id}}"

View File

@@ -12,7 +12,7 @@
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<!--<img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />-->
<div class="name" data-action="toChat" data-item-uuid="{{item.uuid}}" data-roll-type="malefica" data-tooltip="{{{item.system.description}}}">
<div class="name" data-action="toChat" data-item-uuid="{{item.uuid}}" data-roll-type="malefica" data-tooltip="{{{item.system.description}}}<br>Time:{{item.system.time}}<br>Duration:{{item.system.duration}}<br>Range:{{item.system.range}}<br>Target:{{item.system.target}}">
<a>{{item.name}}</a>
</div>
<span class="domain" data-tooltip="Domain">{{upperFirst item.system.domain}}</span>

View File

@@ -6,7 +6,11 @@
<li><strong>Domain : </strong>{{upperFirst system.domain}}</li>
<li><strong>Level : </strong>{{getRomanLevel system.level}}</li>
<li><strong>Time : </strong>{{system.time}}</li>
<li><strong>Duration : </strong>{{system.duration}}</li>
{{#if (eq system.choiceMaintainDuration "duration")}}
<li><strong>Duration : </strong>{{system.duration}}</li>
{{else}}
<li><strong>Maintain : </strong>{{system.maintain}}</li>
{{/if}}
<li><strong>Range : </strong>{{system.range}}</li>
<li><strong>Target : </strong>{{system.target}}</li>
<li>{{{system.description}}}</li>

View File

@@ -5,55 +5,68 @@
{{actorName}}
</div>
<div class="intro-right">
{{#if (eq rollType "stat")}}
<h2>{{localize "HELLBORN.Label.statRoll"}}</h2>
{{/if}}
{{#if weapon}}
<h2>{{weapon.name}}</strong></h2>
{{/if}}
<ul>
{{#if (eq rollType "stat")}}
<li><strong>{{localize "HELLBORN.Label.statRoll"}}</strong></li>
{{/if}}
{{#if weapon}}
<li><strong>Weapon : {{weapon.name}}</strong></li>
<li><strong>Properties :</strong> {{weapon.system.properties}}</li>
<li>
<span>
<span class="chat-roll-label"><strong>{{localize rollItem.label}} : {{rollItem.value}}</strong></span>
<span>{{localize "HELLBORN.Label.difficulty"}} : {{difficulty}}</span>
</span>
</li>
{{#if (gt nbAdvantages 0)}}
<li>With Advantage !</li>
{{/if}}
{{#if (gt nbDisadvantages 0)}}
<li>With Disadvantages ! </li>
{{/if}}
<li><strong>{{localize rollItem.label}} : {{rollItem.value}}</strong></li>
<li class="chat-results-spacing">Results :
{{#each results as |result|}}
{{result.result}}
{{/each}}
</li>
<li>{{localize "HELLBORN.Label.difficulty"}} : {{difficulty}}</li>
{{#if isSuccess}}
{{#if satanicSuccess}}
<li class="chat-results-spacing result-satanic-success">
{{localize "HELLBORN.Label.satanicSuccess"}}
</li>
{{else}}
<li class="chat-results-spacing result-success">
{{localize "HELLBORN.Label.success"}}
</li>
{{/if}}
{{/if}}
{{#if isFailure}}
{{#if fiendishFailure}}
<li class="chat-results-spacing result-fiendish-failure">
{{localize "HELLBORN.Label.fiendishFailure"}}
</li>
{{else}}
<li class="chat-results-spacing result-failure">
{{localize "HELLBORN.Label.failure"}}
</li>
{{/if}}
{{/if}}
{{#if (eq resultType "unknown")}}
<li class="result-unknown">
{{localize "HELLBORN.Label.unknown"}}
</li>
{{else}}
{{#if isSuccess}}
{{#if satanicSuccess}}
<li class="result-satanic-success">
{{localize "HELLBORN.Label.satanicSuccess"}}
</li>
{{else}}
<li class="result-success">
{{localize "HELLBORN.Label.success"}}
</li>
{{/if}}
{{/if}}
{{#if isFailure}}
{{#if fiendishFailure}}
<li class="result-fiendish-failure">
{{localize "HELLBORN.Label.fiendishFailure"}}
</li>
{{else}}
<li class="result-failure">
{{localize "HELLBORN.Label.failure"}}
</li>
{{/if}}
{{/if}}
{{#if isCritical}}
{{/if}}
<li class="chat-results-spacing result-unknown">
{{localize "HELLBORN.Label.unknown"}}
</li>
{{/if}}
</ul>
</div>
</div>

View File

@@ -2,7 +2,7 @@
<div class="intro-chat">
<h2>{{name}}</h2>
<ul>
<li><strong>{{system.flavorText}}</strong></li>
<li><strong><i>{{system.flavorText}}</i></strong></li>
<li><strong>Role : </strong>{{upperFirst system.role}}</li>
<li><strong>Level : </strong>{{getRomanLevel system.level}}</li>
<li>{{{system.description}}}</li>

View File

@@ -2,14 +2,29 @@
<div class="intro-chat">
<h2>{{name}}</h2>
<ul>
<li><strong>Orientation : </strong>{{system.orientation}}</li>
{{#if (eq system.orientation "Upright")}}
<li><strong>Orientation : </strong>Upright</li>
{{else}}
<li><strong>Orientation : </strong>Reversed</li>
{{/if}}
<li><strong>Quote : </strong>{{system.quote}}</li>
<li><strong>Bonus : </strong>{{system.bonus}}</li>
<li><strong>Penalty : </strong>{{system.penalty}}</li>
<li>{{{system.description}}}</li>
<li>{{{system.positiveEffect}}}</li>
<li>{{{system.negativeEffect}}}</li>
{{#if (eq system.orientation "Upright")}}
<li><strong>Upright XP Trigger : </strong>{{system.bonus}}</li>
{{else}}
<li><strong>Reversed XP Trigger : </strong>{{system.penalty}}</li>
{{/if}}
<li class="tarot-spacing"><strong>Description : </strong>{{{system.description}}}</li>
{{#if (eq system.orientation "Upright")}}
<li class="tarot-spacing"><strong>Positive Effect : </strong>{{{system.positiveEffect}}}</li>
{{else}}
<li class="tarot-spacing"><strong>Negative Effect : </strong>{{{system.negativeEffect}}}</li>
{{/if}}
</ul>
<img class="item-img" src="{{system.image}}" />
</div>
</div>

View File

@@ -33,6 +33,19 @@
</div>
</fieldset>
<fieldset>
<legend>{{localize "HELLBORN.Label.ailments"}}</legend>
<div class="ailments">
{{#each system.ailments as |item id|}}
<div class="ailment " data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="false">
<label>{{item.label}}</label> <input type="checkbox" class="checkbox" name="system.ailments.{{id}}.enabled"
{{#if item.enabled}} checked {{/if}}>
</div>
{{/each}}
</div>
</fieldset>
<div class="enemy-column">
<fieldset>

View File

@@ -8,7 +8,14 @@
{{formField systemFields.domain value=system.domain localize=true}}
{{formField systemFields.level value=system.level localize=true}}
{{formField systemFields.time value=system.time localize=true }}
{{formField systemFields.duration value=system.duration localize=true}}
{{formField systemFields.choiceMaintainDuration value=system.choiceMaintainDuration localize=true }}
{{#if (eq system.choiceMaintainDuration "duration")}}
{{formField systemFields.duration value=system.duration localize=true}}
{{else}}
{{formField systemFields.maintain value=system.maintain localize=true}}
{{/if}}
{{formField systemFields.range value=system.range localize=true}}
{{formField systemFields.target value=system.target localize=true}}
{{formField systemFields.hasDamage value=system.hasDamage localize=true}}

View File

@@ -27,7 +27,7 @@
{{formInput systemFields.negativeEffect enriched=enrichedNegativeEffect value=system.negativeEffect name="system.negativeEffect"
toggled=true}}
</div>
<div>
<div class="tarot-pic">
<img src="{{system.image}}" class="item-img" data-edit="image" data-action="editImage" data-tooltip="{{localize "HELLBORN.Label.imageTooltip"}}"/>
{{formField systemFields.image value=system.image localize=true }}
</div>

View File

@@ -5,15 +5,19 @@
</div>
<fieldset>
{{formField systemFields.stat value=system.stat localize=true}}
{{formField systemFields.weaponType value=system.weaponType localize=true}}
{{#if (eq system.weaponType "ranged")}}
{{formField systemFields.subType value=system.subType localize=true}}
{{formField systemFields.range value=system.range localize=true}}
{{formField systemFields.ammo value=system.ammo localize=true}}
{{formField systemFields.ammoQuantity value=system.ammoQuantity localize=true}}
{{/if}}
{{formField systemFields.properties value=system.properties classes="long-input"}}
{{formField systemFields.damage value=system.damage}}
{{formField systemFields.damageStat value=system.damageStat localize=true}}
{{formField systemFields.damageType value=system.damageType}}
{{formField systemFields.cost value=system.cost}}