13 Commits

Author SHA1 Message Date
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
102 changed files with 3307 additions and 2121 deletions

BIN
images/icons/xpplus1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

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
}
/* -------------------------------------------- */
@@ -604,12 +714,12 @@ export class TeDeumActor extends Actor {
let weapon = this.items.get(armeId)
if (weapon) {
let bDegats = 0
if ( weapon.system.typeArme == "melee" ) {
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
@@ -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,16 @@ 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"
}
static installHooks() {
Hooks.on('renderChatLog', (log, html, data) => TeDeumUtility.chatListeners(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 +32,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 +171,25 @@ 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 => {
console.log("Fetched welcome message:", 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 +256,7 @@ export class TeDeumUtility {
return actor
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/* -------------------------------------------- */
static async manageOpposition(rollData) {
if (!this.currentOpposition) {
// Store rollData as current GM opposition
@@ -209,29 +265,47 @@ 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)
}
}
@@ -241,7 +315,18 @@ export class TeDeumUtility {
let defenderToken = canvas.tokens.placeables.find(t => t.id == rollData.defenderTokenId)
if (defenderToken) {
let actor = defenderToken.actor
await actor.appliquerDegats(rollData)
if (game.user.isGM || actor.isOwner) {
await actor.appliquerDegats(rollData)
} else {
// Send a socket message
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 +351,17 @@ export class TeDeumUtility {
TeDeumUtility.appliquerDegats(rollData, messageId)
}
})
$(html).on("click", '.chat-command-gain-xp', 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)
// Hide this button
event.currentTarget.style.display = 'none';
}
})
}
/* -------------------------------------------- */
@@ -360,6 +456,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") {
if (game.user.isGM) {
let rollData = msg.data.rollData
let defenderToken = canvas.tokens.placeables.find(t => t.id == rollData.defenderTokenId)
if (defenderToken) {
let actor = defenderToken.actor
await actor.appliquerDegats(rollData)
} else {
ui.notifications.error("Impossible de trouver la cible de l'attaque, aucun degats appliqué")
}
}
}
}
/* -------------------------------------------- */
@@ -476,6 +594,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 +615,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 +654,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 +708,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 +736,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 +748,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

@@ -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;
}
@@ -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();

View File

@@ -1 +1 @@
MANIFEST-000116
MANIFEST-000198

View File

@@ -1,7 +1,7 @@
2025/07/02-23:06:08.560525 7f0793fff6c0 Recovering log #114
2025/07/02-23:06:08.610681 7f0793fff6c0 Delete type=3 #112
2025/07/02-23:06:08.610784 7f0793fff6c0 Delete type=0 #114
2025/07/02-23:08:13.585521 7f07923ff6c0 Level-0 table #119: started
2025/07/02-23:08:13.585561 7f07923ff6c0 Level-0 table #119: 0 bytes OK
2025/07/02-23:08:13.592021 7f07923ff6c0 Delete type=0 #117
2025/07/02-23:08:13.592190 7f07923ff6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)
2025/10/30-20:18:48.111835 7fee88ff86c0 Recovering log #196
2025/10/30-20:18:48.158268 7fee88ff86c0 Delete type=3 #194
2025/10/30-20:18:48.158356 7fee88ff86c0 Delete type=0 #196
2025/10/30-20:24:05.126356 7fee837fe6c0 Level-0 table #201: started
2025/10/30-20:24:05.126390 7fee837fe6c0 Level-0 table #201: 0 bytes OK
2025/10/30-20:24:05.132701 7fee837fe6c0 Delete type=0 #199
2025/10/30-20:24:05.133022 7fee837fe6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2025/07/02-22:48:25.676634 7f07937fe6c0 Recovering log #110
2025/07/02-22:48:25.686761 7f07937fe6c0 Delete type=3 #108
2025/07/02-22:48:25.686842 7f07937fe6c0 Delete type=0 #110
2025/07/02-23:06:03.267948 7f07923ff6c0 Level-0 table #115: started
2025/07/02-23:06:03.267975 7f07923ff6c0 Level-0 table #115: 0 bytes OK
2025/07/02-23:06:03.299914 7f07923ff6c0 Delete type=0 #113
2025/07/02-23:06:03.388289 7f07923ff6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)
2025/10/20-22:38:45.481103 7f88a77fe6c0 Recovering log #192
2025/10/20-22:38:45.491194 7f88a77fe6c0 Delete type=3 #190
2025/10/20-22:38:45.491267 7f88a77fe6c0 Delete type=0 #192
2025/10/20-22:43:34.530590 7f88a53ff6c0 Level-0 table #197: started
2025/10/20-22:43:34.530642 7f88a53ff6c0 Level-0 table #197: 0 bytes OK
2025/10/20-22:43:34.536818 7f88a53ff6c0 Delete type=0 #195
2025/10/20-22:43:34.536957 7f88a53ff6c0 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-000198 Normal file

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000219
MANIFEST-000301

