22 Commits

Author SHA1 Message Date
a2b712b78d Diverses corrections + ajouts armes en compendiums
All checks were successful
Release Creation / build (release) Successful in 1m53s
2026-02-26 13:30:53 +01:00
fc6bb7a4b1 CSS rework et autres améliorations
All checks were successful
Release Creation / build (release) Successful in 46s
2026-02-12 23:08:51 +01:00
f26130d208 CSS rework et autres améliorations 2026-02-12 23:05:22 +01:00
39da08d4cb CSS rework et autres améliorations 2026-02-12 23:04:37 +01:00
e639b6ae3e Fix rollData = 1
All checks were successful
Release Creation / build (release) Successful in 3m36s
2025-12-01 17:57:19 +01:00
8c247a8981 Echec automatique sur 1
All checks were successful
Release Creation / build (release) Successful in 49s
2025-11-21 21:36:27 +01:00
a09e1a1d95 Les compétences de base ne peuvent être supprimées
All checks were successful
Release Creation / build (release) Successful in 47s
2025-11-02 18:30:20 +01:00
787f88873a Les compétences de base ne peuvent être supprimées 2025-11-02 18:29:46 +01:00
ac481e0dd9 Various minot fixes
All checks were successful
Release Creation / build (release) Successful in 1m18s
2025-10-30 20:24:24 +00:00
375622d900 Add welcome message 2025-10-17 15:31:32 +02:00
3bc055cc1f Add welcome message 2025-10-17 15:28:15 +02:00
c97b7a4889 Correction sur blessures et actions restantes
All checks were successful
Release Creation / build (release) Successful in 53s
2025-10-16 22:59:32 +02:00
5d13500838 Fix sur combat + mains gauche
All checks were successful
Release Creation / build (release) Successful in 43s
2025-09-24 16:43:52 +02:00
d21515e1e3 Fix sur combat + mains gauche 2025-09-24 16:43:40 +02:00
78ef009465 Fix sur combat + mains gauche 2025-09-24 16:42:08 +02:00
e794611bf3 Gestion assistée pour les actions
All checks were successful
Release Creation / build (release) Successful in 46s
2025-09-24 15:11:58 +02:00
529a62045e Gestion assistée pour les actions 2025-09-24 15:09:00 +02:00
d462d22a0a Manye enhancements for combat
All checks were successful
Release Creation / build (release) Successful in 42s
2025-09-18 17:26:02 +02:00
710ee54531 Manye enhancements for combat 2025-09-18 17:24:42 +02:00
7994aa7db4 Fix savoir lors de la creation de perso
All checks were successful
Release Creation / build (release) Successful in 1m30s
2025-09-08 23:47:19 +02:00
5176b4ce87 Amelioration histoire creation de perso, CSS bouton et genre de la providence
All checks were successful
Release Creation / build (release) Successful in 56s
2025-07-20 11:21:08 +02:00
3d6f195fc2 Educcation fix + CSS v13
All checks were successful
Release Creation / build (release) Successful in 43s
2025-07-02 23:08:34 +02:00
105 changed files with 4513 additions and 2618 deletions

54
.gitignore vendored Normal file
View File

@@ -0,0 +1,54 @@
# Dependencies
node_modules/
package-lock.json
# Build outputs
styles/tedeum.css
styles/*.css.map
# IDE & Editor files
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
# System files
Thumbs.db
desktop.ini
# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
*.log
# Temporary files
*.tmp
*.temp
.cache/
# Environment variables
.env
.env.local
# Optional: Uncomment if you want to ignore pack database files
# These are usually committed for systems, but can be regenerated
# packs/**/*.ldb
# packs/**/LOG
# packs/**/LOG.old
# packs/**/MANIFEST-*
# packs/**/CURRENT
# Compiled source
dist/
build/
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db

View File

@@ -1,25 +1,17 @@
var gulp = require('gulp');
var less = require('gulp-less');
var postcss = require('gulp-postcss');
var autoprefixer = require('autoprefixer');
var cssnext = require('postcss-preset-env');
var precss = require('precss');
gulp.task('css', function () {
var processors = [
autoprefixer,
cssnext,
precss
];
return gulp.src('./postcss/*.css')
.pipe(postcss(processors))
return gulp.src('./less/*.less')
.pipe(less())
.pipe(postcss([autoprefixer]))
.pipe(gulp.dest('./styles'));
});
gulp.task('watch', function () {
gulp.watch('./less/*.less', gulp.series('css'));
});
function watchUpdates() {
gulp.watch('./postcss/*.css', css);
}
gulp.task('default', gulp.series('css'));

BIN
images/icons/xpplus1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

2070
less/tedeum.less Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,7 @@ export class TeDeumActorPJSheet extends foundry.appv1.sheets.ActorSheet {
classes: ["fvtt-te-deum", "sheet", "actor"],
template: "systems/fvtt-te-deum/templates/actors/actor-sheet.hbs",
width: 860,
height:680,
height: 680,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "skills" }],
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
editScore: true
@@ -67,7 +67,6 @@ export class TeDeumActorPJSheet extends foundry.appv1.sheets.ActorSheet {
}
this.formData = formData;
console.log("PC : ", formData, this.object);
return formData;
}
@@ -80,7 +79,7 @@ export class TeDeumActorPJSheet extends foundry.appv1.sheets.ActorSheet {
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
html.bind("keydown", function(e) { // Ignore Enter in actores sheet
html.bind("keydown", function (e) { // Ignore Enter in actores sheet
if (e.keyCode === 13) return false;
});
@@ -88,7 +87,7 @@ export class TeDeumActorPJSheet extends foundry.appv1.sheets.ActorSheet {
html.find('.item-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item-id")
let itemId = li.data("item-id")
const item = this.actor.items.get( itemId );
const item = this.actor.items.get(itemId);
item.sheet.render(true);
});
// Delete Inventory Item
@@ -100,16 +99,20 @@ export class TeDeumActorPJSheet extends foundry.appv1.sheets.ActorSheet {
let dataType = $(ev.currentTarget).data("type")
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouveau " + dataType, type: dataType }], { renderSheet: true })
})
html.find('.blessure-add').click(ev => {
let dataType = $(ev.currentTarget).data("type")
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvelle " + dataType, type: dataType, system: { typeBlessure: "estafilade", localisation: "corps", value: 0, appliquee: true, description: "" } }], { renderSheet: true })
})
html.find('.competence-add').click(ev => {
let dataType = $(ev.currentTarget).data("type")
let caracKey = $(ev.currentTarget).data("carac-key")
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvelle " + dataType, type: dataType, system: {caracteristique: caracKey} }], { renderSheet: true })
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvelle " + dataType, type: dataType, system: { caracteristique: caracKey } }], { renderSheet: true })
})
html.find('.subactor-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item");
let actorId = li.data("actor-id");
let actor = game.actors.get( actorId );
let actor = game.actors.get(actorId);
actor.sheet.render(true);
});
@@ -120,12 +123,12 @@ export class TeDeumActorPJSheet extends foundry.appv1.sheets.ActorSheet {
});
html.find('.quantity-minus').click(event => {
const li = $(event.currentTarget).parents(".item");
this.actor.incDecQuantity( li.data("item-id"), -1 );
} );
this.actor.incDecQuantity(li.data("item-id"), -1);
});
html.find('.quantity-plus').click(event => {
const li = $(event.currentTarget).parents(".item");
this.actor.incDecQuantity( li.data("item-id"), +1 );
} );
this.actor.incDecQuantity(li.data("item-id"), +1);
});
html.find('.roll-competence').click((event) => {
let compId = $(event.currentTarget).data("comp-id")
@@ -147,13 +150,13 @@ export class TeDeumActorPJSheet extends foundry.appv1.sheets.ActorSheet {
});
html.find('.item-equip').click(ev => {
const li = $(ev.currentTarget).parents(".item");
this.actor.equipItem( li.data("item-id") );
this.actor.equipItem(li.data("item-id"));
this.render(true);
});
html.find('.update-field').change(ev => {
const fieldName = $(ev.currentTarget).data("field-name");
let value = Number(ev.currentTarget.value);
this.actor.update( { [`${fieldName}`]: value } );
this.actor.update({ [`${fieldName}`]: value });
});
}

View File