View File

@@ -1,7 +1,7 @@
2025/07/02-23:06:08.061648 7f0792ffd6c0 Recovering log #217
2025/07/02-23:06:08.112616 7f0792ffd6c0 Delete type=3 #215
2025/07/02-23:06:08.112666 7f0792ffd6c0 Delete type=0 #217
2025/07/02-23:08:13.519462 7f07923ff6c0 Level-0 table #222: started
2025/07/02-23:08:13.519492 7f07923ff6c0 Level-0 table #222: 0 bytes OK
2025/07/02-23:08:13.525466 7f07923ff6c0 Delete type=0 #220
2025/07/02-23:08:13.539414 7f07923ff6c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)
2025/10/30-20:18:47.606004 7fee88ff86c0 Recovering log #299
2025/10/30-20:18:47.659734 7fee88ff86c0 Delete type=3 #297
2025/10/30-20:18:47.659812 7fee88ff86c0 Delete type=0 #299
2025/10/30-20:24:05.080609 7fee837fe6c0 Level-0 table #304: started
2025/10/30-20:24:05.080662 7fee837fe6c0 Level-0 table #304: 0 bytes OK
2025/10/30-20:24:05.087374 7fee837fe6c0 Delete type=0 #302
2025/10/30-20:24:05.104712 7fee837fe6c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2025/07/02-22:48:25.579874 7f07937fe6c0 Recovering log #213
2025/07/02-22:48:25.591330 7f07937fe6c0 Delete type=3 #211
2025/07/02-22:48:25.591377 7f07937fe6c0 Delete type=0 #213
2025/07/02-23:06:02.984029 7f07923ff6c0 Level-0 table #218: started
2025/07/02-23:06:02.984053 7f07923ff6c0 Level-0 table #218: 0 bytes OK
2025/07/02-23:06:03.018891 7f07923ff6c0 Delete type=0 #216
2025/07/02-23:06:03.055616 7f07923ff6c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)
2025/10/20-22:38:45.384370 7f88a67fc6c0 Recovering log #295
2025/10/20-22:38:45.394880 7f88a67fc6c0 Delete type=3 #293
2025/10/20-22:38:45.394943 7f88a67fc6c0 Delete type=0 #295
2025/10/20-22:43:34.456260 7f88a53ff6c0 Level-0 table #300: started
2025/10/20-22:43:34.456288 7f88a53ff6c0 Level-0 table #300: 0 bytes OK
2025/10/20-22:43:34.462274 7f88a53ff6c0 Delete type=0 #298
2025/10/20-22:43:34.475907 7f88a53ff6c0 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-000301 Normal file

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000218
MANIFEST-000300

View File

@@ -1,7 +1,14 @@
2025/07/02-23:06:08.115418 7f07937fe6c0 Recovering log #216
2025/07/02-23:06:08.203034 7f07937fe6c0 Delete type=3 #214
2025/07/02-23:06:08.203104 7f07937fe6c0 Delete type=0 #216
2025/07/02-23:08:13.507158 7f07923ff6c0 Level-0 table #221: started
2025/07/02-23:08:13.507179 7f07923ff6c0 Level-0 table #221: 0 bytes OK
2025/07/02-23:08:13.513412 7f07923ff6c0 Delete type=0 #219
2025/07/02-23:08:13.539385 7f07923ff6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)
2025/10/30-20:18:47.667302 7fee89ffa6c0 Recovering log #298
2025/10/30-20:18:47.723105 7fee89ffa6c0 Delete type=3 #296
2025/10/30-20:18:47.723199 7fee89ffa6c0 Delete type=0 #298
2025/10/30-20:24:05.064187 7fee837fe6c0 Level-0 table #303: started
2025/10/30-20:24:05.067385 7fee837fe6c0 Level-0 table #303: 1456 bytes OK
2025/10/30-20:24:05.073499 7fee837fe6c0 Delete type=0 #301
2025/10/30-20:24:05.093844 7fee837fe6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at '!items!Z0vD0CnxAXb5FK3p' @ 57 : 1
2025/10/30-20:24:05.093857 7fee837fe6c0 Compacting 1@0 + 1@1 files
2025/10/30-20:24:05.097233 7fee837fe6c0 Generated table #304@0: 29 keys, 12276 bytes
2025/10/30-20:24:05.097264 7fee837fe6c0 Compacted 1@0 + 1@1 files => 12276 bytes
2025/10/30-20:24:05.104037 7fee837fe6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/10/30-20:24:05.104241 7fee837fe6c0 Delete type=2 #279
2025/10/30-20:24:05.104553 7fee837fe6c0 Delete type=2 #303
2025/10/30-20:24:05.104756 7fee837fe6c0 Manual compaction at level-0 from '!items!Z0vD0CnxAXb5FK3p' @ 57 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2025/07/02-22:48:25.594502 7f0792ffd6c0 Recovering log #212
2025/07/02-22:48:25.604218 7f0792ffd6c0 Delete type=3 #210
2025/07/02-22:48:25.604285 7f0792ffd6c0 Delete type=0 #212
2025/07/02-23:06:02.949195 7f07923ff6c0 Level-0 table #217: started
2025/07/02-23:06:02.949224 7f07923ff6c0 Level-0 table #217: 0 bytes OK
2025/07/02-23:06:02.983912 7f07923ff6c0 Delete type=0 #215
2025/07/02-23:06:03.055603 7f07923ff6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)
2025/10/20-22:38:45.398424 7f88a5ffb6c0 Recovering log #294
2025/10/20-22:38:45.409565 7f88a5ffb6c0 Delete type=3 #292
2025/10/20-22:38:45.409638 7f88a5ffb6c0 Delete type=0 #294
2025/10/20-22:43:34.462377 7f88a53ff6c0 Level-0 table #299: started
2025/10/20-22:43:34.462405 7f88a53ff6c0 Level-0 table #299: 0 bytes OK
2025/10/20-22:43:34.468563 7f88a53ff6c0 Delete type=0 #297
2025/10/20-22:43:34.475918 7f88a53ff6c0 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

View File

@@ -1 +1 @@
MANIFEST-000215
MANIFEST-000299

View File

@@ -1,7 +1,7 @@
2025/07/02-23:06:08.011331 7f0798bfa6c0 Recovering log #213
2025/07/02-23:06:08.059546 7f0798bfa6c0 Delete type=3 #211
2025/07/02-23:06:08.059612 7f0798bfa6c0 Delete type=0 #213
2025/07/02-23:08:13.513511 7f07923ff6c0 Level-0 table #218: started
2025/07/02-23:08:13.513531 7f07923ff6c0 Level-0 table #218: 0 bytes OK
2025/07/02-23:08:13.519351 7f07923ff6c0 Delete type=0 #216
2025/07/02-23:08:13.539400 7f07923ff6c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at (end)
2025/10/30-20:18:47.533535 7fee83fff6c0 Recovering log #297
2025/10/30-20:18:47.588558 7fee83fff6c0 Delete type=3 #295
2025/10/30-20:18:47.588691 7fee83fff6c0 Delete type=0 #297
2025/10/30-20:24:05.087512 7fee837fe6c0 Level-0 table #302: started
2025/10/30-20:24:05.087542 7fee837fe6c0 Level-0 table #302: 0 bytes OK
2025/10/30-20:24:05.093717 7fee837fe6c0 Delete type=0 #300
2025/10/30-20:24:05.104733 7fee837fe6c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2025/07/02-22:48:25.565222 7f0798bfa6c0 Recovering log #209
2025/07/02-22:48:25.575102 7f0798bfa6c0 Delete type=3 #207
2025/07/02-22:48:25.575167 7f0798bfa6c0 Delete type=0 #209
2025/07/02-23:06:03.019023 7f07923ff6c0 Level-0 table #214: started
2025/07/02-23:06:03.019048 7f07923ff6c0 Level-0 table #214: 0 bytes OK
2025/07/02-23:06:03.055450 7f07923ff6c0 Delete type=0 #212
2025/07/02-23:06:03.055630 7f07923ff6c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at (end)
2025/10/20-22:38:45.369087 7f88a77fe6c0 Recovering log #293
2025/10/20-22:38:45.378744 7f88a77fe6c0 Delete type=3 #291
2025/10/20-22:38:45.378814 7f88a77fe6c0 Delete type=0 #293
2025/10/20-22:43:34.468664 7f88a53ff6c0 Level-0 table #298: started
2025/10/20-22:43:34.468688 7f88a53ff6c0 Level-0 table #298: 0 bytes OK
2025/10/20-22:43:34.475781 7f88a53ff6c0 Delete type=0 #296
2025/10/20-22:43:34.475927 7f88a53ff6c0 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

View File

View File

View File

@@ -1 +1 @@
MANIFEST-000227
MANIFEST-000310

View File