@@ -34,7 +34,7 @@ export class TeDeumActor extends Actor {
return actor;
}
if (data.type == 'pj' || data.type == 'pnj') {
if (data.type == 'pj' || data.type == 'pnj') {
const skills = await TeDeumUtility.loadCompendium("fvtt-te-deum.competences")
data.items = data.items || []
for (let skill of skills) {
@@ -65,14 +65,43 @@ export class TeDeumActor extends Actor {
super._preUpdate(changed, options, user);
}
/* -------------------------------------------- */
getCompetenceScore(compName) {
let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == compName.toLowerCase())
if (competence) {
if (competence.system.isBase) {
return this.system.caracteristiques[competence.system.caracteristique].value
}
return competence.system.score
}
return 0
}
/* -------------------------------------------- */
getMeilleureCompetenceMainGauche(comp) {
let compScore = this.getCompetenceScore(comp.name)
let mainGaucheScore = this.getCompetenceScore("main gauche")
if (mainGaucheScore < compScore) {
ui.notifications.info(`${this.name} : Utilisation de la compétence Main Gauche au lieu de ${comp.name}`)
let mainGaucheComp = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "main gauche")
if (!mainGaucheComp) {
// Create a fake competence object
mainGaucheComp = foundry.utils.duplicate(comp)
mainGaucheComp.name = "Main Gauche"
mainGaucheComp.system.isBase = false
mainGaucheComp.system.score = 0
mainGaucheComp.system.caracteristique = "adresse"
mainGaucheComp.system.description = "Compétence Main Gauche (automatique)"
mainGaucheComp.system.isMainGauche = true
return mainGaucheComp
} else {
return mainGaucheComp
}
} else {
return comp
}
}
/* -------------------------------------------- */
_onUpdate(changed, options, userId) {
let updates = []
@@ -112,12 +141,6 @@ export class TeDeumActor extends Actor {
updates.push({ _id: initiative.id, "system.score": Number(newScore) })
}
let actionsTour = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "actions/tour")
newScore = this.getCommonBaseValue(this.system.caracteristiques.adresse.value)
if (actionsTour && actionsTour?.system.score != newScore) {
updates.push({ _id: actionsTour.id, "system.score": Number(newScore) })
}
let effort = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "effort")
newScore = this.getCommonBaseValue(this.system.caracteristiques.puissance.value)
if (effort && effort?.system.score != newScore) {
@@ -147,7 +170,7 @@ export class TeDeumActor extends Actor {
getCommonBaseValue(value) {
return game.system.tedeum.config.COMMON_VALUE[value]?.value || 0
}
getInitiative() {
getInitiativeValue() {
return game.system.tedeum.config.COMMON_VALUE[this.system.caracteristiques.adresse.value]?.value || 0
}
/* -------------------------------------------- */
@@ -155,6 +178,24 @@ export class TeDeumActor extends Actor {
return game.system.tedeum.config.BONUS_DEGATS[this.system.caracteristiques.puissance.value]
}
/* -------------------------------------------- */
getAttaqueBonusDegats(rollData = undefined) {
let base = game.system.tedeum.config.BONUS_DEGATS[this.system.caracteristiques.puissance.value].value
let additionalBonus = 0
if (rollData) {
// Spécificité armes naturelle avec gantelet
if (rollData?.arme?.system.specificites?.poing?.hasSpec && this.items.find(item => item.type == "armure" && item.name.toLowerCase() == "gantelet" && item.system.equipe)) {
additionalBonus += 1
rollData.gantelet = true
}
if (rollData.isChargeAPied) {
additionalBonus += this.getCompetenceScore("course")
} else if (rollData.isChargeACheval) {
additionalBonus += this.getCompetenceScore("equitation")
}
}
return base + additionalBonus
}
/* -------------------------------------------- */
getNbArmures() {
return game.system.tedeum.config.MAX_ARMURES_LOURDES[this.system.caracteristiques.puissance.value]
}
@@ -266,41 +307,105 @@ export class TeDeumActor extends Actor {
modTotal += blessDef.modifier
}
// Si le nombre de blessures est supérieur au score d'endurance, alors malus supplémentaire
let endurance = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "endurance")
if (blessures.length > endurance.system.score) {
let enduranceScore = this.getCompetenceScore("endurance")
if (blessures.length > enduranceScore) {
modTotal += -1
}
return modTotal
}
/* -------------------------------------------- */
async appliquerBlessure(blessureId, locId, comment = "") {
let blessure = game.system.tedeum.config.blessures[blessureId]
if (!blessure) {
ui.notifications.warn("Type de blessure inconnu : " + blessureId)
console.error("Type de blessure inconnu : " + blessureId)
return
}
// Create a new blessure object
let blessureObj = {
name: blessure.label,
type: "blessure",
system: {
typeBlessure: blessureId,
localisation: locId || "maindroite",
value: blessure.value,
appliquee: true,
description: comment,
}
}
this.createEmbeddedDocuments('Item', [blessureObj]);
}
/* -------------------------------------------- */
getArmorDegatsModifier(rollData, combat) {
let loc = combat[rollData.loc.id]
// Sans armure
if (loc.armures.length == 0) {
return rollData.arme.system.degatsArmure.sansarmure
}
// Avec armure de cuir
if (loc.armures.find(a => a.system.typeArmure == "cuir")) {
return rollData.arme.system.degatsArmure.cuir
}
// Avec armure de maille
if (loc.armures.find(a => a.system.typeArmure == "maille")) {
return rollData.arme.system.degatsArmure.mailles
}
// Avec armure de plate
if (loc.armures.find(a => a.system.typeArmure == "plate")) {
return rollData.arme.system.degatsArmure.plates
}
return 0
}
/* -------------------------------------------- */
async appliquerDegats(rollData) {
let combat = this.prepareCombat()
rollData.defenderName = this.name
let touche = combat[rollData.loc.id].touche
let armorDegatModifier = this.getArmorDegatsModifier(rollData, combat)
rollData.degats += armorDegatModifier
rollData.armorDegatModifier = armorDegatModifier
let blessureId = "indemne"
if (rollData.degats > 0 && rollData.degats > touche) {
let diff = rollData.degats - touche
for (let bId in game.system.tedeum.config.blessures) {
let blessure = game.system.tedeum.config.blessures[bId]
if (diff >= blessure.degatsMin && diff <= blessure.degatsMax) {
// Create a new blessure object
let blessureObj = {
name: blessure.label,
type: "blessure",
system: {
typeBlessure: bId,
localisation: rollData.loc.id,
appliquee: true,
description: "Blessure infligée par un coup de " + rollData.arme.name + " de " + rollData.alias,
}
if (rollData.isReussiteCritique) {
bId = game.system.tedeum.config.blessuresOrder[blessure.value + 1]
}
rollData.blessure = blessureObj
this.createEmbeddedDocuments('Item', [blessureObj]);
blessureId = bId
break
}
}
}
if (rollData.isReussiteCritique && blessureId == "indemne") { // Critical success without degats => lightest blessure
blessureId = "estafilade"
}
console.log("Appliquer dégats", rollData, combat, blessureId)
if (blessureId != "indemne") {
let blessure = game.system.tedeum.config.blessures[blessureId]
// Create a new blessure object
let blessureObj = {
name: blessure.label,
type: "blessure",
system: {
typeBlessure: blessureId,
localisation: rollData.loc.id,
value: blessure.value,
appliquee: true,
description: "Blessure infligée par un coup de " + rollData.arme.name + " de " + rollData.alias,
}
}
rollData.blessure = blessureObj
rollData.touche = touche
this.createEmbeddedDocuments('Item', [blessureObj]);
}
// Display the relevant chat message
let msg = await TeDeumUtility.createChatWithRollMode(rollData.alias, {
content: await renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-blessure-result.hbs`, rollData)
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-blessure-result.hbs`, rollData)
})
await msg.setFlag("world", "te-deum-rolldata", rollData)
}
@@ -334,7 +439,7 @@ export class TeDeumActor extends Actor {
let providence = foundry.utils.deepClone(this.system.providence)
providence.name = "Providence"
if (this.system.genre.toLowerCase() == "homme") {
providence.qualite = game.system.tedeum.config.providence[providence.value].labelH
providence.qualite = game.system.tedeum.config.providence[providence.value].labelM
} else {
providence.qualite = game.system.tedeum.config.providence[providence.value].labelF
}
@@ -382,6 +487,7 @@ export class TeDeumActor extends Actor {
xp = Math.max(xp + value, 0)
await this.update({ [`system.caracteristiques.${key}.experience`]: xp })
this.sheet?.render(true)
ui.notifications.info(`+${value} XP en ${game.system.tedeum.config.caracteristiques[key].label}`)
}
/* -------------------------------------------- */
@@ -454,7 +560,7 @@ export class TeDeumActor extends Actor {
flag = armure.system.superposableCuir
}
if (item.system.typeArmure == "maille") {
flag = armure.system.superposableMaille
flag = armure.system.superposableMaille
}
if (item.system.typeArmure == "plate") {
flag = armure.system.superposablePlate
@@ -529,12 +635,16 @@ export class TeDeumActor extends Actor {
/* -------------------------------------------- */
getInitiativeScore() {
let initiative = this.items.find(it => it.type == "competence" && it.name.toLowerCase() == "initiative")
if (initiative) {
return initiative.system.score
let initiative = this.getInitiativeValue()
// Vérifie les armes avec bonus d'initiative
let armes = this.getArmes()
for (let arme of armes) {
if (arme.system.equipe && Number(arme.system.initiativeBonus) && Number(arme.system.initiativeBonus) != 0) {
ui.notifications.info("L'arme " + arme.name + " vous confère un bonus d'initiative de " + arme.system.initiativeBonus)
initiative += arme.system.initiativeBonus
}
}
ui.notifications.warn("Impossible de trouver la compétence Initiative pour l'acteur " + this.name)
return -1;
return initiative
}
/* -------------------------------------------- */
@@ -603,13 +713,13 @@ export class TeDeumActor extends Actor {
async rollDegatsArme(armeId) {
let weapon = this.items.get(armeId)
if (weapon) {
let bDegats = 0
if ( weapon.system.typeArme == "melee" ) {
let bDegats = { value: 0 }
if (weapon.system.typeArme == "melee") {
bDegats = this.getBonusDegats()
}
let formula = weapon.system.degats + "+" + bDegats.value
let degatsRoll = await new Roll(formula).roll()
await TeDeumUtility.showDiceSoNice(degatsRoll, game.settings.get("core", "rollMode") )
await TeDeumUtility.showDiceSoNice(degatsRoll, game.settings.get("core", "rollMode"))
let rollData = this.getCommonRollData()
rollData.mode = "degats"
rollData.formula = formula
@@ -618,7 +728,7 @@ export class TeDeumActor extends Actor {
rollData.degats = degatsRoll.total
let msg = await TeDeumUtility.createChatWithRollMode(rollData.alias, {
content: await renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-degats-result.hbs`, rollData)
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-degats-result.hbs`, rollData)
})
await msg.setFlag("world", "te-deum-rolldata", rollData)
console.log("Rolldata result", rollData)
@@ -654,9 +764,14 @@ export class TeDeumActor extends Actor {
let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == compName.toLowerCase())
if (competence) {
rollData.competence = competence
rollData.compScore = rollData.competence.system.isBase ? this.system.caracteristiques[rollData.competence.system.caracteristique].value : rollData.competence.system.score
let c = foundry.utils.duplicate(this.system.caracteristiques[competence.system.caracteristique])
this.updateCarac(c, competence.system.caracteristique)
rollData.carac = c
rollData.allongeLabel = game.system.tedeum.config.armeAllonges[weapon.system.allonge].label
rollData.allongeId = "courte"
rollData.allonges = foundry.utils.duplicate(game.system.tedeum.config.allonges[weapon.system.allonge])
} else {
ui.notifications.warn("Impossible de trouver la compétence " + compName)
return

View File

@@ -6,13 +6,14 @@ export class TeDeumCharacterCreator {
async init() {
this.stages = {}
this.currentStage = "origineSociale"
this.sex = undefined
this.sexe = undefined
this.origineSociale = undefined
this.religion = undefined
this.caracBonus = {}
this.competenceBonus = {}
this.suiviReponses = []
this.competences = TeDeumUtility.getCompetencesForDropDown()
this.choiceSummary = {}
for (let k in game.system.tedeum.config.caracteristiques) {
this.caracBonus[k] = { value: 0 }
@@ -39,6 +40,7 @@ export class TeDeumCharacterCreator {
} else {
this.competenceBonus[compName].value += 1
}
this.choiceSummary[this.currentStage].competences[compName] = 1
}
/*--------------------------------------------*/
@@ -116,6 +118,7 @@ export class TeDeumCharacterCreator {
/*--------------------------------------------*/
async askQuestionnaire(stage, context) {
context.subtitle = "Questionnaire"
this.choiceSummary[this.currentStage].questionnaire = {}
for (let key in stage.system.questionnaire) {
let question = stage.system.questionnaire[key]
@@ -170,13 +173,14 @@ export class TeDeumCharacterCreator {
let compName = context.competences[context.responseKey] || selectedResponse.compName
this.increaseCompetence(compName)
this.suiviReponses.push({ etape: stage.name, question: question.question, reponse: selectedResponse.reponse, compName: compName })
this.suiviReponses.push({ key: this.currentStage, etape: stage.name, question: question.question, reponse: selectedResponse.reponse, compName: compName })
}
}
/*------------- -------------------------------*/
async askCompetences(stage, context) {
context.subtitle = "Choix des Compétences"
this.choiceSummary[this.currentStage].competences = {}
context.fixedCompetences = {}
context.selectCompetences = {}
@@ -273,6 +277,10 @@ export class TeDeumCharacterCreator {
/*------------- -------------------------------*/
async askCarac(stage, context) {
context.subtitle = "Choix des Caractéristiques"
this.choiceSummary[this.currentStage] = {
caracBonus : {},
competences : {}
}
let selected = []
for (let i = 0; i < stage.system.nbChoixCarac; i++) {
@@ -312,6 +320,7 @@ export class TeDeumCharacterCreator {
}
this.caracBonus[choiceResult.carac].value += 1
selected.push(choiceResult.carac)
this.choiceSummary[this.currentStage].caracBonus[choiceResult.carac] = 1
}
}
@@ -360,6 +369,12 @@ export class TeDeumCharacterCreator {
for (let key in this.origineSociale.caracteristiques) {
this.caracBonus[key].value += this.origineSociale.caracteristiques[key]
}
this.choiceSummary['origineSociale'] = {
sexe: this.sexe,
religion: this.religion,
origineSociale: this.origineSociale.label,
caracBonus: this.caracBonus,
}
this.currentStage = "pouponniere"
}
@@ -388,6 +403,7 @@ export class TeDeumCharacterCreator {
this.pouponniere = foundry.utils.duplicate(stage.items.find(item => item.id === choiceResult.selectedItem))
context.title = `La Pouponnière - ${this.pouponniere.name}`
TeDeumUtility.prepareEducationContent(this.pouponniere);
this.choiceSummary['pouponniere'] = {}
context.label = "Valider l'augmentation de caracteristique"
await this.askCarac(this.pouponniere, context)
@@ -581,8 +597,36 @@ export class TeDeumCharacterCreator {
await actor.update({ [`system.fortune.${this.origineSociale.cagnotteUnit}`]: newArgent})
let histoire = ""
for (let reponse of this.suiviReponses) {
histoire += `<p>${reponse.question}<br>${reponse.reponse} (${reponse.compName})</p>`
for ( let key in this.choiceSummary) {
let stageSummary = this.choiceSummary[key]
if (stageSummary.sexe) {
histoire += `<h3>Origine Sociale</h3>`
histoire += `<p>${stageSummary.sexe} - ${stageSummary.religion} - ${stageSummary.origineSociale}</p>`
} else {
histoire += `<h3>${game.system.tedeum.config.etapesEducation[key].label}</h3>`
}
if (stageSummary.caracBonus) {
histoire += `<p><strong>Caractéristiques : </strong><ul>`
for (let caracKey in stageSummary.caracBonus) {
histoire += `<li>${TeDeumUtility.upperFirst(caracKey)} +1</li>`
}
histoire += `</ul></p>`
}
if (stageSummary.competences) {
histoire += `<p><strong>Compétences : </strong><ul>`
for (let compName in stageSummary.competences) {
histoire += `<li>${TeDeumUtility.upperFirst(compName)} +1</li>`
}
histoire += `</ul></p>`
}
let questions = this.suiviReponses.filter( r => r.key === key)
if (questions.length > 0) {
histoire += `<p><strong>Réponses au questionnaire : </strong><ul>`
for (let question of questions) {
histoire += `<li>${question.question} : <i>${question.reponse}</i> (${TeDeumUtility.upperFirst(question.compName)}+1)</li>`
}
histoire += `</ul></p>`
}
}
await actor.update({ "system.histoire": histoire})
actor.render(true)

View File

@@ -2,20 +2,44 @@ import { TeDeumUtility } from "../common/tedeum-utility.js";
/* -------------------------------------------- */
export class TeDeumCombat extends Combat {
/* -------------------------------------------- */
async rollInitiative(ids, formula = undefined, messageOptions = {} ) {
async rollInitiative(ids, formula = undefined, messageOptions = {}) {
//console.log("Roll INIT !")
ids = typeof ids === "string" ? [ids] : ids;
for (let cId of ids) {
const c = this.combatants.get(cId);
let initBonus = c.actor ? c.actor.getInitiativeScore( this.id, cId ) : -1;
await this.updateEmbeddedDocuments("Combatant", [ { _id: cId, initiative: initBonus } ]);
let initBonus = c.actor ? c.actor.getInitiativeScore(this.id, cId) : -1;
console.log("Init Bonus : ", c.name, initBonus)
await this.updateEmbeddedDocuments("Combatant", [{ _id: cId, initiative: initBonus }]);
}
return this;
}
/* -------------------------------------------- */
async modifyAction(combatantId, delta, isMainGauche = false) {
let combatant = this.combatants.get(combatantId)
if (!combatant) return;
let ca = combatant.getFlag("world", "available-actions")
if (!ca) {
ca = { nbActions: 1, nbActionsMainGauche: 0 }
}
if (isMainGauche) {
ca.nbActionsMainGauche += delta
} else {
ca.nbActions += delta
}
if (ca.nbActionsMainGauche < 0) ca.nbActionsMainGauche = 0
if (ca.nbActions < 0) ca.nbActions = 0
console.log("Modify Action : ", combatant.name, ca)
if (game.user.isGM) {
await TeDeumUtility.updateCombatantActions(combatant, ca)
} else {
game.socket.emit("system.fvtt-te-deum", { msg: "msg_modify_combat_action", data: { combatantId: combatantId, ca: ca } })
}
}
/* -------------------------------------------- */
static async checkTurnPosition() {
while (game.combat.turn > 0) {

View File

@@ -4,30 +4,46 @@ export const SYSTEM_ID = "fvtt-te-deum";
export const TEDEUM_CONFIG = {
BONUS_DEGATS: [{}, { label: "1d4", value: -2 }, { label: "1d6", value: -1 }, { label: "1d8", value: 0 },
{ label: "1d10", value: 1 }, { label: "1d12", value: 2 }, { label: "1d20", value: 3 }],
{ label: "1d10", value: 1 }, { label: "1d12", value: 2 }, { label: "1d20", value: 3 }],
MAX_ARMURES_LOURDES: [{}, { value: 1 }, { value: 3 }, { value: 5 },
{ value: 7 }, { value: 9 }, { value: 11 }],
{ value: 7 }, { value: 9 }, { value: 11 }],
ACTIONS_PAR_TOUR: [{}, { value: 1 }, { value: 2 }, { value: 2 },
{ value: 3 }, { value: 3 }, { value: 4 }],
{ value: 3 }, { value: 3 }, { value: 4 }],
COMMON_VALUE: [{}, { value: 1 }, { value: 2 }, { value: 3 },
{ value: 4 }, { value: 5 }, { value: 6 }],
{ value: 4 }, { value: 5 }, { value: 6 }],
COUT_XP: [{}, { value: 10 }, { value: 10 }, { value: 10 },
{ value: 10 }, { value: 30 }, { value: 50 }],
{ value: 10 }, { value: 30 }, { value: 50 }],
LOCALISATION: {
"pieddroit": { label: "Pied Droit", value: 1, locMod: 0, id: "pieddroit", nbArmure: 1, score: { min: 1, max: 1 }, coord: { top: 500, left: 0 } },
"jambedroite": { label: "Jambe Droite", value: 1, locMod: -1, id: "jambedroite", nbArmure: 1, score: { min: 3, max: 4 }, coord: { top: 400, left: 100 } },
"jambegauche": { label: "Jambe Gauche", value: 1, locMod: -1, id: "jambegauche", nbArmure: 1, score: { min: 5, max: 6 }, coord: { top: 400, left: 300 } },
"piedgauche": { label: "Pied Gauche", value: 1, locMod: 0, id: "piedgauche", nbArmure: 1, score: { min: 2, max: 2 }, coord: { top: 500, left: 400 } },
"maindroite": { label: "Main Droite", value: 1, locMod: 0, id: "maindroite", nbArmure: 1, score: { min: 7, max: 7 }, coord: { top: 0, left: 0 } },
"maingauche": { label: "Main Gauche", value: 1, locMod: 0, id: "maingauche", nbArmure: 1, score: { min: 8, max: 8 }, coord: { top: 0, left: 400 } },
"brasdroit": { label: "Bras Droit", value: 1, locMod: -1, id: "brasdroit", nbArmure: 2, score: { min: 9, max: 10 }, coord: { top: 200, left: 0 } },
"brasgauche": { label: "Bras Gauche", value: 1, locMod: -1, id: "brasgauche", nbArmure: 2, score: { min: 11, max: 12 }, coord: { top: 200, left: 400 } },
"corps": { label: "Corps", value: 1, id: "corps", locMod: -2, nbArmure: 2, score: { min: 13, max: 17 }, coord: { top: 200, left: 200 } },
"tete": { label: "Tête", value: 1, id: "tete", locMod: -2, nbArmure: 2, score: { min: 18, max: 20 }, coord: { top: 0, left: 200 } },
"pieddroit": { label: "Pied Droit", value: 1, locMod: 0, id: "pieddroit", categorie: "pied", nbArmure: 1, score: { min: 1, max: 1 }, coord: { top: 500, left: 0 } },
"jambedroite": { label: "Jambe Droite", value: 1, locMod: -1, id: "jambedroite", categorie: "jambe", nbArmure: 1, score: { min: 3, max: 4 }, coord: { top: 400, left: 100 } },
"jambegauche": { label: "Jambe Gauche", value: 1, locMod: -1, id: "jambegauche", categorie: "jambe", nbArmure: 1, score: { min: 5, max: 6 }, coord: { top: 400, left: 300 } },
"piedgauche": { label: "Pied Gauche", value: 1, locMod: 0, id: "piedgauche", categorie: "pied", nbArmure: 1, score: { min: 2, max: 2 }, coord: { top: 500, left: 400 } },
"maindroite": { label: "Main Droite", value: 1, locMod: 0, id: "maindroite", categorie: "main", nbArmure: 1, score: { min: 7, max: 7 }, coord: { top: 0, left: 0 } },
"maingauche": { label: "Main Gauche", value: 1, locMod: 0, id: "maingauche", categorie: "main", nbArmure: 1, score: { min: 8, max: 8 }, coord: { top: 0, left: 400 } },
"brasdroit": { label: "Bras Droit", value: 1, locMod: -1, id: "brasdroit", categorie: "bras", nbArmure: 2, score: { min: 9, max: 10 }, coord: { top: 200, left: 0 } },
"brasgauche": { label: "Bras Gauche", value: 1, locMod: -1, id: "brasgauche", categorie: "bras", nbArmure: 2, score: { min: 11, max: 12 }, coord: { top: 200, left: 400 } },
"corps": { label: "Corps", value: 1, id: "corps", categorie: "corps", locMod: -2, nbArmure: 2, score: { min: 13, max: 17 }, coord: { top: 200, left: 200 } },
"tete": { label: "Tête", value: 1, id: "tete", categorie: "tete", locMod: -2, nbArmure: 2, score: { min: 18, max: 20 }, coord: { top: 0, left: 200 } },
},
ATTAQUE_CIBLEES: {
"aucune": { label: "Aucune", id: "aucune", locMod: 0, description: "Attaque non ciblée" },
"pieddroit": { label: "Pied Droit", id: "pieddroit", locMod: 0, description: "Attaque ciblée sur le pied droit" },
"jambedroite": { label: "Jambe Droite", id: "jambedroite", locMod: -1, description: "Attaque ciblée sur la jambe droite" },
"jambegauche": { label: "Jambe Gauche", id: "jambegauche", locMod: -1, description: "Attaque ciblée sur la jambe gauche" },
"piedgauche": { label: "Pied Gauche", id: "piedgauche", locMod: 0, description: "Attaque ciblée sur le pied gauche" },
"maindroite": { label: "Main Droite", id: "maindroite", locMod: 0, description: "Attaque ciblée sur la main droite" },
"maingauche": { label: "Main Gauche", id: "maingauche", locMod: 0, description: "Attaque ciblée sur la main gauche" },
"brasdroit": { label: "Bras Droit", id: "brasdroit", locMod: -1, description: "Attaque ciblée sur le bras droit" },
"brasgauche": { label: "Bras Gauche", id: "brasgauche", locMod: -1, description: "Attaque ciblée sur le bras gauche" },
"corps": { label: "Corps", id: "corps", locMod: -2, description: "Attaque ciblée sur le corps" },
"tete": { label: "Tête", id: "tete", locMod: -2, description: "Attaque ciblée sur la tête" },
},
ARME_SPECIFICITE: {
"poing": { label: "Poings", id: "poing", melee: true, tir: false },
"pied": { label: "Pieds", id: "pied", melee: true, tir: false },
"encombrante": { label: "Encombrante", id: "encombrante", melee: true, tir: true },
"maintiendistance": { label: "Maintien à distance", id: "maintiendistance", melee: true, tir: false },
"coupassomant": { label: "Coup assomant", id: "coupassomant", melee: true, tir: false },
@@ -43,11 +59,11 @@ export const TEDEUM_CONFIG = {
},
ARME_PORTEES: {
"brulepourpoint": { label: "Brûle-pourpoint", difficulty: "facile", id: "brulepourpoint" },
"courte": { label: "Courte", difficulty: "pardefaut", id: "courte" },
"moyenne": { label: "Moyenne", difficulty: "difficile", id: "moyenne" },
"longue": { label: "Longue", difficulty: "perilleux", id: "longue" },
"extreme": { label: "Extrême", difficulty: "desespere", id: "extreme" },
"brulepourpoint": { label: "Brûle-pourpoint (5)", difficulty: "facile", id: "brulepourpoint" },
"courte": { label: "Courte (7)", difficulty: "pardefaut", id: "courte" },
"moyenne": { label: "Moyenne (11)", difficulty: "difficile", id: "moyenne" },
"longue": { label: "Longue (13)", difficulty: "perilleux", id: "longue" },
"extreme": { label: "Extrême (15)", difficulty: "desespere", id: "extreme" },
},
genre: {
@@ -94,7 +110,7 @@ export const TEDEUM_CONFIG = {
},
caracteristiques: {
savoir: { id: "savoir", value: "savoir", label: "Savoir", description:"Cette caractéristique correspond à la capacité d'abstraction intellectuelle ainsi qu'à la culture générale du personnage. Elle permet d'évaluer la compétence de base Mémoriser." },
savoir: { id: "savoir", value: "savoir", label: "Savoir", description: "Cette caractéristique correspond à la capacité d'abstraction intellectuelle ainsi qu'à la culture générale du personnage. Elle permet d'évaluer la compétence de base Mémoriser." },
sensibilite: { id: "sensibilite", value: "sensibilite", label: "Sensibilité", description: "Cette caractéristique correspond à l'ouverture du personnage sur le monde. Elle englobe l'altruisme, la spiritualité et la créativité du personnage. Elle permet d'évaluer la compétence de base Perception." },
entregent: { id: "entregent", value: "entregent", label: "Entregent", description: "Cette caractéristique correspond à l'ensemble des prédispositions sociales du personnage. Elle englobe le charisme et le respect des usages. Elle permet d'évaluer la compétence de base Charme." },
complexion: { id: "complexion", value: "complexion", label: "Complexion", description: "Cette caractéristique permet d'évaluer la santé et la résistance physique du per- sonnage. Elle permet de calculer la com- pétence de base Endurance, capitale dans la résolution des blessures, la résistance à la douleur, au poison et aux maladies." },
@@ -102,10 +118,10 @@ export const TEDEUM_CONFIG = {
adresse: { id: "adresse", value: "adresse", label: "Adresse", description: "Cette caractéristique correspond à la rapidité et la dextérité du personnage. Elle livre le nombre d'actions qu'un personnage peut accomplir en un tour de combat et permet d'évaluer les compétences de base Initiative & Course." },
},
allonges: {
courte: { courte: { malus: 0 }, moyenne: { malus: -1 }, longue: { malus: -2 }, treslongue: { malus: 0, esquive: 2 } },
moyenne: { courte: { malus: 0 }, moyenne: { malus: 0 }, longue: { malus: -1 }, treslongue: { malus: 0, esquive: 2 } },
longue: { courte: { malus: -2 }, moyenne: { malus: -1 }, longue: { malus: 0 }, treslongue: { malus: -1, esquive: 1 } },
treslongue: { courte: { malus: 0, esquive: 2 }, moyenne: { malus: 0, esquive: 2 }, longue: { malus: 0, esquive: 1 }, treslongue: { malus: 0 } },
courte: { courte: { label: "Courte (0)", malus: 0 }, moyenne: { label: "Moyenne (-1)", malus: -1 }, longue: { label: "Longue (-2)", malus: -2 }, treslongue: { label: "Très longue (0, 2 Esquives)", malus: 0, esquive: 2 } },
moyenne: { courte: { label: "Courte (0)", malus: 0 }, moyenne: { label: "Moyenne (0)", malus: 0 }, longue: { label: "Longue (-1)", malus: -1 }, treslongue: { label: "Très longue (0, 2 Esquives)", malus: 0, esquive: 2 } },
longue: { courte: { label: "Courte (-2)", malus: -2 }, moyenne: { label: "Moyenne (-1)", malus: -1 }, longue: { label: "Longue (0)", malus: 0 }, treslongue: { label: "Très longue (-1, 2 Esquives)", malus: -1, esquive: 1 } },
treslongue: { courte: { label: "Courte (0, 2 Esquives)", malus: 0, esquive: 2 }, moyenne: { label: "Moyenne (0, 2 Esquives)", malus: 0, esquive: 2 }, longue: { label: "Longue (0, 1 Esquive)", malus: 0, esquive: 1 }, treslongue: { label: "Très longue (0)", malus: 0 } },
},
providence: [
{ labelM: "Brebis égarée", labelF: "Brebis égarée", value: 0, diceValue: "0" },
@@ -152,13 +168,13 @@ export const TEDEUM_CONFIG = {
},
difficulte: {
aucune: { label: "Aucune", key: "aucune", value: 0 },
routine: { label: "Routine", key: "routine", value: 3 },
facile: { label: "Facile", key: "facile", value: 5 },
pardefaut: { label: "Par Défaut", key: "pardefaut", value: 7 },
malaise: { label: "Malaisé", key: "malaise", value: 9 },
difficile: { label: "Difficile", key: "difficile", value: 11 },
perilleux: { label: "Perilleux", key: "perilleux", value: 13 },
desespere: { label: "Désespéré", key: "desespere", value: 15 }
routine: { label: "Routine (3)", key: "routine", value: 3 },
facile: { label: "Facile (5)", key: "facile", value: 5 },
pardefaut: { label: "Par Défaut (7)", key: "pardefaut", value: 7 },
malaise: { label: "Malaisé (9)", key: "malaise", value: 9 },
difficile: { label: "Difficile (11)", key: "difficile", value: 11 },
perilleux: { label: "Perilleux (13)", key: "perilleux", value: 13 },
desespere: { label: "Désespéré (15)", key: "desespere", value: 15 }
},
monnaie: {
denier: { label: "Deniers", id: "denier", value: 1 },
@@ -195,13 +211,14 @@ export const TEDEUM_CONFIG = {
{ value: "1", label: "+1 niveau" },
{ value: "2", label: "+2 niveaux" }
],
blessuresOrder: ["indemne", "estafilade", "plaie", "plaiebeante", "plaieatroce", "tuenet", "tuenet", "tuenet", "tuenet", "tuenet"],
blessures: {
indemne: { value: 0, label: "Indemne", key: "indemne", degatsMax: -1, count: 0, modifier: 0 },
estafilade: { value: 1, label: "Estafilade", key: "estafilade", degatsMin: 0, degatsMax: 2, count: 1, modifier: 0 },
plaie: { value: 2, label: "Plaie", key: "plaie", degatsMin: 3, degatsMax: 4, count: 1, modifier: -1 },
plaiebeante: { value: 3, label: "Plaie béante", key: "plaiebeante", degatsMin: 5, degatsMax: 6, count: 1, modifier: -2 },
plaieatroce: { value: 4, label: "Plaie atroce", key: "plaieatroce", degatsMin: 7, degatsMax: 8, count: 1, horsCombat: true, modifier: -12 },
tunenet: { value: 5, label: "Tué net", key: "tuenet", degatsMin: 9, degatsMax: 100, count: 1, horsCombat: true, mort: true, modifier: -12 }
tuenet: { value: 5, label: "Tué net", key: "tuenet", degatsMin: 9, degatsMax: 100, count: 1, horsCombat: true, mort: true, modifier: -100 }
},
virulence: {
aucune: { label: "Aucune", value: "aucune", modifier: 0 },

View File

@@ -1,6 +1,8 @@
/* -------------------------------------------- */
/* -------------------------------------------- */
const ECRYME_WELCOME_MESSAGE_URL = "https://www.uberwald.me/gitea/public/fvtt-te-deum/raw/branch/main/welcome-message-tedeum.html"
export class TeDeumUtility {
/* -------------------------------------------- */
@@ -12,13 +14,19 @@ export class TeDeumUtility {
CONFIG.JournalEntry.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp"
CONFIG.Macro.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp"
CONFIG.Adventure.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp"
}
Hooks.on('renderChatLog', (log, html, data) => TeDeumUtility.chatListeners(html));
static installHooks() {
Hooks.on('renderChatMessageHTML', (message, html) => {
TeDeumUtility.chatListeners(html);
TeDeumUtility.onRenderChatMessage(message, html);
});
Hooks.on("renderActorDirectory", (app, html, data) => {
if (game.user.can('ACTOR_CREATE')) {
const button = document.createElement('button');
button.style.width = '90%';
button.style.width = '60%';
button.classList.add('tedeum-create-character');
button.innerHTML = 'Créer un Personnage'
button.addEventListener('click', () => {
let cr = new game.system.tedeum.TeDeumCharacterCreator();
@@ -27,7 +35,47 @@ export class TeDeumUtility {
$(html).find('.header-actions').after(button)
}
})
//Hooks.on("getChatLogEntryContext", (html, options) => TeDeumUtility.chatMenuManager(html, options));
Hooks.on("combatStart", async (combat, updateData, options) => {
this.resetCombatActions(combat)
});
Hooks.on("combatRound", (combat, updateData, updateOptions) => {
// List all actors related to combatant
if (game.user.isGM) {
this.resetCombatActions(combat)
}
})
Hooks.on("getCombatTrackerContextOptions", (html, options) => {
console.log("Get Combat Tracker Context", html, options)
this.pushCombatOptions(html, options);
});
}
/* -------------------------------------------- */
static pushCombatOptions(html, options) {
options.push({ name: "Actions +1", condition: true, icon: '<i class="fas fa-plus"></i>', callback: target => { game.combat.modifyAction($(target).data('combatant-id'), 1); } })
options.push({ name: "Actions -1", condition: true, icon: '<i class="fas fa-minus"></i>', callback: target => { game.combat.modifyAction($(target).data('combatant-id'), -1); } })
options.push({ name: "Actions MG +1", condition: true, icon: '<i class="fas fa-plus"></i>', callback: target => { game.combat.modifyAction($(target).data('combatant-id'), 1, true); } })
options.push({ name: "Actions MG -1", condition: true, icon: '<i class="fas fa-minus"></i>', callback: target => { game.combat.modifyAction($(target).data('combatant-id'), -1, true); } })
}
/* -------------------------------------------- */
static async resetCombatActions(combat) {
if (game.user.isGM) {
for (let c of combat.combatants) {
let actor = game.actors.get(c.actorId)
if (actor) {
let nbActions = actor.getNbActions()?.value || 0
let isMainGauche = (actor.getCompetenceScore("Main gauche") > 0)
let nbActionsMainGauche = isMainGauche ? nbActions : 0
await c.setFlag("world", "available-actions", { nbActions, nbActionsMainGauche })
await c.update({ name: `${c.token.name} (${nbActions} / ${nbActionsMainGauche})` })
}
}
}
}
/* -------------------------------------------- */
@@ -126,14 +174,24 @@ export class TeDeumUtility {
/* -------------------------------------------- */
static welcomeMessage() {
if (game.user.isGM) {
ChatMessage.create({
user: game.user.id,
whisper: [game.user.id],
content: `<div id="chat-welcome welcome-message-tedeum"><span class="rdd-roll-part">
<strong>Bienvenu dans Te Deum Pour Un Massacre !</strong>
<div class="chat-welcome">Ce système vous est proposé par Open Sesame Games.<br>
Vous trouverez de l'aide dans @UUID[Compendium.fvtt-te-deum.aides.JournalEntry.uNwJgi4kXBCiZmAH]{Aide pour Te Deum}<br>
ainsi que sur le Discord de Foundry FR : https://discord.gg/pPSDNJk</div>` });
// Try to fetch the welcome message from the github repo "welcome-message-ecryme.html"
fetch(ECRYME_WELCOME_MESSAGE_URL)
.then(response => response.text())
.then(html => {
ChatMessage.create({
user: game.user.id,
whisper: [game.user.id],
content: html
});
})
.catch(error => {
console.error("Error fetching welcome message:", error);
ChatMessage.create({
user: game.user.id,
whisper: [game.user.id],
content: "<b>Bienvenue dans Ecryme RPG !</b><br>Visitez le site officiel pour plus d'informations."
});
});
}
}
@@ -200,7 +258,7 @@ export class TeDeumUtility {
return actor
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/* -------------------------------------------- */
static async manageOpposition(rollData) {
if (!this.currentOpposition) {
// Store rollData as current GM opposition
@@ -209,39 +267,76 @@ export class TeDeumUtility {
} else {
// Perform the opposition
let isAttackWinner = true
let rWinner = this.currentOpposition
let rLooser = rollData
if (rWinner.total < rLooser.total) {
rWinner = rollData
rLooser = this.currentOpposition
let rWinner, rLooser
if (this.currentOpposition.total <= rollData.total) {
rWinner = foundry.utils.duplicate(rollData)
rLooser = foundry.utils.duplicate(this.currentOpposition)
isAttackWinner = false
} else {
rWinner = foundry.utils.duplicate(this.currentOpposition)
rLooser = foundry.utils.duplicate(rollData)
isAttackWinner = true
}
this.currentOpposition = undefined // Reset opposition
let oppositionData = {
winner: rWinner,
looser: rLooser
}
// Update difficulty
rWinner.difficulty = rLooser.total
rLooser.difficulty = rWinner.total
await this.computeResults(rWinner)
await this.computeResults(rLooser)
// Auto XP management when opposed
if (rWinner.isReussiteCritique) {
let actor = this.getActorFromRollData(rWinner)
actor.modifyXP(rWinner.carac.key, 1)
}
if (rLooser.isEchecCritique) {
let actor = this.getActorFromRollData(rLooser)
actor.modifyXP(rLooser.carac.key, 1)
}
let msg = await this.createChatWithRollMode(rollData.alias, {
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-opposition-result.hbs`, oppositionData)
})
await msg.setFlag("world", "te-deum-rolldata", rollData)
// Si le gagnant est l'attaquant, appliquer les dégats sur la victime
if ( isAttackWinner && rWinner.isSuccess && rWinner.mode == "arme" && rWinner.arme?.system.typeArme == "melee" && rWinner.defenderTokenId) {
this.appliquerDegats(rWinner)
if (isAttackWinner && rWinner.isSuccess && rWinner.mode == "arme" && rWinner.arme?.system.typeArme == "melee" && rWinner.defenderTokenId) {
await this.appliquerDegats(rWinner)
}
console.log("Rolldata result", rollData)
console.log("Opposition result", rollData, isAttackWinner, oppositionData)
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/* -------------------------------------------- */
static getTokenActorFromId(tokenId) {
for (let scene of game.scenes) {
const tokenDoc = scene.tokens.get(tokenId)
if (tokenDoc) return tokenDoc.actor
}
return null
}
/* -------------------------------------------- */
static async appliquerDegats(rollData) {
await this.processAttaqueMelee(rollData)
let defenderToken = canvas.tokens.placeables.find(t => t.id == rollData.defenderTokenId)
if (defenderToken) {
let actor = defenderToken.actor
await actor.appliquerDegats(rollData)
let defenderActor = this.getTokenActorFromId(rollData.defenderTokenId)
if (defenderActor) {
if (game.user.isGM || defenderActor.isOwner) {
await defenderActor.appliquerDegats(rollData)
} else {
// Send a socket message — seul le premier MJ actif le traitera
game.socket.emit("system.fvtt-te-deum", { name: "msg_apply_damage", data: { rollData } });
}
// Attaque naturelle avec dégats inférieur à -2
if ((rollData?.arme?.system.specificites?.poing?.hasSpec || rollData?.arme?.system.specificites?.pied?.hasSpec) && rollData.degats < -2) {
let attacker = this.getActorFromRollData(rollData)
attacker.appliquerBlessure("estafilade", "maindroite", "Contusion suite à une attaque naturelle")
ui.notifications.info(`${attacker.name} subit 1 contusion en infligeant ${rollData.degats} dégâts à mains nues`)
}
} else {
ui.notifications.error("Impossible de trouver la cible de l'attaque, aucun degats appliqué")
}
@@ -266,6 +361,25 @@ export class TeDeumUtility {
TeDeumUtility.appliquerDegats(rollData, messageId)
}
})
$(html).on("click", '.chat-command-gain-xp', async event => {
let messageId = TeDeumUtility.findChatMessageId(event.currentTarget)
let message = game.messages.get(messageId)
let rollData = message.getFlag("world", "te-deum-rolldata")
if (rollData) {
let actor = TeDeumUtility.getActorFromRollData(rollData)
actor.modifyXP(rollData.carac.key, 1)
event.currentTarget.style.display = 'none'; // feedback immédiat local
await message.setFlag("world", "te-deum-xp-used", true) // sync tous les clients
}
})
}
/* -------------------------------------------- */
static onRenderChatMessage(message, html) {
if (message.getFlag("world", "te-deum-xp-used")) {
const btn = html.querySelector('.chat-command-gain-xp');
if (btn) btn.style.display = 'none';
}
}
/* -------------------------------------------- */
@@ -360,6 +474,28 @@ export class TeDeumUtility {
chatMsg.setFlag("world", "tedeum-rolldata", rollData)
}
}
if (msg.name == "msg_modify_combat_action") {
if (game.user.isGM) {
let { combatantId, ca } = msg.data
let combatant = game.combat.combatants.get(combatantId)
if (combatant) {
console.log("sock - Modify Combat Action : ", combatant.name, ca)
await TeDeumUtility.updateCombatantActions(combatant, ca)
}
}
}
if (msg.name == "msg_apply_damage") {
const firstGM = game.users.find(u => u.isGM && u.active)
if (game.user === firstGM) {
let rollData = msg.data.rollData
let defenderActor = TeDeumUtility.getTokenActorFromId(rollData.defenderTokenId)
if (defenderActor) {
await defenderActor.appliquerDegats(rollData)
} else {
ui.notifications.error("Impossible de trouver la cible de l'attaque, aucun degats appliqué")
}
}
}
}
/* -------------------------------------------- */
@@ -445,9 +581,11 @@ export class TeDeumUtility {
}
if (rollData.diceSum == 1) {
let critiqueRoll = await new Roll(rollData.carac.negativeDice)
rollData.isSuccess = false
await critiqueRoll.evaluate()
await this.showDiceSoNice(critiqueRoll, game.settings.get("core", "rollMode"))
rollData.critiqueRoll = foundry.utils.duplicate(critiqueRoll)
rollData.critiqueTotal = critiqueRoll.total
if (critiqueRoll.total > rollData.competence.system.score) {
rollData.isEchecCritique = true
}
@@ -476,6 +614,15 @@ export class TeDeumUtility {
if (rollData.isMouvement) {
localModifier -= 1
}
if (rollData.arme && rollData.allongeId) {
localModifier += rollData.allonges[rollData.allongeId].malus
rollData.allongeMalus = rollData.allonges[rollData.allongeId].malus
rollData.nbEsquives = rollData.allonges[rollData.allongeId]?.esquive || 0
}
if (rollData.attaqueCiblee && rollData.attaqueCiblee != "aucune") {
localModifier -= 1
rollData.loc = foundry.utils.duplicate(game.system.tedeum.config.LOCALISATION[rollData.attaqueCiblee])
}
let diceBase = this.modifyDice(rollData.carac.dice, localModifier + Number(rollData.bonusMalus) + rollData.santeModifier)
if (!diceBase) return;
diceFormula = diceBase + "x + " + rollData.compScore
@@ -488,24 +635,30 @@ export class TeDeumUtility {
/* -------------------------------------------- */
static async getLocalisation(rollData) {
let locRoll = await new Roll("1d20").roll()
await this.showDiceSoNice(locRoll, game.settings.get("core", "rollMode"))
rollData.locRoll = foundry.utils.duplicate(locRoll)
for (let key in game.system.tedeum.config.LOCALISATION) {
let loc = game.system.tedeum.config.LOCALISATION[key]
if (locRoll.total >= loc.score.min && locRoll.total <= loc.score.max) {
rollData.loc = foundry.utils.duplicate(loc)
break
let locRoll
if (rollData.loc) {
locRoll = await new Roll(String(rollData.loc.score.min)).roll()
} else {
locRoll = await new Roll("1d20").roll()
await this.showDiceSoNice(locRoll, game.settings.get("core", "rollMode"))
for (let key in game.system.tedeum.config.LOCALISATION) {
let loc = game.system.tedeum.config.LOCALISATION[key]
if (locRoll.total >= loc.score.min && locRoll.total <= loc.score.max) {
rollData.loc = foundry.utils.duplicate(loc)
break
}
}
}
rollData.locRoll = foundry.utils.duplicate(locRoll)
}
/* -------------------------------------------- */
static async processAttaqueMelee(rollData) {
await this.getLocalisation(rollData)
let actor = game.actors.get(rollData.actorId)
let bDegats = actor.getBonusDegats()
let degatsRoll = await new Roll(rollData.arme.system.degats + "+" + bDegats.value).roll()
let bDegats = actor.getAttaqueBonusDegats(rollData)
rollData.degatsFormula = rollData.arme.system.degats + "+" + bDegats
let degatsRoll = await new Roll(rollData.degatsFormula).roll()
await this.showDiceSoNice(degatsRoll, game.settings.get("core", "rollMode"))
rollData.degatsRoll = foundry.utils.duplicate(degatsRoll)
rollData.degats = degatsRoll.total
@@ -521,12 +674,51 @@ export class TeDeumUtility {
await this.getLocalisation(rollData)
// Now the degats
let degatsRoll = await new Roll(rollData.arme.system.degats).roll()
await this.showDiceSoNice(rollData.locRoll, game.settings.get("core", "rollMode"))
await this.showDiceSoNice(degatsRoll, game.settings.get("core", "rollMode"))
rollData.degatsRoll = foundry.utils.duplicate(degatsRoll)
rollData.degats = degatsRoll.total
}
}
/* -------------------------------------------- */
static async updateCombatantActions(combatant, ca) {
await combatant.setFlag("world", "available-actions", ca)
await combatant.update({ name: `${combatant.token.name} (${ca.nbActions} / ${ca.nbActionsMainGauche})` })
}
/* -------------------------------------------- */
static async manageCombatActions(actor, rollData) {
let combat = game.combats.active
if (!combat) return;
let combatant = combat.getCombatantByActor(actor)
if (!combatant) return;
let ca = combatant.getFlag("world", "available-actions")
if (!ca) return;
if (rollData.mode == "arme" && rollData.isMainGauche) {
if (ca.nbActionsMainGauche > 0) {
ca.nbActionsMainGauche -= 1
ca.nbActions = Math.max(ca.nbActions - 1, 0)
} else {
ui.notifications.error(`${actor.name} n'a plus d'actions disponibles à la main gauche pour ce round`)
}
}
if (ca.nbActions > 0) {
ca.nbActions -= 1
} else {
ui.notifications.error(`${actor.name} n'a plus d'actions disponibles pour ce round`)
}
console.log("Manage combat actions 1", actor.name, combatant)
if (game.user.isGM) {
await this.updateCombatantActions(combatant, ca)
} else {
// Send a socket message
game.socket.emit("system.fvtt-te-deum", { name: "msg_modify_combat_action", data: { combatantId: combatant.id, ca } });
}
rollData.hasActions = true
rollData.remainingActions = ca.nbActions
rollData.remainingActionsMainGauche = ca.nbActionsMainGauche
}
/* -------------------------------------------- */
static async rollTeDeum(rollData) {
@@ -536,9 +728,13 @@ export class TeDeumUtility {
rollData.difficulty = "pardefaut"
}
rollData.difficulty = game.system.tedeum.config.difficulte[rollData.difficulty].value
// Compute the real competence score
if ( rollData.competence ) {
if ( rollData.competence.system.isBase) {
if (rollData.competence) {
if (rollData.isMainGauche) {
rollData.competence = actor.getMeilleureCompetenceMainGauche(rollData.competence)
}
if (rollData.competence.system.isBase) {
rollData.compScore = actor.system.caracteristiques[rollData.competence.system.caracteristique].value
} else {
rollData.compScore = rollData.competence.system.score
@@ -560,6 +756,8 @@ export class TeDeumUtility {
await this.processAttaqueDistance(rollData)
await this.manageCombatActions(actor, rollData)
let msg = await this.createChatWithRollMode(rollData.alias, {
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-generic-result.hbs`, rollData)
})
@@ -570,10 +768,6 @@ export class TeDeumUtility {
if (rollData.enableProvidence) {
actor.modifyProvidence(-1)
}
// Manage XP
if (rollData.isReussiteCritique || rollData.isEchecCritique) {
actor.modifyXP(rollData.carac.key, 1)
}
}
/* -------------------------------------------- */

View File

@@ -1,17 +1,17 @@
export class TeDeumArmeSchema extends foundry.abstract.TypeDataModel {
export class TeDeumArmeSchema extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
const requiredInteger = { required: true, nullable: false, integer: true };
const requiredDouble = { required: true, nullable: false, integer: false };
const schema = {};
schema.typeArme = new fields.StringField({required: true, choices: ["melee", "tir"], initial: "melee"});
schema.allonge = new fields.StringField({required: true, choices: ["courte", "moyenne", "longue", "treslongue"], initial: "courte"});
schema.typeArme = new fields.StringField({ required: true, choices: ["melee", "tir"], initial: "melee" });
schema.allonge = new fields.StringField({ required: true, choices: ["courte", "moyenne", "longue", "treslongue"], initial: "courte" });
schema.specificites = new fields.SchemaField(
Object.values((game.system.tedeum.config.ARME_SPECIFICITE)).reduce((obj, spec) => {
obj[spec.id] = new fields.SchemaField({
hasSpec: new fields.BooleanField({initial: false}),
hasSpec: new fields.BooleanField({ initial: false }),
});
return obj;
}, {})
@@ -26,35 +26,35 @@ export class TeDeumArmeSchema extends foundry.abstract.TypeDataModel {
}, {})
);
schema.degatsArmure = new fields.SchemaField( {
sansarmure : new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
cuir : new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
plates : new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
mailles : new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
schema.degatsArmure = new fields.SchemaField({
sansarmure: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
cuir: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
plates: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
mailles: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
});
schema.tempsRecharge = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 });
schema.competenceRecharge = new fields.StringField({ required: false, choices:["aucune", "archerie", "arquebusade"], initial: "aucune", blank: true });
schema.competenceRecharge = new fields.StringField({ required: false, choices: ["aucune", "archerie", "arquebusade"], initial: "aucune", blank: true });
schema.valeurEchecCritique = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 });
schema.initiativeBonus = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 });
schema.initiativeBonus = new fields.NumberField({ ...requiredInteger, initial: 0 });
schema.degats = new fields.StringField({ required: false, blank: true, initial: "0" });
schema.degatscrosse = new fields.StringField({ required: false, blank: true, initial: "0" });
let comp = []
for (let key of Object.keys(game.system.tedeum.config.armeCompetences)) {
comp.push(key);
}
schema.competence = new fields.StringField({ required: true, choices:comp, initial: "bagarre" });
schema.competence2 = new fields.StringField({ required: false, choices:comp, initial: "", blank: true });
schema.competence = new fields.StringField({ required: true, choices: comp, initial: "bagarre" });
schema.competence2 = new fields.StringField({ required: false, choices: comp, initial: "", blank: true });
schema.prix = new fields.NumberField({ ...requiredDouble, initial: 0, min: 0 });
schema.monnaie = new fields.StringField({ required: true, blank: false, initial: "denier" });
schema.equipe = new fields.BooleanField({initial: false}),
schema.description = new fields.HTMLField({ required: true, blank: true });
schema.equipe = new fields.BooleanField({ initial: false }),
schema.description = new fields.HTMLField({ required: true, blank: true });
return schema;
}

View File

@@ -4,8 +4,9 @@ export class TeDeumBlessureSchema extends foundry.abstract.TypeDataModel {
const requiredInteger = { required: true, nullable: false, integer: true };
const schema = {};
schema.typeBlessure = new fields.StringField({required: true, choices: ["indemne", "estafilade", "plaie", "plaiebeante", "plaieatroce", "tuenet"], initial: "estafilade"});
schema.localisation = new fields.StringField({required: true, choices: ["piedgauche", "pieddroit", "jambegauche", "jambedroite", "maingauche", "maindroite", "brasgauche", "brasdroit", "tete", "corps"], initial: "corps"});
schema.typeBlessure = new fields.StringField({ required: true, choices: ["indemne", "estafilade", "plaie", "plaiebeante", "plaieatroce", "tuenet"], initial: "estafilade" });
schema.value = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
schema.localisation = new fields.StringField({ required: true, choices: ["piedgauche", "pieddroit", "jambegauche", "jambedroite", "maingauche", "maindroite", "brasgauche", "brasdroit", "tete", "corps"], initial: "corps" });
schema.description = new fields.HTMLField({ required: true, blank: true });

View File

@@ -14,7 +14,7 @@ export class TeDeumEducationSchema extends foundry.abstract.TypeDataModel {
return obj;
}, {})
);
schema.genre = new fields.StringField({required: true, initial: "Homme", choices: ["masculin", "mixte", "Homme", "Femme", "Mixte"]});
schema.nbChoixCarac = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 });
@@ -32,7 +32,7 @@ export class TeDeumEducationSchema extends foundry.abstract.TypeDataModel {
});
return comps;
}, {}));
schema.hasCompetencesOpt = new fields.BooleanField({initial: false})
schema.competencesOptNumber = new fields.NumberField({ ...requiredInteger, initial: 1, min:0 })
schema.competencesOpt = new fields.SchemaField(Array.fromRange(14, 1).reduce((comps, i) => {
@@ -51,7 +51,7 @@ export class TeDeumEducationSchema extends foundry.abstract.TypeDataModel {
reponse: new fields.StringField({ required: true, blank: true, initial: "" }),
compName: new fields.StringField({ required: true, blank: true, initial: "" }),
toSelect: new fields.BooleanField({ initial: false }),
compList: new fields.SchemaField(Array.fromRange(10, 1).reduce((comps, i) => {
compList: new fields.SchemaField(Array.fromRange(16, 1).reduce((comps, i) => {
comps[`comp${i}`] = new fields.SchemaField({
compName: new fields.StringField({ required: true, blank: true, initial: "" }),
});
@@ -63,7 +63,7 @@ export class TeDeumEducationSchema extends foundry.abstract.TypeDataModel {
});
return questions;
}, {}));
schema.debouches = new fields.SchemaField(Array.fromRange(24, 1).reduce((debouches, i) => {
debouches[`debouche${i}`] = new fields.SchemaField({
debouche: new fields.StringField({ required: true, blank: true, initial: "" })
@@ -73,7 +73,7 @@ export class TeDeumEducationSchema extends foundry.abstract.TypeDataModel {
schema.cagnotteMultiplier = new fields.NumberField({ ...requiredDouble, initial: 1.0, min: 0 });
schema.cagnotteDivider = new fields.NumberField({ ...requiredDouble, initial: 1.0, min: 0 });
schema.description = new fields.HTMLField({ required: true, blank: true });
schema.trousseau = new fields.StringField({ required: true, blank: true, initial: "" });

View File

@@ -6,7 +6,7 @@ export class TeDeumRollDialog extends Dialog {
static async create(actor, rollData) {
let options = { classes: ["tedeum-roll-dialog"], width: 540, height: 'fit-content', 'z-index': 99999 }
let html = await renderTemplate('systems/fvtt-te-deum/templates/dialogs/roll-dialog-generic.hbs', rollData);
let html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-te-deum/templates/dialogs/roll-dialog-generic.hbs', rollData);
return new TeDeumRollDialog(actor, rollData, html, options);
}
@@ -43,7 +43,7 @@ export class TeDeumRollDialog extends Dialog {
/* -------------------------------------------- */
async refreshDialog() {
const content = await renderTemplate("systems/fvtt-te-deum/templates/dialogs/roll-dialog-generic.hbs", this.rollData)
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/roll-dialog-generic.hbs", this.rollData)
this.data.content = content
this.render(true)
}
@@ -60,9 +60,18 @@ export class TeDeumRollDialog extends Dialog {
html.find('#bonusMalusPerso').change((event) => {
this.rollData.bonusMalusPerso = Number(event.currentTarget.value)
})
html.find('#roll-allonge').change((event) => {
this.rollData.allongeId = event.currentTarget.value
})
html.find('#roll-main-gauche').change((event) => {
this.rollData.isMainGauche = event.currentTarget.checked
})
html.find('#roll-difficulty').change((event) => {
this.rollData.difficulty = String(event.currentTarget.value) || "pardefaut"
})
html.find('#roll-attaque-ciblee').change((event) => {
this.rollData.attaqueCiblee = event.currentTarget.value || "0"
})
html.find('#roll-bonus-malus').change((event) => {
this.rollData.bonusMalus = event.currentTarget.value || "0"
})
@@ -80,8 +89,14 @@ export class TeDeumRollDialog extends Dialog {
html.find('#roll-tir-mouvement').change((event) => {
this.rollData.isMouvement = event.currentTarget.checked
})
html.find('#roll-charge-a-pied').change((event) => {
this.rollData.isChargeAPied = event.currentTarget.checked
})
html.find('#roll-charge-a-cheval').change((event) => {
this.rollData.isChargeACheval = event.currentTarget.checked
})
}
}

View File

@@ -59,7 +59,6 @@ export class TeDeumItemSheet extends foundry.appv1.sheets.ItemSheet {
}
this.options.editable = !(this.object.origin == "embeddedItem");
console.log("ITEM DATA", formData, this);
return formData;
}
@@ -92,7 +91,7 @@ export class TeDeumItemSheet extends foundry.appv1.sheets.ItemSheet {
payload: chatData,
});
renderTemplate('systems/fvtt-te-deum/templates/post-item.html', chatData).then(html => {
foundry.applications.handlebars.renderTemplate('systems/fvtt-te-deum/templates/post-item.html', chatData).then(html => {
let chatOptions = TeDeumUtility.chatDataSetup(html);
ChatMessage.create(chatOptions)
});
@@ -157,7 +156,7 @@ export class TeDeumItemSheet extends foundry.appv1.sheets.ItemSheet {
let itemType = li.data("item-type");
});
}
}
/* -------------------------------------------- */
get template() {

View File

@@ -90,6 +90,8 @@ Hooks.once("init", async function () {
foundry.documents.collections.Items.registerSheet("fvtt-te-deum", TeDeumItemSheet, { makeDefault: true });
TeDeumUtility.init()
TeDeumUtility.installHooks()
});
@@ -98,6 +100,7 @@ Hooks.once("init", async function () {
/* -------------------------------------------- */
Hooks.once("ready", function () {
// User warning
if (!game.user.isGM && game.user.character == undefined) {
ui.notifications.info("Attention ! Aucun personnage relié au joueur !");
@@ -107,10 +110,10 @@ Hooks.once("ready", function () {
});
}
import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter=>{
import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => {
console.log("ClassCounter loaded", moduleCounter)
moduleCounter.ClassCounter.registerUsageCount()
}).catch(err=>
}).catch(err =>
console.log("No stats available, giving up.")
)
TeDeumUtility.ready();

21
package.json Normal file
View File

@@ -0,0 +1,21 @@
{
"name": "fvtt-te-deum",
"version": "1.0.0",
"description": "Système Te Deum pour FoundryVTT",
"private": true,
"scripts": {
"build:css": "gulp css",
"watch:css": "gulp watch"
},
"devDependencies": {
"gulp": "^4.0.2",
"gulp-less": "^5.0.0",
"less": "^4.2.0",
"autoprefixer": "^10.4.20",
"gulp-postcss": "^9.0.1",
"postcss": "^8.4.49"
},
"keywords": ["foundry-vtt", "te-deum"],
"author": "",
"license": "ISC"
}

View File

@@ -1 +1 @@
MANIFEST-000108
MANIFEST-000226

View File

@@ -1,7 +1,3 @@
2025/06/04-15:05:47.545416 7ff25bfff6c0 Recovering log #106
2025/06/04-15:05:47.556041 7ff25bfff6c0 Delete type=3 #104
2025/06/04-15:05:47.556120 7ff25bfff6c0 Delete type=0 #106
2025/06/04-15:26:45.555523 7ff25a3ff6c0 Level-0 table #111: started
2025/06/04-15:26:45.555566 7ff25a3ff6c0 Level-0 table #111: 0 bytes OK
2025/06/04-15:26:45.562169 7ff25a3ff6c0 Delete type=0 #109
2025/06/04-15:26:45.562425 7ff25a3ff6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)
2026/02/25-16:17:49.096861 7f821f7fe6c0 Recovering log #224
2026/02/25-16:17:49.106471 7f821f7fe6c0 Delete type=3 #222
2026/02/25-16:17:49.106539 7f821f7fe6c0 Delete type=0 #224

View File

@@ -1,7 +1,7 @@
2025/05/18-22:00:33.531561 7f8905ffb6c0 Recovering log #101
2025/05/18-22:00:33.592770 7f8905ffb6c0 Delete type=3 #99
2025/05/18-22:00:33.592842 7f8905ffb6c0 Delete type=0 #101
2025/05/18-22:05:29.127669 7f8667fff6c0 Level-0 table #107: started
2025/05/18-22:05:29.127710 7f8667fff6c0 Level-0 table #107: 0 bytes OK
2025/05/18-22:05:29.134205 7f8667fff6c0 Delete type=0 #105
2025/05/18-22:05:29.134321 7f8667fff6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)
2026/02/25-15:53:40.937630 7f821ffff6c0 Recovering log #220
2026/02/25-15:53:40.949873 7f821ffff6c0 Delete type=3 #218
2026/02/25-15:53:40.949933 7f821ffff6c0 Delete type=0 #220
2026/02/25-16:16:19.716603 7f821d8d46c0 Level-0 table #225: started
2026/02/25-16:16:19.716652 7f821d8d46c0 Level-0 table #225: 0 bytes OK
2026/02/25-16:16:19.765894 7f821d8d46c0 Delete type=0 #223
2026/02/25-16:16:19.766155 7f821d8d46c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)

Binary file not shown.

BIN
packs/aides/MANIFEST-000226 Normal file

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000211
MANIFEST-000329

View File

@@ -1,7 +1,3 @@
2025/06/04-15:05:47.429143 7ff25affd6c0 Recovering log #209
2025/06/04-15:05:47.441082 7ff25affd6c0 Delete type=3 #207
2025/06/04-15:05:47.441344 7ff25affd6c0 Delete type=0 #209
2025/06/04-15:26:45.478679 7ff25a3ff6c0 Level-0 table #214: started
2025/06/04-15:26:45.478793 7ff25a3ff6c0 Level-0 table #214: 0 bytes OK
2025/06/04-15:26:45.485108 7ff25a3ff6c0 Delete type=0 #212
2025/06/04-15:26:45.505317 7ff25a3ff6c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)
2026/02/25-16:17:49.007591 7f821f7fe6c0 Recovering log #327
2026/02/25-16:17:49.018485 7f821f7fe6c0 Delete type=3 #325
2026/02/25-16:17:49.018548 7f821f7fe6c0 Delete type=0 #327

View File

@@ -1,7 +1,7 @@
2025/05/18-22:00:33.073973 7f8904ff96c0 Recovering log #204
2025/05/18-22:00:33.125273 7f8904ff96c0 Delete type=3 #202
2025/05/18-22:00:33.125334 7f8904ff96c0 Delete type=0 #204
2025/05/18-22:05:29.052408 7f8667fff6c0 Level-0 table #210: started
2025/05/18-22:05:29.052435 7f8667fff6c0 Level-0 table #210: 0 bytes OK
2025/05/18-22:05:29.058826 7f8667fff6c0 Delete type=0 #208
2025/05/18-22:05:29.071831 7f8667fff6c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)
2026/02/25-15:53:40.848906 7f821effd6c0 Recovering log #323
2026/02/25-15:53:40.858667 7f821effd6c0 Delete type=3 #321
2026/02/25-15:53:40.858720 7f821effd6c0 Delete type=0 #323
2026/02/25-16:16:19.467652 7f821d8d46c0 Level-0 table #328: started
2026/02/25-16:16:19.467677 7f821d8d46c0 Level-0 table #328: 0 bytes OK
2026/02/25-16:16:19.528659 7f821d8d46c0 Delete type=0 #326
2026/02/25-16:16:19.528885 7f821d8d46c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)

Binary file not shown.

BIN
packs/armes/MANIFEST-000329 Normal file

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000210
MANIFEST-000329

View File

@@ -1,7 +1,3 @@
2025/06/04-15:05:47.446612 7ff2609fa6c0 Recovering log #208
2025/06/04-15:05:47.457941 7ff2609fa6c0 Delete type=3 #206
2025/06/04-15:05:47.458200 7ff2609fa6c0 Delete type=0 #208
2025/06/04-15:26:45.491864 7ff25a3ff6c0 Level-0 table #213: started
2025/06/04-15:26:45.491924 7ff25a3ff6c0 Level-0 table #213: 0 bytes OK
2025/06/04-15:26:45.498683 7ff25a3ff6c0 Delete type=0 #211
2025/06/04-15:26:45.505345 7ff25a3ff6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)
2026/02/25-16:17:49.020792 7f821effd6c0 Recovering log #327
2026/02/25-16:17:49.030955 7f821effd6c0 Delete type=3 #325
2026/02/25-16:17:49.031024 7f821effd6c0 Delete type=0 #327

View File

@@ -1,7 +1,7 @@
2025/05/18-22:00:33.135764 7f89067fc6c0 Recovering log #203
2025/05/18-22:00:33.191351 7f89067fc6c0 Delete type=3 #201
2025/05/18-22:00:33.191454 7f89067fc6c0 Delete type=0 #203
2025/05/18-22:05:29.065248 7f8667fff6c0 Level-0 table #209: started
2025/05/18-22:05:29.065277 7f8667fff6c0 Level-0 table #209: 0 bytes OK
2025/05/18-22:05:29.071683 7f8667fff6c0 Delete type=0 #207
2025/05/18-22:05:29.071852 7f8667fff6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)
2026/02/25-15:53:40.860848 7f821f7fe6c0 Recovering log #323
2026/02/25-15:53:40.871268 7f821f7fe6c0 Delete type=3 #321
2026/02/25-15:53:40.871372 7f821f7fe6c0 Delete type=0 #323
2026/02/25-16:16:19.298465 7f821d8d46c0 Level-0 table #328: started
2026/02/25-16:16:19.298546 7f821d8d46c0 Level-0 table #328: 0 bytes OK
2026/02/25-16:16:19.356349 7f821d8d46c0 Delete type=0 #326
2026/02/25-16:16:19.528831 7f821d8d46c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000207
MANIFEST-000327

View File

@@ -1,7 +1,3 @@
2025/06/04-15:05:47.413144 7ff25bfff6c0 Recovering log #205
2025/06/04-15:05:47.423163 7ff25bfff6c0 Delete type=3 #203
2025/06/04-15:05:47.423245 7ff25bfff6c0 Delete type=0 #205
2025/06/04-15:26:45.485291 7ff25a3ff6c0 Level-0 table #210: started
2025/06/04-15:26:45.485326 7ff25a3ff6c0 Level-0 table #210: 0 bytes OK
2025/06/04-15:26:45.491655 7ff25a3ff6c0 Delete type=0 #208
2025/06/04-15:26:45.505333 7ff25a3ff6c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at (end)
2026/02/25-16:17:48.995540 7f821e7fc6c0 Recovering log #325
2026/02/25-16:17:49.005262 7f821e7fc6c0 Delete type=3 #323
2026/02/25-16:17:49.005349 7f821e7fc6c0 Delete type=0 #325

View File

@@ -1,7 +1,7 @@
2025/05/18-22:00:32.966617 7f8905ffb6c0 Recovering log #200
2025/05/18-22:00:33.058932 7f8905ffb6c0 Delete type=3 #198
2025/05/18-22:00:33.058991 7f8905ffb6c0 Delete type=0 #200
2025/05/18-22:05:29.044847 7f8667fff6c0 Level-0 table #206: started
2025/05/18-22:05:29.044904 7f8667fff6c0 Level-0 table #206: 0 bytes OK
2025/05/18-22:05:29.052189 7f8667fff6c0 Delete type=0 #204
2025/05/18-22:05:29.071818 7f8667fff6c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at (end)
2026/02/25-15:53:40.836015 7f821ffff6c0 Recovering log #321
2026/02/25-15:53:40.846129 7f821ffff6c0 Delete type=3 #319
2026/02/25-15:53:40.846180 7f821ffff6c0 Delete type=0 #321
2026/02/25-16:16:19.415073 7f821d8d46c0 Level-0 table #326: started
2026/02/25-16:16:19.415106 7f821d8d46c0 Level-0 table #326: 0 bytes OK
2026/02/25-16:16:19.467523 7f821d8d46c0 Delete type=0 #324
2026/02/25-16:16:19.528868 7f821d8d46c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000219
MANIFEST-000339

View File

@@ -1,7 +1,3 @@
2025/06/04-15:05:47.464179 7ff25b7fe6c0 Recovering log #217
2025/06/04-15:05:47.474973 7ff25b7fe6c0 Delete type=3 #215
2025/06/04-15:05:47.475215 7ff25b7fe6c0 Delete type=0 #217
2025/06/04-15:26:45.511713 7ff25a3ff6c0 Level-0 table #222: started
2025/06/04-15:26:45.511749 7ff25a3ff6c0 Level-0 table #222: 0 bytes OK
2025/06/04-15:26:45.518781 7ff25a3ff6c0 Delete type=0 #220
2025/06/04-15:26:45.531871 7ff25a3ff6c0 Manual compaction at level-0 from '!folders!9PQi3Lv54rpcxavo' @ 72057594037927935 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at (end)
2026/02/25-16:17:49.032966 7f821ffff6c0 Recovering log #337
2026/02/25-16:17:49.043199 7f821ffff6c0 Delete type=3 #335
2026/02/25-16:17:49.043264 7f821ffff6c0 Delete type=0 #337

View File

@@ -1,7 +1,7 @@
2025/05/18-22:00:33.199430 7f89057fa6c0 Recovering log #212
2025/05/18-22:00:33.264639 7f89057fa6c0 Delete type=3 #210
2025/05/18-22:00:33.264698 7f89057fa6c0 Delete type=0 #212
2025/05/18-22:05:29.078828 7f8667fff6c0 Level-0 table #218: started
2025/05/18-22:05:29.078861 7f8667fff6c0 Level-0 table #218: 0 bytes OK
2025/05/18-22:05:29.085105 7f8667fff6c0 Delete type=0 #216
2025/05/18-22:05:29.098638 7f8667fff6c0 Manual compaction at level-0 from '!folders!9PQi3Lv54rpcxavo' @ 72057594037927935 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at (end)
2026/02/25-15:53:40.874436 7f821ffff6c0 Recovering log #333
2026/02/25-15:53:40.884848 7f821ffff6c0 Delete type=3 #331
2026/02/25-15:53:40.884904 7f821ffff6c0 Delete type=0 #333
2026/02/25-16:16:19.356498 7f821d8d46c0 Level-0 table #338: started
2026/02/25-16:16:19.356535 7f821d8d46c0 Level-0 table #338: 0 bytes OK
2026/02/25-16:16:19.414898 7f821d8d46c0 Delete type=0 #336
2026/02/25-16:16:19.528852 7f821d8d46c0 Manual compaction at level-0 from '!folders!9PQi3Lv54rpcxavo' @ 72057594037927935 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

View File

@@ -1 +1 @@
MANIFEST-000210
MANIFEST-000328

View File

@@ -1,7 +1,3 @@
2025/06/04-15:05:47.481354 7ff25affd6c0 Recovering log #208
2025/06/04-15:05:47.492415 7ff25affd6c0 Delete type=3 #206
2025/06/04-15:05:47.492508 7ff25affd6c0 Delete type=0 #208
2025/06/04-15:26:45.499004 7ff25a3ff6c0 Level-0 table #213: started
2025/06/04-15:26:45.499054 7ff25a3ff6c0 Level-0 table #213: 0 bytes OK
2025/06/04-15:26:45.505185 7ff25a3ff6c0 Delete type=0 #211
2025/06/04-15:26:45.505355 7ff25a3ff6c0 Manual compaction at level-0 from '!items!17mjvwS8R3B6LloG' @ 72057594037927935 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at (end)
2026/02/25-16:17:49.045639 7f821e7fc6c0 Recovering log #326
2026/02/25-16:17:49.056537 7f821e7fc6c0 Delete type=3 #324
2026/02/25-16:17:49.056606 7f821e7fc6c0 Delete type=0 #326

View File

@@ -1,7 +1,7 @@
2025/05/18-22:00:33.273056 7f8904ff96c0 Recovering log #203
2025/05/18-22:00:33.327855 7f8904ff96c0 Delete type=3 #201
2025/05/18-22:00:33.327981 7f8904ff96c0 Delete type=0 #203
2025/05/18-22:05:29.058954 7f8667fff6c0 Level-0 table #209: started
2025/05/18-22:05:29.058982 7f8667fff6c0 Level-0 table #209: 0 bytes OK
2025/05/18-22:05:29.065089 7f8667fff6c0 Delete type=0 #207
2025/05/18-22:05:29.071842 7f8667fff6c0 Manual compaction at level-0 from '!items!17mjvwS8R3B6LloG' @ 72057594037927935 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at (end)
2026/02/25-15:53:40.888183 7f821effd6c0 Recovering log #322
2026/02/25-15:53:40.897808 7f821effd6c0 Delete type=3 #320
2026/02/25-15:53:40.897873 7f821effd6c0 Delete type=0 #322
2026/02/25-16:16:19.645632 7f821d8d46c0 Level-0 table #327: started
2026/02/25-16:16:19.645665 7f821d8d46c0 Level-0 table #327: 0 bytes OK
2026/02/25-16:16:19.716424 7f821d8d46c0 Delete type=0 #325
2026/02/25-16:16:19.766141 7f821d8d46c0 Manual compaction at level-0 from '!items!17mjvwS8R3B6LloG' @ 72057594037927935 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

View File

View File

@@ -1 +1 @@
MANIFEST-000210
MANIFEST-000328

View File

@@ -1,7 +1,3 @@
2025/06/04-15:05:47.497176 7ff25bfff6c0 Recovering log #208
2025/06/04-15:05:47.507676 7ff25bfff6c0 Delete type=3 #206
2025/06/04-15:05:47.507762 7ff25bfff6c0 Delete type=0 #208
2025/06/04-15:26:45.518949 7ff25a3ff6c0 Level-0 table #213: started
2025/06/04-15:26:45.518983 7ff25a3ff6c0 Level-0 table #213: 0 bytes OK
2025/06/04-15:26:45.525386 7ff25a3ff6c0 Delete type=0 #211
2025/06/04-15:26:45.531893 7ff25a3ff6c0 Manual compaction at level-0 from '!items!1icaxIywAwDXQcMz' @ 72057594037927935 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at (end)
2026/02/25-16:17:49.058989 7f821effd6c0 Recovering log #326
2026/02/25-16:17:49.068511 7f821effd6c0 Delete type=3 #324
2026/02/25-16:17:49.068568 7f821effd6c0 Delete type=0 #326

View File

@@ -1,7 +1,7 @@
2025/05/18-22:00:33.333998 7f89067fc6c0 Recovering log #203
2025/05/18-22:00:33.393841 7f89067fc6c0 Delete type=3 #201
2025/05/18-22:00:33.393896 7f89067fc6c0 Delete type=0 #203
2025/05/18-22:05:29.085237 7f8667fff6c0 Level-0 table #209: started
2025/05/18-22:05:29.085265 7f8667fff6c0 Level-0 table #209: 0 bytes OK
2025/05/18-22:05:29.091461 7f8667fff6c0 Delete type=0 #207
2025/05/18-22:05:29.098648 7f8667fff6c0 Manual compaction at level-0 from '!items!1icaxIywAwDXQcMz' @ 72057594037927935 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at (end)
2026/02/25-15:53:40.899737 7f821f7fe6c0 Recovering log #322
2026/02/25-15:53:40.910545 7f821f7fe6c0 Delete type=3 #320
2026/02/25-15:53:40.910590 7f821f7fe6c0 Delete type=0 #322
2026/02/25-16:16:19.529006 7f821d8d46c0 Level-0 table #327: started
2026/02/25-16:16:19.529044 7f821d8d46c0 Level-0 table #327: 0 bytes OK
2026/02/25-16:16:19.584573 7f821d8d46c0 Delete type=0 #325
2026/02/25-16:16:19.766110 7f821d8d46c0 Manual compaction at level-0 from '!items!1icaxIywAwDXQcMz' @ 72057594037927935 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

View File

View File

@@ -1 +1 @@
MANIFEST-000147
MANIFEST-000265

View File

@@ -1,7 +1,3 @@
2025/06/04-15:05:47.528778 7ff25b7fe6c0 Recovering log #145
2025/06/04-15:05:47.538793 7ff25b7fe6c0 Delete type=3 #143
2025/06/04-15:05:47.538886 7ff25b7fe6c0 Delete type=0 #145
2025/06/04-15:26:45.525488 7ff25a3ff6c0 Level-0 table #150: started
2025/06/04-15:26:45.525518 7ff25a3ff6c0 Level-0 table #150: 0 bytes OK
2025/06/04-15:26:45.531590 7ff25a3ff6c0 Delete type=0 #148
2025/06/04-15:26:45.531909 7ff25a3ff6c0 Manual compaction at level-0 from '!scenes!FJXugdbkBpEJEdR6' @ 72057594037927935 : 1 .. '!scenes!FJXugdbkBpEJEdR6' @ 0 : 0; will stop at (end)
2026/02/25-16:17:49.082827 7f821e7fc6c0 Recovering log #263
2026/02/25-16:17:49.093869 7f821e7fc6c0 Delete type=3 #261
2026/02/25-16:17:49.093933 7f821e7fc6c0 Delete type=0 #263

View File

@@ -1,7 +1,7 @@
2025/05/18-22:00:33.470618 7f89057fa6c0 Recovering log #140
2025/05/18-22:00:33.527042 7f89057fa6c0 Delete type=3 #138
2025/05/18-22:00:33.527136 7f89057fa6c0 Delete type=0 #140
2025/05/18-22:05:29.091684 7f8667fff6c0 Level-0 table #146: started
2025/05/18-22:05:29.091715 7f8667fff6c0 Level-0 table #146: 0 bytes OK
2025/05/18-22:05:29.098504 7f8667fff6c0 Delete type=0 #144
2025/05/18-22:05:29.098657 7f8667fff6c0 Manual compaction at level-0 from '!scenes!FJXugdbkBpEJEdR6' @ 72057594037927935 : 1 .. '!scenes!FJXugdbkBpEJEdR6' @ 0 : 0; will stop at (end)
2026/02/25-15:53:40.925187 7f821effd6c0 Recovering log #259
2026/02/25-15:53:40.934520 7f821effd6c0 Delete type=3 #257
2026/02/25-15:53:40.934568 7f821effd6c0 Delete type=0 #259
2026/02/25-16:16:19.945947 7f821d8d46c0 Level-0 table #264: started
2026/02/25-16:16:19.946001 7f821d8d46c0 Level-0 table #264: 0 bytes OK
2026/02/25-16:16:20.001848 7f821d8d46c0 Delete type=0 #262
2026/02/25-16:16:20.001994 7f821d8d46c0 Manual compaction at level-0 from '!scenes!FJXugdbkBpEJEdR6' @ 72057594037927935 : 1 .. '!scenes!FJXugdbkBpEJEdR6' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

View File

View File

@@ -1 +1 @@
MANIFEST-000210
MANIFEST-000329

View File

@@ -1,7 +1,3 @@
2025/06/04-15:05:47.512282 7ff2609fa6c0 Recovering log #208
2025/06/04-15:05:47.522888 7ff2609fa6c0 Delete type=3 #206
2025/06/04-15:05:47.522989 7ff2609fa6c0 Delete type=0 #208
2025/06/04-15:26:45.505492 7ff25a3ff6c0 Level-0 table #213: started
2025/06/04-15:26:45.505521 7ff25a3ff6c0 Level-0 table #213: 0 bytes OK
2025/06/04-15:26:45.511578 7ff25a3ff6c0 Delete type=0 #211
2025/06/04-15:26:45.531835 7ff25a3ff6c0 Manual compaction at level-0 from '!items!1bAL2MQVpVBd0c5Z' @ 72057594037927935 : 1 .. '!items!zs67k4sxCid6oTK3' @ 0 : 0; will stop at (end)
2026/02/25-16:17:49.070393 7f821ffff6c0 Recovering log #327
2026/02/25-16:17:49.080654 7f821ffff6c0 Delete type=3 #325
2026/02/25-16:17:49.080720 7f821ffff6c0 Delete type=0 #327

View File

@@ -1,7 +1,7 @@
2025/05/18-22:00:33.404356 7f8905ffb6c0 Recovering log #203
2025/05/18-22:00:33.459805 7f8905ffb6c0 Delete type=3 #201
2025/05/18-22:00:33.459865 7f8905ffb6c0 Delete type=0 #203
2025/05/18-22:05:29.071945 7f8667fff6c0 Level-0 table #209: started
2025/05/18-22:05:29.071972 7f8667fff6c0 Level-0 table #209: 0 bytes OK
2025/05/18-22:05:29.078657 7f8667fff6c0 Delete type=0 #207
2025/05/18-22:05:29.098624 7f8667fff6c0 Manual compaction at level-0 from '!items!1bAL2MQVpVBd0c5Z' @ 72057594037927935 : 1 .. '!items!zs67k4sxCid6oTK3' @ 0 : 0; will stop at (end)
2026/02/25-15:53:40.912618 7f821e7fc6c0 Recovering log #323
2026/02/25-15:53:40.922737 7f821e7fc6c0 Delete type=3 #321
2026/02/25-15:53:40.922804 7f821e7fc6c0 Delete type=0 #323
2026/02/25-16:16:19.584692 7f821d8d46c0 Level-0 table #328: started
2026/02/25-16:16:19.584724 7f821d8d46c0 Level-0 table #328: 0 bytes OK
2026/02/25-16:16:19.645484 7f821d8d46c0 Delete type=0 #326
2026/02/25-16:16:19.766128 7f821d8d46c0 Manual compaction at level-0 from '!items!1bAL2MQVpVBd0c5Z' @ 72057594037927935 : 1 .. '!items!zs67k4sxCid6oTK3' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

View File

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -148,8 +148,8 @@
],
"title": "Te Deum pour Un Massacre, le Jeu de Rôles (Officiel)",
"url": "https://www.uberwald.me/gitea/public/fvtt-te-deum",
"version": "13.0.1",
"download": "https://www.uberwald.me/gitea/public/fvtt-te-deum/releases/download/13.0.0/fvtt-te-deum-13.0.1.zip",
"version": "13.0.2",
"download": "https://www.uberwald.me/gitea/public/fvtt-te-deum/releases/download/13.0.1/fvtt-te-deum-13.0.2.zip",
"background": "systems/fvtt-te-deum/images/ui/tdeum_welcome_page_01.webp",
"flags": {
"hotReload": {

View File

@@ -40,30 +40,35 @@
<div class="grid grid-2col">
<div>
<ul class="item-list alternate-list">
{{#each caracList as |char key|}}
<li class="item flexrow list-item carac-box">
<img class="sheet-competence-img" src="systems/fvtt-te-deum/images/icons/{{key}}.webp" />
<label class="item-left-pad item-field item-field-label-medium" data-tooltip="{{char.description}}">{{char.name}}</label>
<select type="text" class="input-numeric-short" name="system.caracteristiques.{{key}}.value"
data-dtype="Number" />
{{selectOptions @root.config.descriptionValeur selected=char.value labelAttr="valeur"}}
</select>
<label class="item-field item-field-label-medium">{{char.qualite}}</label>
<label class="item-field item-field-label-medium">{{char.dice}} ({{char.negativeDice}})</label>
</li>
{{/each}}
</ul>
<ul class="item-list alternate-list">
{{#each caracList as |char key|}}
<li class="item flexrow list-item carac-box">
<img class="sheet-competence-img" src="systems/fvtt-te-deum/images/icons/{{key}}.webp" />
<label class="item-left-pad item-field item-field-label-medium"
data-tooltip="{{char.description}}">{{char.name}}</label>
<select type="text" class="input-numeric-short" name="system.caracteristiques.{{key}}.value"
data-dtype="Number" />
{{selectOptions @root.config.descriptionValeur selected=char.value labelAttr="valeur"}}
</select>
<label class="item-field item-field-label-medium">{{char.qualite}}</label>
<label class="item-field item-field-label-medium">{{char.dice}} ({{char.negativeDice}})</label>
</li>
{{/each}}
</ul>
<div>
<h4>Malus de santé : {{santeModifier}} niveaux</h4>
</div>
<div>
<h4>Malus de santé : {{santeModifier}} niveaux</h4>
</div>
<ul class="item-list alternate-list">
<ul class="item-list alternate-list">
<li class="item flexrow list-item items-title-bg">
<span class="item-field-title-long">
<h3><label class="item-field-label-long">Blessures</label></h3>
</span>
<div class="item-controls item-controls-fixed">
<a class="item-control blessure-add" data-type="blessure" title="Ajouter une Blessure"><i class="fas fa-plus"></i></a>
</div>
</li>
{{#each blessures as |blessure key|}}
<li class="item flexrow list-item list-item-shadow item-id" data-item-id="{{blessure._id}}">
@@ -140,7 +145,8 @@
<div>
<ul class="item-list alternate-list">
<li class="item flexrow list-item carac-box">
<label class="item-left-pad item-field item-field-label-medium" data-tooltip="{{providence.description}}">Providence</label>
<label class="item-left-pad item-field item-field-label-medium"
data-tooltip="{{providence.description}}">Providence</label>
<select type="text" class="input-numeric-short" name="system.providence.value" data-dtype="Number" />
{{selectOptions @root.config.providence selected=providence.value nameAttr="value" valueAttr="value"
labelAttr="value"}}
@@ -149,16 +155,21 @@
<label class="item-field item-field-label-short">{{providence.dice}}</label>
</li>
<li class="item flexrow list-item carac-box">
<label class="item-left-pad item-field item-field-label-medium" data-tooltip=" La Bienveillance nest pas à proprement parler une compétence : il sagit de lévaluation chiffrée de l'atta- chement que l'ange gardien du personnage éprouve pour son protégé. Cet attachement peut se détériorer si le personnage se montre indigne ou mauvais, et s'érode avec lâge. La Bienveillance a un score initial de 10 pour un nouveau PJ ayant moins de 30 ans.">
<label class="item-left-pad item-field item-field-label-medium"
data-tooltip=" La Bienveillance nest pas à proprement parler une compétence : il sagit de lévaluation chiffrée de l'atta- chement que l'ange gardien du personnage éprouve pour son protégé. Cet attachement peut se détériorer si le personnage se montre indigne ou mauvais, et s'érode avec lâge. La Bienveillance a un score initial de 10 pour un nouveau PJ ayant moins de 30 ans.">
Bienveillance</label>
<input class="input-numeric-short" type="text" name="system.bienveillance.value" value="{{system.bienveillance.value}}" data-dtype="Number" />
<input class="input-numeric-short" type="text" name="system.bienveillance.value"
value="{{system.bienveillance.value}}" data-dtype="Number" />
<label class="item-left-pad item-field item-field-label-medium">Bonus dégats</label>
<input class="input-numeric-short" type="text" value="{{bonusDegats.label}}" disabled data-dtype="Number" />
<input class="input-numeric-short" type="text" value="{{bonusDegats.value}}" disabled
data-dtype="Number" />
</li>
<li class="item flexrow list-item carac-box">
<label class="item-left-pad item-field item-field-label-medium">Armures Lourdes</label>
<input class="input-numeric-short" type="text" value="{{nbArmuresLourdes}}" disabled data-dtype="Number" />&nbsp;/&nbsp;
<input class="input-numeric-short" type="text" value="{{pointsArmuresLourdes.value}}" disabled data-dtype="Number" />
<input class="input-numeric-short" type="text" value="{{nbArmuresLourdes}}" disabled
data-dtype="Number" />&nbsp;/&nbsp;
<input class="input-numeric-short" type="text" value="{{pointsArmuresLourdes.value}}" disabled
data-dtype="Number" />
<label class="item-left-pad item-field item-field-label-medium">Actions/Tour</label>
<input class="input-numeric-short" type="text" value="{{nbActions.value}}" disabled data-dtype="Number" />
</li>
@@ -172,7 +183,7 @@
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-add" data-type="grace" title="Créer une Grâce"><i
class="fas fa-plus"></i></a>
class="fas fa-plus"></i></a>
</div>
</li>
{{#each graces as |grace key|}}
@@ -204,19 +215,20 @@
<img class="sheet-competence-img" src="systems/fvtt-te-deum/images/icons/{{key}}.webp" />
<h3 class="item-field-label-long14" data-tooltip="Caracteristique">{{carac.name}} : {{carac.qualite}}</h3>
<label class="item-field item-field-label-short">{{carac.value}}</label>
<label class="item-field ">{{carac.dice}} (xp :
<label class="item-field-xp ">{{carac.dice}} (xp :
{{#if @root.isGM}}
<input class="input-numeric-short" type="text" name="system.caracteristiques.{{key}}.experience" value="{{carac.experience}}" data-dtype="Number" />
<input class="input-numeric-short" type="text" name="system.caracteristiques.{{key}}.experience"
value="{{carac.experience}}" data-dtype="Number" />
{{else}}
{{carac.experience}})
{{/if}}
)
</label>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control competence-add" data-type="competence" data-carac-key="{{key}}" title="Ajouter une Compétence"><i
class="fas fa-plus"></i></a>
</div>
<div class="item-controls item-controls-fixed">
<a class="item-control competence-add" data-type="competence" data-carac-key="{{key}}"
title="Ajouter une Compétence"><i class="fas fa-plus"></i></a>
</div>
</li>
<ul class="ul-level1 flexrow item-list">
{{#each carac.competences as |comp skillkey|}}
@@ -226,7 +238,11 @@
</label>
<span>&nbsp;</span>
<a class="item-control item-edit" title="Editer"><i class="fas fa-edit"></i></a>
{{#if comp.system.isBase}}
<span class="item-control"><i class="fa-solid fa-trash-slash"></i></span>
{{else}}
<a class="item-control item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
{{/if}}
</li>
{{/each}}
</ul>
@@ -267,11 +283,13 @@
</span>
<span class="item-field-label-medium">{{upperFirst arme.system.typeArme}}</span>
<span class="item-field-label-medium">{{upperFirst arme.system.competence}}</span>
<span class="item-field-label-medium"><a class="roll-degats" data-arme-id="{{arme._id}}">{{arme.system.degats}}</a></span>
<span class="item-field-label-medium"><a class="roll-degats"
data-arme-id="{{arme._id}}">{{arme.system.degats}}</a></span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed-full">
<a class="item-control item-equip" title="Equiper" {{#unless arme.system.equipe}}style="color:gray;"{{/unless}}>
<a class="item-control item-equip" title="Equiper" {{#unless arme.system.equipe}}style="color:gray;"
{{/unless}}>
<i class="fas fa-shield-alt"></i>
</a>
<a class="item-control item-edit" title="Editer"><i class="fas fa-edit"></i></a>
@@ -297,7 +315,8 @@
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed-full">
<a class="item-control item-equip" title="Equiper" {{#unless armure.system.equipe}}style="color:gray;"{{/unless}}>
<a class="item-control item-equip" title="Equiper" {{#unless armure.system.equipe}}style="color:gray;"
{{/unless}}>
<i class="fas fa-shield-alt"></i>
</a>
<a class="item-control item-edit" title="Editer l'armure"><i class="fas fa-edit"></i></a>
@@ -318,12 +337,12 @@
<h4 class="center">{{loc.score.min}}-{{loc.score.max}}. {{loc.label}}</h4>
<div class="flexcol">
{{#each loc.armures as |armure idx| }}
<span>{{armure.name}} ({{armure.system.protection}})</span>
<span>{{armure.name}} ({{armure.system.protection}})</span>
{{/each}}
<span>Touché : {{touche}}</span>
<span>Blessures : </span>
{{#each loc.blessures as |blessure idx| }}
<span>{{blessure.name}} ({{blessure.malus}})</span>
<span>{{blessure.name}} ({{blessure.malus}})</span>
{{/each}}
</div>
</div>
@@ -397,8 +416,7 @@
</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-add" data-type="simple" title="Créer une simple"><i
class="fas fa-plus"></i></a>
<a class="item-control item-add" data-type="simple" title="Créer une simple"><i class="fas fa-plus"></i></a>
</div>
</li>
{{#each simples as |simple key|}}
@@ -415,7 +433,7 @@
</div>
</li>
{{/each}}
</ul>
</ul>
</div>
@@ -428,7 +446,7 @@
<li class="item flexrow">
<label class="item-name-label-medium">Genre</label>
<select type="text" class="" name="system.genre" value="{{system.genre}}" data-dtype="String" />
{{selectOptions @root.config.genre selected=system.genre}}
{{selectOptions @root.config.genre selected=system.genre}}
</select>
</li>
<li class="item flexrow">
@@ -438,8 +456,7 @@
</li>
<li class="item flexrow">
<label class="item-name-label-medium">Age</label>
<input type="text" class="" name="system.age" value="{{system.age}}"
data-dtype="String" />
<input type="text" class="" name="system.age" value="{{system.age}}" data-dtype="String" />
</li>
<li class="item flexrow">
<label class="item-name-label-medium">Date de Naissance</label>
@@ -462,8 +479,7 @@
</li>
<li class="item flexrow">
<label class="item-name-label-medium">Religion</label>
<input type="text" class="" name="system.religion" value="{{system.religion}}"
data-dtype="String" />
<input type="text" class="" name="system.religion" value="{{system.religion}}" data-dtype="String" />
</li>
</ul>
</div>

View File

@@ -1,31 +1,110 @@
<div class="chat-message-header">
{{#if actorImg}}
<img class="actor-icon" src="{{actorImg}}" alt="{{alias}}" />
<img class="actor-icon" src="{{actorImg}}" alt="{{alias}}" />
{{/if}}
<h4 class="chat-actor-name">{{alias}}</h4>
</div>
<hr>
<div class="chat-roll-details" style="margin-top: 0.3rem;">
{{#if img}}
<div >
<img class="chat-icon" src="{{img}}" alt="{{name}}" />
</div>
<div style="text-align: center; margin-bottom: 0.3rem;">
<img class="chat-icon" src="{{img}}" alt="{{name}}" />
</div>
{{/if}}
<div class="flexcol">
</div>
<div>
<ul>
{{#if blessure}}
<li>{{defenderName}} a subi une blessure!</li>
<li>Gravité : {{blessure.name}}</li>
<li>Localisation : {{loc.label}}</li>
{{else}}
<li>Aucune blessure subie par {{defenderName}}</li>
{{/if}}
</ul>
</div>
<div class="chat-info-badge" style="margin-bottom: 0.4rem;">
<strong>{{alias}}</strong>
attaque
<strong>{{defenderName}}</strong>
</div>
<ul style="margin: 0; padding-left: 0.5rem;">
{{#if arme}}
<li style="margin: 0.2rem 0;"><span class="chat-info-badge">Dégâts
{{arme.name}}
:
{{degats}}
({{degatsFormula}})</span></li>
{{/if}}
{{#if loc}}
<li style="margin: 0.2rem 0;"><span
class="chat-difficulty-badge"
>Localisation : {{loc.label}}</span></li>
<li style="margin: 0.2rem 0;">Touché : {{touche}}</li>
{{/if}}
{{#if gantelet}}
<li>Poing avec gantelet: +1 dégat</li>
{{/if}}
{{#if isChargeAPied}}
<li>Charge à pied (+Course)</li>
{{/if}}
{{#if isChargeACheval}}
<li>Charge à cheval (+Equitation)</li>
{{/if}}
{{#if isReussiteCritique}}
<li style="margin: 0.3rem 0;"><span class="chat-result-success">🎯
Réussite critique : La blessure a été augmentée d'un niveau</span></li>
{{/if}}
{{#if blessure}}
<li style="margin: 0.3rem 0;"><span class="chat-warning-badge">⚔️
{{defenderName}}
a subi une blessure!</span></li>
<li style="margin: 0.2rem 0;"><strong>Gravité :
{{blessure.name}}</strong></li>
{{#if (eq loc.categorie "tete")}}
{{#if (gt blessure.system.value 0)}}
<li style="margin: 0.3rem 0;"><span class="chat-result-failure">💥
{{defenderName}}
doit réussir un test d'Endurance de difficulté 7 ou être assommé</span></li>
{{/if}}
{{/if}}
{{#if (eq loc.categorie "bras")}}
{{#if (gt blessure.system.value 2)}}
<li style="margin: 0.3rem 0;"><span class="chat-result-failure">💥
{{defenderName}}
lâche l'objet tenu par son bras. Il doit faire un test d'endurance
pour l'utiliser désormais.</span></li>
{{/if}}
{{/if}}
{{#if (eq loc.categorie "jambe")}}
{{#if (gt blessure.system.value 2)}}
<li style="margin: 0.3rem 0;"><span class="chat-result-failure">💥
{{defenderName}}
tombe au sol. Pour se relever et marcher, il doit réussir un test
d'Endurance à chaque tour.</span></li>
{{/if}}
{{/if}}
{{#if (eq loc.categorie "main")}}
{{#if (gt blessure.system.value 1)}}
<li style="margin: 0.3rem 0;"><span class="chat-result-failure">💥
{{defenderName}}
lâche l'objet tenu par sa main. Il doit faire un test d'endurance
pour l'utiliser désormais.</span></li>
{{/if}}
{{/if}}
{{#if (eq loc.categorie "pied")}}
{{#if (gt blessure.system.value 1)}}
<li style="margin: 0.3rem 0;"><span class="chat-result-failure">💥
{{defenderName}}
tombe au sol. Pour se relever et marcher, il doit réussir un test
d'Endurance à chaque tour.</span></li>
{{/if}}
{{/if}}
{{else}}
<li style="margin: 0.3rem 0;"><span class="chat-result-success">✓ Aucune
blessure subie par
{{defenderName}}</span></li>
{{/if}}
</ul>
</div>

View File

@@ -1,23 +1,44 @@
<div class="chat-message-header">
{{#if actorImg}}
<img class="actor-icon" src="{{actorImg}}" alt="{{alias}}" />
<img class="actor-icon" src="{{actorImg}}" alt="{{alias}}" />
{{/if}}
<h4 class="chat-actor-name">{{alias}}</h4>
</div>
<hr>
<div class="chat-roll-details" style="margin-top: 0.3rem;">
{{#if img}}
<div >
<img class="chat-icon" src="{{arme.img}}" alt="{{name}}" />
</div>
<div style="text-align: center; margin-bottom: 0.3rem;">
<img class="chat-icon" src="{{arme.img}}" alt="{{name}}" />
</div>
{{/if}}
<div>
<ul>
<li>Dégats de {{arme.name}}: {{formula}} </li>
<li>Dégats infligés : {{degats}}</li>
</ul>
</div>
</div>
<ul style="margin: 0; padding-left: 0.5rem;">
<li style="margin: 0.2rem 0;"><span class="chat-info-badge">Dégâts de
{{arme.name}}:
{{formula}}</span></li>
{{#if gantelet}}
<li style="margin: 0.2rem 0;"><span class="chat-difficulty-badge">🥊 Poing
avec gantelet: +1 dégât</span></li>
{{/if}}
{{#if isChargeAPied}}
<li style="margin: 0.2rem 0;"><span class="chat-difficulty-badge">🏃
Charge à pied (+Course)</span></li>
{{/if}}
{{#if isChargeACheval}}
<li style="margin: 0.2rem 0;"><span class="chat-difficulty-badge">🐴
Charge à cheval (+Équitation)</span></li>
{{/if}}
<li style="margin: 0.3rem 0;"><span class="chat-warning-badge">⚔️ Dégâts
infligés :
{{degats}}</span></li>
{{#if loc}}
<li style="margin: 0.2rem 0;"><span class="chat-difficulty-badge">🎯
Localisation :
{{loc.label}}</span></li>
{{/if}}
{{#if isReussiteCritique}}
<li style="margin: 0.3rem 0;"><span class="chat-result-success">🎯
Réussite critique : La blessure sera augmentée d'un niveau</span></li>
{{/if}}
</ul>
</div>

View File

@@ -5,92 +5,134 @@
<h4 class="chat-actor-name">{{alias}}</h4>
</div>
<hr>
{{#if img}}
<div style="text-align: center; padding: 0.25rem;">
<img class="chat-icon" src="{{img}}" alt="{{name}}" style="border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.15);" />
</div>
{{/if}}
{{#if img}}
<div >
<img class="chat-icon" src="{{img}}" alt="{{name}}" />
<div class="chat-roll-details">
<ul>
{{#if carac}}
<li><strong>{{carac.name}}:</strong> {{carac.qualite}} <span class="chat-dice-formula">{{carac.dice}}</span></li>
{{/if}}
{{#if competence}}
<li><strong>{{competence.name}}:</strong> {{compScore}}</li>
{{/if}}
{{#if bonusMalus}}
<li class="chat-info-badge"><strong>Bonus/Malus:</strong> {{bonusMalus}}</li>
{{/if}}
{{#if santeModifier}}
<li class="chat-warning-badge"><strong>Santé:</strong> {{santeModifier}} niveaux</li>
{{/if}}
{{#if enableProvidence}}
<li class="chat-info-badge" style="background: rgba(255, 215, 0, 0.2); border-left-color: goldenrod;">⭐ Un niveau de Providence a été utilisé !</li>
{{/if}}
{{#if hasActions}}
<li class="chat-info-badge" data-tooltip="Nombre d'actions restantes, avec MG = Main Gauche">
<strong>Actions restantes:</strong> {{remainingActions}} (MG:{{remainingActionsMainGauche}})
</li>
{{/if}}
{{#if arme}}
{{#if isViser}}
<li class="chat-info-badge">✓ Bonus de visée (+1 niveau)</li>
{{/if}}
{{#if isMouvement}}
<li class="chat-warning-badge">⚠ Malus de cible petite ou en mouvement (-1 niveau)</li>
{{/if}}
{{#if attaqueCiblee}}
<li class="chat-warning-badge">⚠ Attaque ciblée, -1 niveau</li>
{{/if}}
{{#if allongeMalus}}
<li class="chat-warning-badge">⚠ Malus d'allonge: {{allongeMalus}} niveau</li>
{{/if}}
{{/if}}
<li><strong>Formule:</strong> <span class="chat-dice-formula">{{diceFormula}}</span></li>
{{#if isTir}}
<li><strong>Portée:</strong> {{porteeLabel}} <span class="chat-difficulty-badge">Difficulté: {{difficulty}}</span></li>
{{else}}
<li><strong>Difficulté:</strong> <span class="chat-difficulty-badge">{{difficulty}}</span></li>
{{/if}}
</ul>
</div>
<div class="chat-roll-result-section">
<div class="chat-total-result">Résultat: {{total}}</div>
<div style="text-align: center;">
{{#if isSuccess}}
<div class="chat-result-success">Succès !</div>
{{#if isReussiteCritique}}
<div class="chat-result-success" data-tooltip="Si le jet n'est pas opposé, cliquez sur le bouton pour gagner 1 XP en {{carac.name}}" style="margin-top: 0.3rem;">
🌟 Réussite critique (XP potentiel) !
</div>
{{/if}}
{{#if arme}}
<div class="chat-info-badge" style="display: block; margin-top: 0.4rem; padding: 0.3rem; font-size: 0.9em;">
⚔️ <strong>Attaque réussie !</strong> Faites une opposition avec la défense de la cible ou appliquez directement les dégâts.
</div>
{{/if}}
{{else}}
<div class="chat-result-failure">Échec !</div>
{{#if critiqueTotal}}
<div class="chat-negative-dice" style="margin-top: 0.3rem;">
Dé négatif: {{critiqueTotal}}
</div>
{{/if}}
{{#if isEchecCritique}}
<div class="chat-result-failure" data-tooltip="Si le jet n'est pas opposé, cliquez sur le bouton pour gagner 1 XP en {{carac.name}}" style="margin-top: 0.3rem;">
💀 Échec critique (XP potentiel) !
</div>
{{/if}}
{{/if}}
{{#if nbEsquives}}
<div class="chat-warning-badge" style="display: block; margin-top: 0.4rem; padding: 0.3rem;">
⚠️ Rappel : vous devez réussir {{nbEsquives}} tests d'esquive pour arriver au contact (règle d'allonge des armes).
</div>
{{/if}}
{{#if loc}}
<div class="chat-info-badge" style="display: block; margin-top: 0.4rem; padding: 0.3rem; background: rgba(255, 215, 0, 0.15); border-left-color: goldenrod;">
🎯 <strong>Localisation:</strong> {{loc.label}}
</div>
{{/if}}
{{#if degats}}
<div class="chat-warning-badge" style="display: block; margin-top: 0.4rem; padding: 0.3rem; font-size: 0.95em; background: rgba(255, 100, 100, 0.15); border-left-color: #a82020;">
⚔️ <strong>Dégâts:</strong> {{degats}} {{#if isReussiteCritique}}<em>(Augmentez la gravité de la blessure d'un niveau)</em>{{/if}}
</div>
{{/if}}
</div>
</div>
<div class="chat-actions-bar">
{{#if (or isEchecCritique isReussiteCritique)}}
<a class="chat-command-gain-xp">
<img class="chat-command-img" data-tooltip="Cliquez ici pour +1 XP en {{carac.name}} si pas d'opposition"
src="systems/fvtt-te-deum/images/icons/xpplus1.webp">
</a>
{{/if}}
<div class="flexcol">
</div>
<a class="chat-command-opposition">
<img class="chat-command-img" data-tooltip="Test en opposition"
src="systems/fvtt-te-deum/images/icons/opposition.webp">
</a>
<div>
<ul>
{{#if carac}}
<li>{{carac.name}}: {{carac.qualite}} ({{carac.dice}}) </li>
{{/if}}
{{#if competence}}
<li>{{competence.name}}: {{compScore}} </li>
{{/if}}
{{#if bonusMalus}}
<li>Bonus/Malus: {{bonusMalus}} </li>
{{/if}}
{{#if santeModifier}}
<li>Santé: {{santeModifier}} niveaux</li>
{{/if}}
{{#if enableProvidence}}
<li>Un niveau de Providence a été utilisé !</li>
{{/if}}
{{#if isViser}}
<li>Bonus de visée (+1 niveau)</li>
{{/if}}
{{#if isMouvement}}
<li>Malus de cible petite ou en mouvement (-1 niveau)</li>
{{/if}}
{{#if arme}}
{{#if isSuccess}}
<a class="chat-command-appliquer-degats">
<img class="chat-command-img" data-tooltip="Appliquer les dégâts directement sans opposition"
src="systems/fvtt-te-deum/images/icons/appliquer-degats.webp">
</a>
{{/if}}
{{/if}}
</div>
</div>
<li>Dés: {{diceFormula}} </li>
{{#if isTir}}
<li>Portée: {{porteeLabel}} ( {{difficulty}} )</li>
{{else}}
<li>Difficulté: {{difficulty}} </li>
{{/if}}
</ul>
</div>
<div class="flexrow">
<ul class="chat-result-column">
<li><strong>Résultat: {{total}}</strong> </li>
{{#if isSuccess}}
<li><strong class="chat-result-success">Succès !</strong> </li>
{{#if isReussiteCritique}}
<li><strong class="chat-result-success">Réussite critique ! 1 XP gagné en {{carac.name}}.</strong> </li>
{{/if}}
{{#if arme}}
<li><strong class="">Attaque réussie ! Faites une opposition avec la défense de la cible ou appliquez directement les dégats.</strong> </li>
{{/if}}
{{else}}
<li><strong class="chat-result-failure">Echec !</strong> </li>
{{#if isEchecCritique}}
<li><strong class="chat-result-failure">Echec critique ! 1 XP gagné en {{carac.name}}.</strong> </li>
{{/if}}
{{/if}}
{{#if loc}}
<li><strong>Attaque réussie !!</strong> </li>
<li>Localisation: {{loc.label}} </li>
<li>Dégats: {{degats}} {{#if isReussiteCritique}}(Augmentez la gravité de la blessure d'un niveau){{/if}}</li>
{{/if}}
</ul>
<div>
<a class="chat-command-opposition" >
<img class="chat-command-img" data-tooltip="Test en opposition" src="systems/fvtt-te-deum/images/icons/opposition.webp">
</a>
{{#if arme}}
{{#if isSuccess}}
<a class="chat-command-appliquer-degats" >
<img class="chat-command-img" data-tooltip="Appliquer les dégats directement sans opposition" src="systems/fvtt-te-deum/images/icons/appliquer-degats.webp">
</a>
{{/if}}
{{/if}}
</div>
</div>
</div>
</div>

View File

@@ -1,15 +1,22 @@
<div class="chat-message-header">
<img class="actor-icon" src="{{winner.actorImg}}" alt="{{winner.alias}}" />
<img class="chat-command-img" data-tooltip="Test en opposition" src="systems/fvtt-te-deum/images/icons/opposition.webp">
<img class="chat-command-img" data-tooltip="Test en opposition"
src="systems/fvtt-te-deum/images/icons/opposition.webp">
<img class="actor-icon" src="{{looser.actorImg}}" alt="{{looser.alias}}" />
<label class="chat-actor-name-opposition">{{winner.alias}} vs {{looser.alias}}</label>
<label class="chat-actor-name-opposition">{{winner.alias}} vs {{looser.alias}}</label>
</div>
<hr>
<hr>
<div >
<label class="chat-result-success">{{winner.alias}} ({{winner.competence.name}}, {{winner.total}}) l'emporte sur {{looser.alias}} ({{looser.competence.name}}, {{looser.total}})</label>
</div>
<div>
<label class="chat-result-success">{{winner.alias}} ({{winner.competence.name}}, {{winner.total}}) l'emporte sur
{{looser.alias}} ({{looser.competence.name}}, {{looser.total}})</label>
{{#if winner.isReussiteCritique}}
<div><strong class="chat-result-success">Réussite critique ! 1 XP gagné en {{winner.carac.name}}.</strong> </div>
{{/if}}
{{#if looser.isEchecCritique}}
<div><strong class="chat-result-failure">Echec critique ! 1 XP gagné en {{looser.carac.name}}.</strong> </div>
{{/if}}
</div>

View File

@@ -1,75 +1,176 @@
<form class="skill-roll-dialog">
<header class="roll-dialog-header">
{{#if img}}
<img class="actor-icon" src="{{img}}" data-edit="img" title="{{name}}" />
<img class="actor-icon" src="{{img}}" data-edit="img" title="{{name}}" />
{{/if}}
<h1 class="dialog-roll-title roll-dialog-header">{{title}}</h1>
</header>
<div class="flexcol">
<div class="flexrow">
<span class="roll-dialog-label">Caracteristique </span>
<span class="roll-dialog-label">{{carac.name}} : {{carac.qualite}} ({{carac.dice}})</span>
<span class="roll-dialog-label">Caractéristique </span>
<span class="roll-dialog-label">{{carac.name}}
:
{{carac.qualite}}
({{carac.dice}})</span>
</div>
{{#if competence}}
<div class="flexrow">
<span class="roll-dialog-label">Compétence </span>
<span class="roll-dialog-label">{{competence.name}} ({{compScore}})</span>
</div>
<div class="flexrow">
<span class="roll-dialog-label">🎯 Compétence </span>
<span class="roll-dialog-label">{{competence.name}}
({{compScore}})</span>
</div>
{{/if}}
{{#if santeModifier}}
<div class="flexrow">
<span class="roll-dialog-label">Malus Blessures </span>
<span class="roll-dialog-label">{{santeModifier}} niveaux</span>
</div>
<div class="flexrow">
<span class="roll-dialog-label">💔 Malus Blessures </span>
<span class="roll-dialog-label">{{santeModifier}} niveaux</span>
</div>
{{/if}}
<div class="flexrow">
<span class="roll-dialog-label">Bonus/Malus : </span>
<select class="" type="text" id="roll-bonus-malus" value="{{bonusMalus}}" data-dtype="Number">
{{selectOptions config.bonusMalus selected=bonusMalus labelAttr="label" valueAttr="value" nameAttr="value"}}
<span class="roll-dialog-label"> Bonus/Malus : </span>
<select
class=""
type="text"
id="roll-bonus-malus"
value="{{bonusMalus}}"
data-dtype="Number"
>
{{selectOptions
config.bonusMalus
selected=bonusMalus
labelAttr="label"
valueAttr="value"
nameAttr="value"
}}
</select>
</div>
{{#if providence.value}}
<div class="flexrow">
<span class="roll-dialog-label">Utiliser la Providence ({{providence.dice}})</span>
<input type="checkbox" id="roll-enable-providence" {{checked enableProvidence}} />
</div>
<div class="flexrow">
<span class="roll-dialog-label">Utiliser la Providence ({{providence.dice}})</span>
<input
type="checkbox"
id="roll-enable-providence"
{{checked enableProvidence}}
/>
</div>
{{/if}}
{{#if arme}}
{{#if isTir}}
<div class="flexrow">
<span class="roll-dialog-label">Portée : </span>
<select class="" type="text" id="roll-portee-tir" value="{{porteeTir}}" data-dtype="String">
<span class="roll-dialog-label">🏹 Portée : </span>
<select
class=""
type="text"
id="roll-portee-tir"
value="{{porteeTir}}"
data-dtype="String"
>
{{#select porteeTir}}
{{#each config.ARME_PORTEES as |portee key|}}
<option value="{{key}}">{{portee.label}}</option>
{{/each}}
{{#each config.ARME_PORTEES as |portee key|}}
<option value="{{key}}">{{portee.label}}</option>
{{/each}}
{{/select}}
</select>
</div>
<div class="flexrow">
<span class="roll-dialog-label">Viser : </span>
<span class="roll-dialog-label">👁️ Viser : </span>
<input type="checkbox" id="roll-tir-viser" {{checked isViser}} />
</div>
<div class="flexrow">
<span class="roll-dialog-label">Cible petite/en mouvement : </span>
<input type="checkbox" id="roll-tir-mouvement" {{checked isMouvement}} />
<span class="roll-dialog-label">🏃 Cible petite/en mouvement : </span>
<input
type="checkbox"
id="roll-tir-mouvement"
{{checked isMouvement}}
/>
</div>
{{else}}
<div class="flexrow">
<span class="roll-dialog-label">⚔️ Allonge
{{allongeLabel}}
: Indiquez l'allonge de votre adversaire ci-dessous.</span>
</div>
<div class="flexrow">
<span
class="roll-dialog-label"
data-tooltip="Modification d'allonge selon votre arme et celle de votre adversaire"
>🗡️ Allonge arme adversaire :
</span>
<select
class=""
type="text"
id="roll-allonge"
value="{{allongeId}}"
data-dtype="String"
>
{{#select allongeId}}
{{#each allonges as |allonge key|}}
<option value="{{key}}">{{allonge.label}}</option>
{{/each}}
{{/select}}
</select>
</div>
<div class="flexrow">
<span class="roll-dialog-label">🏃 Charge à pied ?</span>
<input
type="checkbox"
id="roll-charge-a-pied"
{{checked isChargeAPied}}
/>
</div>
<div class="flexrow">
<span class="roll-dialog-label">🐴 Charge à cheval ?</span>
<input
type="checkbox"
id="roll-charge-a-cheval"
{{checked isChargeACheval}}
/>
</div>
{{/if}}
<div class="flexrow">
<span class="roll-dialog-label">✋ Main gauche ?</span>
<input type="checkbox" id="roll-main-gauche" {{checked isMainGauche}} />
</div>
<div class="flexrow">
<span class="roll-dialog-label">🎯 Attaque ciblée (-1 Niveau): </span>
<select
class=""
type="text"
id="roll-attaque-ciblee"
value="{{attaqueCiblee}}"
data-dtype="String"
>
{{#select attaqueCiblee}}
{{#each config.ATTAQUE_CIBLEES as |attaque key|}}
<option value="{{key}}">{{attaque.label}}</option>
{{/each}}
{{/select}}
</select>
</div>
{{else}}
<div class="flexrow">
<span class="roll-dialog-label">Difficulté : </span>
<select class="" type="text" id="roll-difficulty" value="{{difficulty}}" data-dtype="String">
{{selectOptions config.difficulte selected=difficulty valueAttr="key" labelAttr="label"}}
</select>
</div>
<div class="flexrow">
<span class="roll-dialog-label">📊 Difficulté : </span>
<select
class=""
type="text"
id="roll-difficulty"
value="{{difficulty}}"
data-dtype="String"
>
{{selectOptions
config.difficulte
selected=difficulty
valueAttr="key"
labelAttr="label"
}}
</select>
</div>
{{/if}}
</div>

View File

@@ -38,22 +38,22 @@
</select>
</li>
<h3>Spécificités</h3>
<h3>⚔️ Spécificités</h3>
<li class="flexrow">
<label class="item-name-label-long">Dégâts</label>
<label class="item-name-label-long">💥 Dégâts</label>
<input type="text" class="padd-right numeric-input item-field-label-short"
name="system.degats" value="{{system.degats}}" data-dtype="String" />
</li>
<li class="flexrow">
<label class="item-name-label-long">Valeur d'echec critique (ie 1 par défaut)</label>
<label class="item-name-label-long">⚠️ Valeur d'échec critique (ie 1 par défaut)</label>
<input type="text" class="padd-right numeric-input item-field-label-short"
name="system.valeurEchecCritique" value="{{system.valeurEchecCritique}}" data-dtype="Numeric" />
</li>
{{#if (eq system.typeArme "melee")}}
<li class="flexrow">
<label class="item-name-label-long">Allonge</label>
<label class="item-name-label-long">🗡️ Allonge</label>
<select name="system.allonge">
{{selectOptions config.armeAllonges selected=system.allonge labelAttr="label"}}
</select>
@@ -62,12 +62,12 @@
{{#if (eq system.typeArme "tir")}}
<li class="flexrow">
<label class="item-name-label-long">Temps de recharge</label>
<label class="item-name-label-long">⏱️ Temps de recharge</label>
<input type="text" class="padd-right numeric-input item-field-label-short"
name="system.tempsRecharge" value="{{system.tempsRecharge}}" data-dtype="Number" />
</li>
<li class="flexrow">
<label class="item-name-label-long">Compétence de recharge</label>
<label class="item-name-label-long">🔄 Compétence de recharge</label>
<select name="system.competenceRecharge">
{{selectOptions config.competencesRecharge selected=system.competenceRecharge labelAttr="label"}}
</select>
@@ -90,7 +90,7 @@
{{/each}}
{{#if (eq system.typeArme "tir")}}
<h3>Portées</h3>
<h3>🎯 Portées</h3>
{{#each system.portees as |portee porteeId|}}
<li class="flexrow">
<label class="item-name-label-long">{{getConfigLabel "ARME_PORTEES" porteeId}}</label>
@@ -100,7 +100,7 @@
{{/each}}
{{/if}}
<h3>Degats sur armures</h3>
<h3>🛡️ Degats sur armures</h3>
{{#each system.degatsArmure as |degat degtId|}}
<li class="flexrow">
<label class="item-name-label-long">{{getConfigLabel "degatsArmure" degtId}}</label>
@@ -109,21 +109,21 @@
</li>
{{/each}}
<h3>Autres</h3>
<h3>📝 Autres</h3>
<li class="flexrow">
<label class="item-name-label-long">Equipé?</label>
<label class="item-name-label-long">Equipé?</label>
<input type="checkbox" name="system.equipe" {{checked system.equipe}} />
</li>
<li class="flexrow">
<label class="item-name-label-long">Bonus d'Initiative</label>
<label class="item-name-label-long">Bonus d'Initiative</label>
<input type="text" class="padd-right numeric-input item-field-label-short"
name="system.initiativeBonus" value="{{system.initiativeBonus}}" data-dtype="Number" />
</li>
<li class="flexrow">
<label class="item-name-label-long">Prix</label>
<label class="item-name-label-long">💰 Prix</label>
<input type="text" class="padd-right numeric-input item-field-label-short"
name="system.prix" value="{{system.prix}}" data-dtype="Number" />
<select name="system.monnaie">

View File

@@ -33,13 +33,13 @@
{{/each}}
<li class="flexrow">
<label class="item-name-label-long">Protection</label>
<label class="item-name-label-long">🛡️ Protection</label>
<input type="text" class="padd-right numeric-input item-field-label-short"
name="system.protection" value="{{system.protection}}" data-dtype="Number" />
</li>
<li class="flexrow">
<label class="item-name-label-long">Cout en pièces d'Armure Lourde</label>
<label class="item-name-label-long">⚖️ Cout en pièces d'Armure Lourde</label>
<input type="text" class="padd-right numeric-input item-field-label-short"
name="system.coutArmureLourde" value="{{system.coutArmureLourde}}" data-dtype="Number" />
</li>
@@ -57,12 +57,12 @@
</li>
<li class="flexrow">
<label class="item-name-label-long">Equipé?</label>
<label class="item-name-label-long">Equipé?</label>
<input type="checkbox" name="system.equipe" {{checked system.equipe}} />
</li>
<li class="flexrow">
<label class="item-name-label-long">Prix</label>
<label class="item-name-label-long">💰 Prix</label>
<input type="text" class="padd-right numeric-input item-field-label-short"
name="system.prix" value="{{system.prix}}" data-dtype="Number" />
<select name="system.monnaie">

Some files were not shown because too many files have changed in this diff Show More