@@ -1,14 +1,14 @@
2025/07/02-23:06:08.205635 7f0798bfa6c0 Recovering log #225
2025/07/02-23:06:08.258516 7f0798bfa6c0 Delete type=3 #223
2025/07/02-23:06:08.258587 7f0798bfa6c0 Delete type=0 #225
2025/07/02-23:08:13.497309 7f07923ff6c0 Level-0 table #230: started
2025/07/02-23:08:13.500727 7f07923ff6c0 Level-0 table #230: 31862 bytes OK
2025/07/02-23:08:13.507034 7f07923ff6c0 Delete type=0 #228
2025/07/02-23:08:13.525588 7f07923ff6c0 Manual compaction at level-0 from '!folders!9PQi3Lv54rpcxavo' @ 72057594037927935 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at '!items!dbl7clezSXISzlqE' @ 511 : 1
2025/07/02-23:08:13.525598 7f07923ff6c0 Compacting 1@0 + 1@1 files
2025/07/02-23:08:13.532830 7f07923ff6c0 Generated table #231@0: 71 keys, 264331 bytes
2025/07/02-23:08:13.532886 7f07923ff6c0 Compacted 1@0 + 1@1 files => 264331 bytes
2025/07/02-23:08:13.538890 7f07923ff6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/07/02-23:08:13.539063 7f07923ff6c0 Delete type=2 #214
2025/07/02-23:08:13.539294 7f07923ff6c0 Delete type=2 #230
2025/07/02-23:08:13.539429 7f07923ff6c0 Manual compaction at level-0 from '!items!dbl7clezSXISzlqE' @ 511 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at (end)
2025/10/30-20:18:47.729266 7fee83fff6c0 Recovering log #308
2025/10/30-20:18:47.838564 7fee83fff6c0 Delete type=3 #306
2025/10/30-20:18:47.838645 7fee83fff6c0 Delete type=0 #308
2025/10/30-20:24:05.139878 7fee837fe6c0 Level-0 table #313: started
2025/10/30-20:24:05.143788 7fee837fe6c0 Level-0 table #313: 5933 bytes OK
2025/10/30-20:24:05.150257 7fee837fe6c0 Delete type=0 #311
2025/10/30-20:24:05.167769 7fee837fe6c0 Manual compaction at level-0 from '!folders!9PQi3Lv54rpcxavo' @ 72057594037927935 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at '!items!v4mzjKOYibOsJ9Wn' @ 516 : 1
2025/10/30-20:24:05.167783 7fee837fe6c0 Compacting 1@0 + 1@1 files
2025/10/30-20:24:05.175449 7fee837fe6c0 Generated table #314@0: 71 keys, 264301 bytes
2025/10/30-20:24:05.175485 7fee837fe6c0 Compacted 1@0 + 1@1 files => 264301 bytes
2025/10/30-20:24:05.182651 7fee837fe6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/10/30-20:24:05.182920 7fee837fe6c0 Delete type=2 #289
2025/10/30-20:24:05.183329 7fee837fe6c0 Delete type=2 #313
2025/10/30-20:24:05.183569 7fee837fe6c0 Manual compaction at level-0 from '!items!v4mzjKOYibOsJ9Wn' @ 516 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2025/07/02-22:48:25.606929 7f0793fff6c0 Recovering log #221
2025/07/02-22:48:25.616919 7f0793fff6c0 Delete type=3 #219
2025/07/02-22:48:25.617003 7f0793fff6c0 Delete type=0 #221
2025/07/02-23:06:02.914258 7f07923ff6c0 Level-0 table #226: started
2025/07/02-23:06:02.914309 7f07923ff6c0 Level-0 table #226: 0 bytes OK
2025/07/02-23:06:02.949061 7f07923ff6c0 Delete type=0 #224
2025/07/02-23:06:03.055588 7f07923ff6c0 Manual compaction at level-0 from '!folders!9PQi3Lv54rpcxavo' @ 72057594037927935 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at (end)
2025/10/20-22:38:45.412732 7f88a77fe6c0 Recovering log #304
2025/10/20-22:38:45.422278 7f88a77fe6c0 Delete type=3 #302
2025/10/20-22:38:45.422357 7f88a77fe6c0 Delete type=0 #304
2025/10/20-22:43:34.450000 7f88a53ff6c0 Level-0 table #309: started
2025/10/20-22:43:34.450073 7f88a53ff6c0 Level-0 table #309: 0 bytes OK
2025/10/20-22:43:34.456130 7f88a53ff6c0 Delete type=0 #307
2025/10/20-22:43:34.475895 7f88a53ff6c0 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

0
packs/graces/000302.log Normal file
View File

View File

@@ -1 +1 @@
MANIFEST-000218
MANIFEST-000300

View File

@@ -1,7 +1,7 @@
2025/07/02-23:06:08.261714 7f0792ffd6c0 Recovering log #216
2025/07/02-23:06:08.311445 7f0792ffd6c0 Delete type=3 #214
2025/07/02-23:06:08.311538 7f0792ffd6c0 Delete type=0 #216
2025/07/02-23:08:13.545827 7f07923ff6c0 Level-0 table #221: started
2025/07/02-23:08:13.545856 7f07923ff6c0 Level-0 table #221: 0 bytes OK
2025/07/02-23:08:13.552104 7f07923ff6c0 Delete type=0 #219
2025/07/02-23:08:13.565260 7f07923ff6c0 Manual compaction at level-0 from '!items!17mjvwS8R3B6LloG' @ 72057594037927935 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at (end)
2025/10/30-20:18:47.860314 7fee897f96c0 Recovering log #298
2025/10/30-20:18:47.913091 7fee897f96c0 Delete type=3 #296
2025/10/30-20:18:47.913276 7fee897f96c0 Delete type=0 #298
2025/10/30-20:24:05.073687 7fee837fe6c0 Level-0 table #303: started
2025/10/30-20:24:05.073741 7fee837fe6c0 Level-0 table #303: 0 bytes OK
2025/10/30-20:24:05.080367 7fee837fe6c0 Delete type=0 #301
2025/10/30-20:24:05.104689 7fee837fe6c0 Manual compaction at level-0 from '!items!17mjvwS8R3B6LloG' @ 72057594037927935 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2025/07/02-22:48:25.621861 7f0798bfa6c0 Recovering log #212
2025/07/02-22:48:25.632707 7f0798bfa6c0 Delete type=3 #210
2025/07/02-22:48:25.632773 7f0798bfa6c0 Delete type=0 #212
2025/07/02-23:06:03.143237 7f07923ff6c0 Level-0 table #217: started
2025/07/02-23:06:03.143280 7f07923ff6c0 Level-0 table #217: 0 bytes OK
2025/07/02-23:06:03.180090 7f07923ff6c0 Delete type=0 #215
2025/07/02-23:06:03.267926 7f07923ff6c0 Manual compaction at level-0 from '!items!17mjvwS8R3B6LloG' @ 72057594037927935 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at (end)
2025/10/20-22:38:45.426760 7f88a67fc6c0 Recovering log #294
2025/10/20-22:38:45.437521 7f88a67fc6c0 Delete type=3 #292
2025/10/20-22:38:45.437578 7f88a67fc6c0 Delete type=0 #294
2025/10/20-22:43:34.481978 7f88a53ff6c0 Level-0 table #299: started
2025/10/20-22:43:34.482001 7f88a53ff6c0 Level-0 table #299: 0 bytes OK
2025/10/20-22:43:34.488034 7f88a53ff6c0 Delete type=0 #297
2025/10/20-22:43:34.501875 7f88a53ff6c0 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

View File

@@ -1 +1 @@
MANIFEST-000218
MANIFEST-000300

View File

@@ -1,7 +1,7 @@
2025/07/02-23:06:08.314387 7f07937fe6c0 Recovering log #216
2025/07/02-23:06:08.375793 7f07937fe6c0 Delete type=3 #214
2025/07/02-23:06:08.375871 7f07937fe6c0 Delete type=0 #216
2025/07/02-23:08:13.539538 7f07923ff6c0 Level-0 table #221: started
2025/07/02-23:08:13.539632 7f07923ff6c0 Level-0 table #221: 0 bytes OK
2025/07/02-23:08:13.545699 7f07923ff6c0 Delete type=0 #219
2025/07/02-23:08:13.565250 7f07923ff6c0 Manual compaction at level-0 from '!items!1icaxIywAwDXQcMz' @ 72057594037927935 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at (end)
2025/10/30-20:18:47.916696 7fee89ffa6c0 Recovering log #298
2025/10/30-20:18:47.966821 7fee89ffa6c0 Delete type=3 #296
2025/10/30-20:18:47.966944 7fee89ffa6c0 Delete type=0 #298
2025/10/30-20:24:05.104925 7fee837fe6c0 Level-0 table #303: started
2025/10/30-20:24:05.104996 7fee837fe6c0 Level-0 table #303: 0 bytes OK
2025/10/30-20:24:05.112111 7fee837fe6c0 Delete type=0 #301
2025/10/30-20:24:05.132946 7fee837fe6c0 Manual compaction at level-0 from '!items!1icaxIywAwDXQcMz' @ 72057594037927935 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2025/07/02-22:48:25.636123 7f07937fe6c0 Recovering log #212
2025/07/02-22:48:25.645614 7f07937fe6c0 Delete type=3 #210
2025/07/02-22:48:25.645667 7f07937fe6c0 Delete type=0 #212
2025/07/02-23:06:03.055707 7f07923ff6c0 Level-0 table #217: started
2025/07/02-23:06:03.055763 7f07923ff6c0 Level-0 table #217: 0 bytes OK
2025/07/02-23:06:03.089395 7f07923ff6c0 Delete type=0 #215
2025/07/02-23:06:03.217665 7f07923ff6c0 Manual compaction at level-0 from '!items!1icaxIywAwDXQcMz' @ 72057594037927935 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at (end)
2025/10/20-22:38:45.440391 7f88a6ffd6c0 Recovering log #294
2025/10/20-22:38:45.450539 7f88a6ffd6c0 Delete type=3 #292
2025/10/20-22:38:45.450600 7f88a6ffd6c0 Delete type=0 #294
2025/10/20-22:43:34.476040 7f88a53ff6c0 Level-0 table #299: started
2025/10/20-22:43:34.476068 7f88a53ff6c0 Level-0 table #299: 0 bytes OK
2025/10/20-22:43:34.481903 7f88a53ff6c0 Delete type=0 #297
2025/10/20-22:43:34.501865 7f88a53ff6c0 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

0
packs/scenes/000239.log Normal file
View File

View File

@@ -1 +1 @@
MANIFEST-000155
MANIFEST-000237

View File

@@ -1,7 +1,7 @@
2025/07/02-23:06:08.461850 7f0792ffd6c0 Recovering log #153
2025/07/02-23:06:08.557282 7f0792ffd6c0 Delete type=3 #151
2025/07/02-23:06:08.557355 7f0792ffd6c0 Delete type=0 #153
2025/07/02-23:08:13.559253 7f07923ff6c0 Level-0 table #158: started
2025/07/02-23:08:13.559274 7f07923ff6c0 Level-0 table #158: 0 bytes OK
2025/07/02-23:08:13.565147 7f07923ff6c0 Delete type=0 #156
2025/07/02-23:08:13.565275 7f07923ff6c0 Manual compaction at level-0 from '!scenes!FJXugdbkBpEJEdR6' @ 72057594037927935 : 1 .. '!scenes!FJXugdbkBpEJEdR6' @ 0 : 0; will stop at (end)
2025/10/30-20:18:48.043058 7fee83fff6c0 Recovering log #235
2025/10/30-20:18:48.100398 7fee83fff6c0 Delete type=3 #233
2025/10/30-20:18:48.100494 7fee83fff6c0 Delete type=0 #235
2025/10/30-20:24:05.118858 7fee837fe6c0 Level-0 table #240: started
2025/10/30-20:24:05.118895 7fee837fe6c0 Level-0 table #240: 0 bytes OK
2025/10/30-20:24:05.126205 7fee837fe6c0 Delete type=0 #238
2025/10/30-20:24:05.132999 7fee837fe6c0 Manual compaction at level-0 from '!scenes!FJXugdbkBpEJEdR6' @ 72057594037927935 : 1 .. '!scenes!FJXugdbkBpEJEdR6' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2025/07/02-22:48:25.663904 7f0793fff6c0 Recovering log #149
2025/07/02-22:48:25.673958 7f0793fff6c0 Delete type=3 #147
2025/07/02-22:48:25.674014 7f0793fff6c0 Delete type=0 #149
2025/07/02-23:06:03.180321 7f07923ff6c0 Level-0 table #154: started
2025/07/02-23:06:03.180370 7f07923ff6c0 Level-0 table #154: 0 bytes OK
2025/07/02-23:06:03.217524 7f07923ff6c0 Delete type=0 #152
2025/07/02-23:06:03.267938 7f07923ff6c0 Manual compaction at level-0 from '!scenes!FJXugdbkBpEJEdR6' @ 72057594037927935 : 1 .. '!scenes!FJXugdbkBpEJEdR6' @ 0 : 0; will stop at (end)
2025/10/20-22:38:45.466574 7f88a67fc6c0 Recovering log #231
2025/10/20-22:38:45.477284 7f88a67fc6c0 Delete type=3 #229
2025/10/20-22:38:45.477341 7f88a67fc6c0 Delete type=0 #231
2025/10/20-22:43:34.495773 7f88a53ff6c0 Level-0 table #236: started
2025/10/20-22:43:34.495801 7f88a53ff6c0 Level-0 table #236: 0 bytes OK
2025/10/20-22:43:34.501743 7f88a53ff6c0 Delete type=0 #234
2025/10/20-22:43:34.501890 7f88a53ff6c0 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

0
packs/simples/000303.log Normal file
View File

View File

@@ -1 +1 @@
MANIFEST-000219
MANIFEST-000301

View File

@@ -1,7 +1,7 @@
2025/07/02-23:06:08.378229 7f0793fff6c0 Recovering log #216
2025/07/02-23:06:08.459001 7f0793fff6c0 Delete type=3 #214
2025/07/02-23:06:08.459067 7f0793fff6c0 Delete type=0 #216
2025/07/02-23:08:13.552198 7f07923ff6c0 Level-0 table #222: started
2025/07/02-23:08:13.552225 7f07923ff6c0 Level-0 table #222: 0 bytes OK
2025/07/02-23:08:13.559173 7f07923ff6c0 Delete type=0 #220
2025/07/02-23:08:13.565269 7f07923ff6c0 Manual compaction at level-0 from '!items!1bAL2MQVpVBd0c5Z' @ 72057594037927935 : 1 .. '!items!zs67k4sxCid6oTK3' @ 0 : 0; will stop at (end)
2025/10/30-20:18:47.970822 7fee88ff86c0 Recovering log #299
2025/10/30-20:18:48.023766 7fee88ff86c0 Delete type=3 #297
2025/10/30-20:18:48.023869 7fee88ff86c0 Delete type=0 #299
2025/10/30-20:24:05.112322 7fee837fe6c0 Level-0 table #304: started
2025/10/30-20:24:05.112357 7fee837fe6c0 Level-0 table #304: 0 bytes OK
2025/10/30-20:24:05.118656 7fee837fe6c0 Delete type=0 #302
2025/10/30-20:24:05.132978 7fee837fe6c0 Manual compaction at level-0 from '!items!1bAL2MQVpVBd0c5Z' @ 72057594037927935 : 1 .. '!items!zs67k4sxCid6oTK3' @ 0 : 0; will stop at (end)

View File

@@ -1,14 +1,7 @@
2025/07/02-22:48:25.650049 7f0792ffd6c0 Recovering log #212
2025/07/02-22:48:25.660583 7f0792ffd6c0 Delete type=3 #210
2025/07/02-22:48:25.660640 7f0792ffd6c0 Delete type=0 #212
2025/07/02-23:06:03.089582 7f07923ff6c0 Level-0 table #217: started
2025/07/02-23:06:03.105841 7f07923ff6c0 Level-0 table #217: 1554 bytes OK
2025/07/02-23:06:03.143061 7f07923ff6c0 Delete type=0 #215
2025/07/02-23:06:03.217682 7f07923ff6c0 Manual compaction at level-0 from '!items!1bAL2MQVpVBd0c5Z' @ 72057594037927935 : 1 .. '!items!zs67k4sxCid6oTK3' @ 0 : 0; will stop at '!items!zBWj3vo5FcIGYFPS' @ 81 : 1
2025/07/02-23:06:03.217690 7f07923ff6c0 Compacting 1@0 + 1@1 files
2025/07/02-23:06:03.236486 7f07923ff6c0 Generated table #218@0: 36 keys, 20892 bytes
2025/07/02-23:06:03.236511 7f07923ff6c0 Compacted 1@0 + 1@1 files => 20892 bytes
2025/07/02-23:06:03.267525 7f07923ff6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/07/02-23:06:03.267666 7f07923ff6c0 Delete type=2 #205
2025/07/02-23:06:03.267848 7f07923ff6c0 Delete type=2 #217
2025/07/02-23:06:03.300028 7f07923ff6c0 Manual compaction at level-0 from '!items!zBWj3vo5FcIGYFPS' @ 81 : 1 .. '!items!zs67k4sxCid6oTK3' @ 0 : 0; will stop at (end)
2025/10/20-22:38:45.453322 7f88a77fe6c0 Recovering log #295
2025/10/20-22:38:45.462900 7f88a77fe6c0 Delete type=3 #293
2025/10/20-22:38:45.462956 7f88a77fe6c0 Delete type=0 #295
2025/10/20-22:43:34.488213 7f88a53ff6c0 Level-0 table #300: started
2025/10/20-22:43:34.488242 7f88a53ff6c0 Level-0 table #300: 0 bytes OK
2025/10/20-22:43:34.495670 7f88a53ff6c0 Delete type=0 #298
2025/10/20-22:43:34.501883 7f88a53ff6c0 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

@@ -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|}}
@@ -267,11 +279,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 +311,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 +333,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 +412,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 +429,7 @@
</div>
</li>
{{/each}}
</ul>
</ul>
</div>
@@ -428,7 +442,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 +452,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 +475,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

@@ -5,27 +5,95 @@
<h4 class="chat-actor-name">{{alias}}</h4>
</div>
<hr>
{{#if img}}
<div >
<img class="chat-icon" src="{{img}}" alt="{{name}}" />
</div>
{{/if}}
<hr>
<div class="flexcol">
</div>
{{#if img}}
<div>
<img class="chat-icon" src="{{img}}" alt="{{name}}" />
</div>
{{/if}}
<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="flexcol">
</div>
</div>
<div>
<ul>
<li><strong>{{alias}}</strong> attaque <strong>{{defenderName}}</strong></li>
{{#if arme}}
<li><label class="chat-weapon-name">Dégats {{arme.name}} : {{degats}} ({{degatsFormula}})</label></li>
{{/if}}
{{#if loc}}
<li>Localisation : {{loc.label}}</li>
<li>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><strong class="chat-result-success">Réussite critique : La blessure a été augmentée d'un niveau</strong></li>
{{/if}}
{{#if blessure}}
<li><strong>{{defenderName}} a subi une blessure!</strong></li>
<li>Gravité : {{blessure.name}}</li>
{{#if (eq loc.categorie "tete")}}
{{#if (gt blessure.system.value 0)}}
<li><strong class="chat-result-warning">{{defenderName}} doit réussir un test d'Endurance de difficulté 7 ou être
assommé</strong></li>
{{/if}}
{{/if}}
{{#if (eq loc.categorie "bras")}}
{{#if (gt blessure.system.value 2)}}
<li><strong class="chat-result-warning">{{defenderName}} lache l'objet tenu par son bras. Il doit faire un test
d'endurance
pour l'utiliser désormais.</strong></li>
{{/if}}
{{/if}}
{{#if (eq loc.categorie "jambe")}}
{{#if (gt blessure.system.value 2)}}
<li><strong class="chat-result-warning">{{defenderName}} tombe au sol. Pour se relever et marcher, il doit réussir
un test
d'Endurance à chaque tour.
</strong></li>
{{/if}}
{{/if}}
{{#if (eq loc.categorie "main")}}
{{#if (gt blessure.system.value 1)}}
<li><strong class="chat-result-warning">{{defenderName}} lache l'objet tenu par sa main. Il doit faire un test
d'endurance
pour l'utiliser désormais.</strong></li>
{{/if}}
{{/if}}
{{#if (eq loc.categorie "pied")}}
{{#if (gt blessure.system.value 1)}}
<li><strong class="chat-result-warning">{{defenderName}} tombe au sol. Pour se relever et marcher, il doit réussir
un test
d'Endurance à chaque tour.
</strong></li>
{{/if}}
{{/if}}
{{else}}
<li>Aucune blessure subie par {{defenderName}}</li>
{{/if}}
</ul>
</div>
</div>

View File

@@ -5,19 +5,34 @@
<h4 class="chat-actor-name">{{alias}}</h4>
</div>
<hr>
{{#if img}}
<div >
<img class="chat-icon" src="{{arme.img}}" alt="{{name}}" />
</div>
{{/if}}
<hr>
<div>
<ul>
<li>Dégats de {{arme.name}}: {{formula}} </li>
<li>Dégats infligés : {{degats}}</li>
</ul>
</div>
{{#if img}}
<div>
<img class="chat-icon" src="{{arme.img}}" alt="{{name}}" />
</div>
{{/if}}
</div>
<div>
<ul>
<li>Dégats de {{arme.name}}: {{formula}} </li>
{{#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}}
<li>Dégats infligés : {{degats}}</li>
{{#if loc}}
<li>Localisation : {{loc.label}}</li>
{{/if}}
{{#if isReussiteCritique}}
<li><strong class="chat-result-success">Réussite critique : La blessure sera augmentée d'un niveau</strong></li>
{{/if}}
</ul>
</div>
</div>

View File

@@ -5,92 +5,130 @@
<h4 class="chat-actor-name">{{alias}}</h4>
</div>
<hr>
<hr>
{{#if img}}
<div >
<img class="chat-icon" src="{{img}}" alt="{{name}}" />
</div>
{{/if}}
{{#if img}}
<div>
<img class="chat-icon" src="{{img}}" alt="{{name}}" />
</div>
{{/if}}
<div class="flexcol">
</div>
<div class="flexcol">
</div>
<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}}
<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}}
<li>Dés: {{diceFormula}} </li>
{{#if isTir}}
<li>Portée: {{porteeLabel}} ( {{difficulty}} )</li>
{{else}}
<li>Difficulté: {{difficulty}} </li>
{{/if}}
{{#if hasActions}}
<li data-tooltip="Nombre d'actions restantes, avec MG = Main Gauche">Actions restantes: {{remainingActions}}
(MG:{{remainingActionsMainGauche}})</li>
{{/if}}
</ul>
</div>
{{#if arme}}
{{#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 attaqueCiblee}}
<li>Attaque ciblée, -1 niveau</li>
{{/if}}
{{#if allongeMalus}}
<li>Malus d'allonge: {{allongeMalus}} niveau</li>
{{/if}}
{{/if}}
<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}}
<li>Dés: {{diceFormula}} </li>
{{#if isTir}}
<li>Portée: {{porteeLabel}} ( {{difficulty}} )</li>
{{else}}
<li>Difficulté: {{difficulty}} </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}}
</ul>
</div>
{{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}}
<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 data-tooltip="Si le jet n'est pas opposé, cliquez sur le bouton pour gagner 1 XP gagné en {{carac.name}}">
<strong class="chat-result-success">Réussite critique (XP potentiel) !</strong>
</li>
{{/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}}
<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}}
{{#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}}
{{else}}
<li><strong class="chat-result-failure">Echec !</strong> </li>
{{#if isEchecCritique}}
<li data-tooltip="Si le jet n'est pas opposé, cliquez sur le bouton pour gagner 1 XP gagné en {{carac.name}}">
<strong class="chat-result-failure">Echec critique (XP potentiel) !</strong>
</li>
{{/if}}
{{/if}}
{{#if nbEsquives}}
<li>Rappel : vous devez réussir {{nbEsquives}} tests d'esquive pour arriver au contact (règle d'allonge des armes).
</li>
{{/if}}
{{#if loc}}
<li><strong>Attaque réussie !!</strong> </li>
<li>Localisation: {{loc.label}} </li>
{{/if}}
{{#if degats}}
<li>Dégats: {{degats}} {{#if isReussiteCritique}}(Augmentez la gravité de la blessure d'un niveau){{/if}}</li>
{{/if}}
</ul>
<div>
{{#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}}
<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>
</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>

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