31 Commits

Author SHA1 Message Date
e794611bf3 Gestion assistée pour les actions
All checks were successful
Release Creation / build (release) Successful in 46s
2025-09-24 15:11:58 +02:00
529a62045e Gestion assistée pour les actions 2025-09-24 15:09:00 +02:00
d462d22a0a Manye enhancements for combat
All checks were successful
Release Creation / build (release) Successful in 42s
2025-09-18 17:26:02 +02:00
710ee54531 Manye enhancements for combat 2025-09-18 17:24:42 +02:00
7994aa7db4 Fix savoir lors de la creation de perso
All checks were successful
Release Creation / build (release) Successful in 1m30s
2025-09-08 23:47:19 +02:00
5176b4ce87 Amelioration histoire creation de perso, CSS bouton et genre de la providence
All checks were successful
Release Creation / build (release) Successful in 56s
2025-07-20 11:21:08 +02:00
3d6f195fc2 Educcation fix + CSS v13
All checks were successful
Release Creation / build (release) Successful in 43s
2025-07-02 23:08:34 +02:00
3693d68c24 Correction sur les compétences de base
All checks were successful
Release Creation / build (release) Successful in 1m0s
2025-06-04 15:29:32 +02:00
16ccd2f3e1 Foundry v13 migration 2025-05-09 10:28:22 +02:00
631eb280ca Foundry v13 migration
All checks were successful
Release Creation / build (release) Successful in 55s
2025-05-09 10:26:29 +02:00
88ca98945f Fix #3 2025-04-20 09:25:48 +02:00
edfb2105d3 Various enhancements + fixes
All checks were successful
Release Creation / build (release) Successful in 56s
2025-04-12 00:18:45 +02:00
84cc59c57d Fix and enhancements
All checks were successful
Release Creation / build (release) Successful in 2m23s
2025-04-05 23:15:46 +02:00
e9c0fbd818 Fix URL scheme
All checks were successful
Release Creation / build (release) Successful in 1m30s
2025-03-19 13:55:30 +01:00
aaabb7ed75 Correction sur XP, echec critique et tir réussi
All checks were successful
Release Creation / build (release) Successful in 53s
2025-03-18 20:38:30 +01:00
fee7a3a9fb Gestion opposition en combat melee 2025-03-11 20:16:26 +01:00
31517030f6 Gestion opposition en combat melee
All checks were successful
Release Creation / build (release) Successful in 39s
2025-03-11 20:10:06 +01:00
c5cbf2a6d1 Gestion du genre dans la creation de perso 2025-03-11 13:45:04 +01:00
a30f813d94 Fix genre 2025-03-10 16:56:25 +01:00
090f6be601 Fix genre 2025-03-10 16:56:10 +01:00
60db1f65e4 Prit fix sur equipement et armes d'hast 2025-03-10 15:52:37 +01:00
d532765d2b Correction sur creation PNJ
All checks were successful
Release Creation / build (release) Successful in 2m0s
2025-03-01 22:01:01 +01:00
b6016742ae Enable PNJ 2025-03-01 19:42:15 +01:00
761f95d6d9 Ajout comp libres
All checks were successful
Release Creation / build (release) Successful in 44s
2025-02-25 22:29:05 +01:00
c24f4fe502 Ajout comp libres
All checks were successful
Release Creation / build (release) Successful in 1m13s
2025-02-25 21:29:52 +01:00
caedcf5e21 Update release 2025-02-24 19:53:03 +01:00
fe0814e498 Conserve l'historique des réponses
All checks were successful
Release Creation / build (release) Successful in 1m26s
2025-02-22 22:44:00 +01:00
544f9f467a Import and fix helper pictures 2025-02-21 17:49:49 +01:00
ce5771f930 Import and fix helper pictures 2025-02-21 17:47:49 +01:00
93b8325bb9 Import and fix helper pictures
All checks were successful
Release Creation / build (release) Successful in 50s
2025-02-21 17:41:36 +01:00
48be65e7fd Add release action 2025-02-21 10:43:37 +01:00
191 changed files with 1385 additions and 603 deletions

View File

@@ -27,7 +27,7 @@ jobs:
env:
version: ${{steps.get_version.outputs.version-without-v}}
url: https://www.uberwald.me/gitea/${{gitea.repository}}
manifest: https://www.uberwald.me/gitea/public/${{gitea.repository}}/releases/download/latest/system.json
manifest: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/latest/system.json
download: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-te-deum-${{github.event.release.tag_name}}.zip
# Create a zip file with all files required by the module to add to the release

View File

@@ -1,10 +1,18 @@
# Système Foundry pour Te Deum pour un massacre (French RPG, Open Sesam Games, Official)
# Système Foundry pour Te Deum pour un Massacre (French RPG, Open Sesame Games, Official)
This is a base game system with functionnal character sheets for the game Te Deum pour un massacre.
# Contributions
- Original code realised by Uberwald (https://www.uberwald.me/)
Snapshot of the system :
![Alt text](https://www.lahiette.com/leratierbretonnien/wp-content/uploads/2025/02/tedeum_snapshot.webp "a title")
# Copyright mentions
Copyright 2025 Open Sesame Games
All rights reserved
@@ -13,5 +21,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
Te Deum pour un massacre is a game written by Jean-Philippe Jaworski. The author retains his moral rights regarding this work in both print and digital formats.
# Requests or Problems
Please report any requests or problems you have at contact@open-sesame.games

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -0,0 +1,29 @@
# 13.0.0
- Support de Foundry v13
# 12.0.23
- Correction sur les jets réussie en tir
- Correction sur le dés négatif pour les échecs critiques
- Correction sur l'XP et édition de l'XP en mode MJ
# 12.0.22
- Correction pour les armes d'hast
- Correction sur la zone libre d'équipement
- Bouton + pour créer un équipement à nouveau opérationnel
- Modification de la gestion des jets en combat, avec gestion opposition ou degats immédiats
- Gestion du genre dans la création de personnage
# 12.0.21
- Creation de PNJ OK
# 12.0.20
- Corrections sur la création de perso
# 12.0.19
- Initial release !

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
images/icons/xpplus1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -6,7 +6,7 @@
import { TeDeumUtility } from "../common/tedeum-utility.js";
/* -------------------------------------------- */
export class TeDeumActorPJSheet extends ActorSheet {
export class TeDeumActorPJSheet extends foundry.appv1.sheets.ActorSheet {
/** @override */
static get defaultOptions() {
@@ -15,7 +15,7 @@ export class TeDeumActorPJSheet extends 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
@@ -42,6 +42,7 @@ export class TeDeumActorPJSheet extends ActorSheet {
providence: this.actor.prepareProvidence(),
arbreCompetences: this.actor.prepareArbreCompetences(),
equipements: this.actor.getEquipements(),
simples: this.actor.getSimples(),
armures: this.actor.getArmures(),
graces: this.actor.getGraces(),
blessures: this.actor.getBlessures(),
@@ -55,8 +56,10 @@ export class TeDeumActorPJSheet extends ActorSheet {
nbArmuresLourdes: this.actor.getNbArmuresLourdesActuel(),
santeModifier: this.actor.getSanteModifier(),
educations: this.actor.getEducations(),
description: await TextEditor.enrichHTML(this.object.system.description, { async: true }),
notes: await TextEditor.enrichHTML(this.object.system.notes, { async: true }),
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.description, { async: true }),
equipmentfree: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.equipmentfree, { async: true }),
notes: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.notes, { async: true }),
histoire: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.histoire, { async: true }),
options: this.options,
owner: this.document.isOwner,
editScore: this.options.editScore,
@@ -64,7 +67,6 @@ export class TeDeumActorPJSheet extends ActorSheet {
}
this.formData = formData;
console.log("PC : ", formData, this.object);
return formData;
}
@@ -76,16 +78,16 @@ export class TeDeumActorPJSheet extends 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;
});
});
// Update Inventory Item
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
@@ -95,16 +97,25 @@ export class TeDeumActorPJSheet extends ActorSheet {
})
html.find('.item-add').click(ev => {
let dataType = $(ev.currentTarget).data("type")
this.actor.createEmbeddedDocuments('Item', [{ name: "NewItem", type: dataType }], { renderSheet: true })
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 })
})
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);
});
html.find('.subactor-delete').click(ev => {
const li = $(ev.currentTarget).parents(".item");
let actorId = li.data("actor-id");
@@ -112,17 +123,17 @@ export class TeDeumActorPJSheet extends 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")
this.actor.rollCompetence(compId)
});
});
html.find('.roll-arme').click((event) => {
const armeId = $(event.currentTarget).data("arme-id")
this.actor.rollArme(armeId)
@@ -131,24 +142,24 @@ export class TeDeumActorPJSheet extends ActorSheet {
const armeId = $(event.currentTarget).data("arme-id")
this.actor.rollDegatsArme(armeId)
});
html.find('.lock-unlock-sheet').click((event) => {
this.options.editScore = !this.options.editScore;
this.render(true);
});
});
html.find('.item-equip').click(ev => {
const li = $(ev.currentTarget).parents(".item");
this.actor.equipItem( li.data("item-id") );
this.render(true);
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 });
});
}
/* -------------------------------------------- */
/** @override */
setPosition(options = {}) {

View File

@@ -14,8 +14,8 @@ export class TeDeumActor extends Actor {
/**
* Override the create() function to provide additional SoS functionality.
*
* This overrided create() function adds initial items
* Namely: Basic skills, money,
* This overrided create() function adds initial items
* Namely: Basic skills, money,
*
* @param {Object} data Barebones actor data which this function adds onto.
* @param {Object} options (Unused) Additional options which customize the creation workflow.
@@ -34,7 +34,7 @@ export class TeDeumActor extends Actor {
return actor;
}
if (data.type == 'pj') {
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,6 +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(`${actor.name} : Utilisation de la compétence Main Gauche au lieu de ${comp.name}`)
let mainGaucheComp = this.itms.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 = []
@@ -104,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) {
@@ -119,8 +150,10 @@ export class TeDeumActor extends Actor {
if (updates.length > 0) {
this.updateEmbeddedDocuments('Item', updates)
}
super._onUpdate(changed, options, userId);
}
/* -------------------------------------------- */
async _preCreate(data, options, user) {
await super._preCreate(data, options, user);
@@ -137,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
}
/* -------------------------------------------- */
@@ -145,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]
}
@@ -190,6 +241,11 @@ export class TeDeumActor extends Actor {
TeDeumUtility.sortArrayObjectsByName(comp)
return comp;
}
getSimples() {
let comp = foundry.utils.duplicate(this.items.filter(item => item.type == 'simple') || [])
TeDeumUtility.sortArrayObjectsByName(comp)
return comp;
}
getArmures() {
let comp = foundry.utils.duplicate(this.items.filter(item => item.type == 'armure') || [])
TeDeumUtility.sortArrayObjectsByName(comp)
@@ -251,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)
}
@@ -295,7 +415,11 @@ export class TeDeumActor extends Actor {
c.key = key
c.name = game.system.tedeum.config.caracteristiques[key].label
c.generalqualite = game.system.tedeum.config.descriptionValeur[c.value].qualite
c.qualite = game.system.tedeum.config.descriptionValeur[c.value][key]
if (this.system.genre.toLowerCase() == "homme") {
c.qualite = game.system.tedeum.config.descriptionValeur[c.value][key]
} else {
c.qualite = game.system.tedeum.config.descriptionValeurFemme[c.value][key]
}
c.dice = game.system.tedeum.config.descriptionValeur[c.value].dice
c.negativeDice = game.system.tedeum.config.descriptionValeur[c.value].negativeDice
}
@@ -314,7 +438,11 @@ export class TeDeumActor extends Actor {
prepareProvidence() {
let providence = foundry.utils.deepClone(this.system.providence)
providence.name = "Providence"
providence.qualite = game.system.tedeum.config.providence[providence.value].labelM
if (this.system.genre.toLowerCase() == "homme") {
providence.qualite = game.system.tedeum.config.providence[providence.value].labelM
} else {
providence.qualite = game.system.tedeum.config.providence[providence.value].labelF
}
providence.dice = game.system.tedeum.config.providence[providence.value].diceValue
providence.description = "La Providence représente la Volonté Divine à l'œuvre pour guider ou sauver un être humain. Les PJ montent dans léchelle de la Providence en menant à bien leurs missions et en se montrant vertueux. Les points de Providence peuvent servir à augmenter temporairement une caractéris- tique, à modifier la gravité d'une blessure, et à résister au vieillissement. Chaque person- nage commence avec un score initial de 1 en Providence (au niveau Pauvre pécheur)."
return providence
@@ -352,11 +480,14 @@ export class TeDeumActor extends Actor {
providence.value = Math.min(Math.max(providence.value + value, 0), 6)
this.update({ "system.providence": providence })
}
/* -------------------------------------------- */
modifyXP(key, value) {
async modifyXP(key, value) {
let xp = this.system.caracteristiques[key].experience
xp = Math.max(xp + value, 0)
this.update({ [`system.caracteristiques.${key}.experience`]: xp })
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}`)
}
/* -------------------------------------------- */
@@ -429,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
@@ -504,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
}
/* -------------------------------------------- */
@@ -570,6 +705,7 @@ export class TeDeumActor extends Actor {
let rollData = this.getCommonCompetence(compId)
rollData.mode = "competence"
rollData.title = rollData.competence.name
rollData.compScore = rollData.competence.system.isBase ? this.system.caracteristiques[rollData.competence.system.caracteristique].value : rollData.competence.system.score
this.startRoll(rollData).catch("Error on startRoll")
}
@@ -578,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
@@ -622,14 +758,20 @@ export class TeDeumActor extends Actor {
// Setup competence + carac
if (!compName) {
compName = weapon.system.competence
let compIdx = weapon.system.competence
compName = game.system.tedeum.config.armeCompetences[compIdx]?.label
}
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,12 +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 }
@@ -38,6 +40,7 @@ export class TeDeumCharacterCreator {
} else {
this.competenceBonus[compName].value += 1
}
this.choiceSummary[this.currentStage].competences[compName] = 1
}
/*--------------------------------------------*/
@@ -68,7 +71,7 @@ export class TeDeumCharacterCreator {
/*--------------------------------------------*/
async askStageName(context) {
const content = await renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-stage-name.hbs", context)
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-stage-name.hbs", context)
const choiceResult = await foundry.applications.api.DialogV2.wait({
window: { title: context.title },
classes: ["fvtt-te-deum"],
@@ -115,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]
@@ -126,7 +130,7 @@ export class TeDeumCharacterCreator {
context.competences = {}
context.responseKey = "reponse1" // By default
const content = await renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-questions.hbs", context)
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-questions.hbs", context)
const choiceResult = await foundry.applications.api.DialogV2.wait({
window: { title: context.title },
classes: ["fvtt-te-deum"],
@@ -155,7 +159,7 @@ export class TeDeumCharacterCreator {
// Get the responseKey data
let responseKey = $(event.target).data("response-key")
let compName = event.target.value
console.log("Questionnaire Change", responseKey, compName)
console.log("Questionnaire Change", responseKey, compName)
context.competences[responseKey] = compName.toLowerCase()
})
}
@@ -168,12 +172,15 @@ export class TeDeumCharacterCreator {
let selectedResponse = question.reponses[context.responseKey]
let compName = context.competences[context.responseKey] || selectedResponse.compName
this.increaseCompetence(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 = {}
@@ -189,7 +196,7 @@ export class TeDeumCharacterCreator {
}
}
const content = await renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-competences.hbs", context)
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-competences.hbs", context)
const choiceResult = await foundry.applications.api.DialogV2.wait({
window: { title: context.title },
classes: ["fvtt-te-deum"],
@@ -233,7 +240,7 @@ export class TeDeumCharacterCreator {
}
}
const content = await renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-competences.hbs", context)
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-competences.hbs", context)
const choiceResult = await foundry.applications.api.DialogV2.wait({
window: { title: context.title },
classes: ["fvtt-te-deum"],
@@ -270,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++) {
@@ -280,7 +291,7 @@ export class TeDeumCharacterCreator {
context.caracList.push(game.system.tedeum.config.caracteristiques[carac.caracId])
}
const content = await renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-carac.hbs", context)
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-carac.hbs", context)
const choiceResult = await foundry.applications.api.DialogV2.wait({
window: { title: context.title },
classes: ["fvtt-te-deum"],
@@ -309,6 +320,7 @@ export class TeDeumCharacterCreator {
}
this.caracBonus[choiceResult.carac].value += 1
selected.push(choiceResult.carac)
this.choiceSummary[this.currentStage].caracBonus[choiceResult.carac] = 1
}
}
@@ -322,7 +334,7 @@ export class TeDeumCharacterCreator {
origineChoice: game.system.tedeum.config.origineSociale
}
const content = await renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-origine.hbs", context)
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-origine.hbs", context)
const label = "Valider le choix de l'Origine Sociale"
const choiceResult = await foundry.applications.api.DialogV2.wait({
window: { title: context.title },
@@ -357,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"
}
@@ -371,6 +389,7 @@ export class TeDeumCharacterCreator {
title: "Création de personnage - La Pouponnière",
subtitle: "Choix de la Pouponnière",
label: "Valider le choix de la Pouponnière",
hasGenre: false,
choices: pouponniereItems,
caracBonus: this.caracBonus,
competenceBonus: this.competenceBonus
@@ -384,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)
@@ -400,11 +420,12 @@ export class TeDeumCharacterCreator {
/*--------------------------------------------*/
async renderPetitsGrimauds(stage) {
// Filter available pouponniere from origineSociale
let grimaudsItems = stage.items.filter(item => item.system.accessible[this.origineSociale.id].isaccessible)
let grimaudsItems = stage.items.filter(item => item.system.accessible[this.origineSociale.id].isaccessible && (item.system.genre === this.sexe || item.system.genre === "Mixte"))
let context = {
title: "Les Petits Grimauds",
label: "Valider le choix des Petits Grimauds",
hasGenre: true,
choices: grimaudsItems,
caracBonus: this.caracBonus,
competenceBonus: this.competenceBonus
@@ -434,12 +455,13 @@ export class TeDeumCharacterCreator {
/*--------------------------------------------*/
async renderRosesDeLaVie(stage) {
// Filter available pouponniere from origineSociale
let rosesItems = stage.items.filter(item => item.system.accessible[this.origineSociale.id].isaccessible)
let rosesItems = stage.items.filter(item => item.system.accessible[this.origineSociale.id].isaccessible && (item.system.genre === this.sexe || item.system.genre === "Mixte"))
let context = {
title: "Création de personnage - Les Roses de la Vie",
label: "Valider le choix des Roses de la Vie",
choices: rosesItems,
hasGenre: true,
caracBonus: this.caracBonus,
competenceBonus: this.competenceBonus
@@ -485,6 +507,7 @@ export class TeDeumCharacterCreator {
title: "Création de personnage - L'Age Viril",
label: "Valider le choix de l'Age Viril",
choices: ageVirilItems,
hasGenre: false,
caracBonus: this.caracBonus,
competenceBonus: this.competenceBonus
}
@@ -538,7 +561,7 @@ export class TeDeumCharacterCreator {
let actor = await TeDeumActor.create({name: "Nouveau personnage", type: "pj"})
let updates = {}
for (let key in this.caracBonus) {
updates[`system.caracteristiques.${key}.value`] = Number(this.caracBonus[key].value)+1
updates[`system.caracteristiques.${key}.value`] = Number(this.caracBonus[key].value)+1
}
updates['system.genre'] = this.sexe
updates['system.religion'] = TeDeumUtility.upperFirst(this.religion)
@@ -546,7 +569,7 @@ export class TeDeumCharacterCreator {
updates['system.equipmentfree'] = this.ageViril.system.trousseau
actor.update( updates);
// Process competences : increase know skills
// Process competences : increase know skills
let updateComp = []
let toAdd = []
for (let compName in this.competenceBonus) {
@@ -555,13 +578,13 @@ export class TeDeumCharacterCreator {
updateComp.push({ _id: comp._id, "system.score": this.competenceBonus[compName].value })
} else {
toAdd.push( compName)
}
}
}
actor.updateEmbeddedDocuments("Item", updateComp)
// Process adding skills
// Process adding skills
let compendiumSkill = TeDeumUtility.getCompetences()
let compToAdd = [ this.pouponniere, this.grimauds, this.roses, this.ageViril ]
let compToAdd = [ this.pouponniere, this.grimauds, this.roses, this.ageViril ]
for (let compName of toAdd) {
let comp = compendiumSkill.find( i => i.name.toLowerCase() === compName.toLowerCase())
comp.system.score = this.competenceBonus[compName].value
@@ -573,9 +596,51 @@ export class TeDeumCharacterCreator {
newArgent /= this.ageViril.system.cagnotteDivider
await actor.update({ [`system.fortune.${this.origineSociale.cagnotteUnit}`]: newArgent})
let histoire = ""
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)
const content = await renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-finished.hbs", context)
context.pointsCompetence = {
"savoir": { score: actor.getCompetenceScore("Mémoriser"), label: "Savoir" },
"sensibilite": { score: actor.getCompetenceScore("Perception"), label: "Sensibilité" },
"entregent": { score: actor.getCompetenceScore("Charme"), label: "Entregent" },
"puissance": { score: actor.getCompetenceScore("Effort"), label: "Puissance" },
"complexion": { score: actor.getCompetenceScore("Endurance"), label: "Complexion" },
"adresse": { score: actor.getCompetenceScore("Initiative"), label: "Adresse" },
}
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-finished.hbs", context)
const label = "Terminer"
const choiceResult = await foundry.applications.api.DialogV2.wait({
window: { title: context.title },

View File

@@ -2,20 +2,39 @@ import { TeDeumUtility } from "../common/tedeum-utility.js";
/* -------------------------------------------- */
export class TeDeumCombat extends Combat {
/* -------------------------------------------- */
async rollInitiative(ids, formula = undefined, messageOptions = {} ) {
console.log("Roll INIT !")
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;
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
await combatant.setFlag("world", "available-actions", ca)
await combatant.update({ name: `${combatant.token.name} (${ca.nbActions} / ${ca.nbActionsMainGauche})` })
}
/* -------------------------------------------- */
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 },
@@ -57,7 +73,7 @@ export const TEDEUM_CONFIG = {
descriptionValeurOdd: {
1: { valeur: 1, qualite: "Mauvais", dice: "d4", negativeDice: "d20", savoir: "Sot", sensibilite: "Obtus", entregent: "Rustaud", puissance: "Menu", complexion: "Anémique", adresse: "Empesé" },
2: { valeur: 2, qualite: "Médiocre", dice: "d6", negativeDice: "d12", savoir: "Limité", sensibilite: "Etriqué", entregent: "Frustre", puissance: "Délicat", complexion: "Languide", adresse: "Gauche" },
2: { valeur: 2, qualite: "Médiocre", dice: "d6", negativeDice: "d12", savoir: "Limité", sensibilite: "Etriqué", entregent: "Fruste", puissance: "Délicat", complexion: "Languide", adresse: "Gauche" },
3: { valeur: 3, qualite: "Correct", dice: "d8", negativeDice: "d10", savoir: "Mêlé", sensibilite: "Ouvert", entregent: "Badin", puissance: "Membru", complexion: "Dispos", adresse: "Ingambe" },
4: { valeur: 4, qualite: "Bon", dice: "d10", negativeDice: "d8", savoir: "Lettré", sensibilite: "Fin", entregent: "Disert", puissance: "Vigoureux", complexion: "Gaillard", adresse: "Leste" },
5: { valeur: 5, qualite: "Bon", dice: "d10", negativeDice: "d8", savoir: "Lettré", sensibilite: "Fin", entregent: "Disert", puissance: "Vigoureux", complexion: "Gaillard", adresse: "Leste" },
@@ -71,12 +87,20 @@ export const TEDEUM_CONFIG = {
},
descriptionValeur: {
1: { valeur: 1, qualite: "Mauvais", dice: "d4", negativeDice: "d20", savoir: "Sot", sensibilite: "Obtus", entregent: "Rustaud", puissance: "Menu", complexion: "Anémique", adresse: "Empesé" },
2: { valeur: 2, qualite: "Médiocre", dice: "d6", negativeDice: "d12", savoir: "Limité", sensibilite: "Etriqué", entregent: "Frustre", puissance: "Délicat", complexion: "Languide", adresse: "Gauche" },
2: { valeur: 2, qualite: "Médiocre", dice: "d6", negativeDice: "d12", savoir: "Limité", sensibilite: "Etriqué", entregent: "Fruste", puissance: "Délicat", complexion: "Languide", adresse: "Gauche" },
3: { valeur: 3, qualite: "Correct", dice: "d8", negativeDice: "d10", savoir: "Mêlé", sensibilite: "Ouvert", entregent: "Badin", puissance: "Membru", complexion: "Dispos", adresse: "Ingambe" },
4: { valeur: 4, qualite: "Bon", dice: "d10", negativeDice: "d8", savoir: "Lettré", sensibilite: "Fin", entregent: "Disert", puissance: "Vigoureux", complexion: "Gaillard", adresse: "Leste" },
5: { valeur: 5, qualite: "Excellent", dice: "d12", negativeDice: "d6", savoir: "Docte", sensibilite: "Subtil", entregent: "Galant", puissance: "Musculeux", complexion: "Sanguin", adresse: "Preste" },
6: { valeur: 6, qualite: "Admirable", dice: "d20", negativeDice: "d4", savoir: "Humaniste", sensibilite: "Spirituel", entregent: "Sémillant", puissance: "Hercule", complexion: "Aguerri", adresse: "Alerte" },
},
descriptionValeurFemme: {
1: { valeur: 1, qualite: "Mauvais", dice: "d4", negativeDice: "d20", savoir: "Sotte", sensibilite: "Obtuse", entregent: "Rustaude", puissance: "Menue", complexion: "Anémique", adresse: "Empesée" },
2: { valeur: 2, qualite: "Médiocre", dice: "d6", negativeDice: "d12", savoir: "Limitée", sensibilite: "Etriquée", entregent: "Fruste", puissance: "Délicate", complexion: "Languide", adresse: "Gauche" },
3: { valeur: 3, qualite: "Correct", dice: "d8", negativeDice: "d10", savoir: "Mêlée", sensibilite: "Ouverte", entregent: "Badine", puissance: "Membrue", complexion: "Dispose", adresse: "Ingambe" },
4: { valeur: 4, qualite: "Bon", dice: "d10", negativeDice: "d8", savoir: "Lettrée", sensibilite: "Fine", entregent: "Diserte", puissance: "Vigoureuse", complexion: "Gaillarde", adresse: "Leste" },
5: { valeur: 5, qualite: "Excellent", dice: "d12", negativeDice: "d6", savoir: "Docte", sensibilite: "Subtile", entregent: "Galante", puissance: "Musculeuse", complexion: "Sanguine", adresse: "Preste" },
6: { valeur: 6, qualite: "Admirable", dice: "d20", negativeDice: "d4", savoir: "Humaniste", sensibilite: "Spirituelle", entregent: "Sémillante", puissance: "Hercule", complexion: "Aguerrie", adresse: "Alerte" },
},
diceValeur: ["d4", "d6", "d8", "d10", "d12", "d20"],
degatsArmure: {
sansarmure: { label: "Sans armure" },
@@ -86,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." },
@@ -94,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" },
@@ -117,6 +141,11 @@ export const TEDEUM_CONFIG = {
melee: { label: "Mêlée", value: "melee" },
tir: { label: "Tir", value: "tir" }
},
genreEducation: {
"homme": { label: "Homme", value: "Homme" },
"femme": { label: "Femme", value: "Femme" },
"mixte": { label: "Mixte", value: "Mixte" }
},
armeAllonges: {
courte: { label: "Courte", value: "courte" },
moyenne: { label: "Moyenne", value: "moyenne" },
@@ -139,24 +168,29 @@ 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 },
sol: { label: "Sols", id: "sol", value: 10 },
livre: { label: "Livres", id: "livre", value: 100 }
},
monnaieUnit: {
"1": { label: "Deniers", id: "denier", value: 1 },
"10": { label: "Sols", id: "sol", value: 10 },
"100": { label: "Livres", id: "livre", value: 100 }
},
etapesEducation: {
pouponniere: { label: "La Pouponnière", value: "pouponniere", agemin: 0, agemax: 6, nbCompetences: 2, nbCaracteristiques: 3, hasQuestionnaire: true, hasDebouches: false, hasMultiplier: false, canCompetencesOpt: false },
petitsgrimauds: { label: "La classe des Petits Grimauds", value: "petitsgrimauds", agemin: 7, agemax: 12, nbCompetences: 10, nbCaracteristiques: 3, hasDebouches: false, hasQuestionnaire: true, hasMultiplier: false, canCompetencesOpt: false },
rosevie: { label: "Les Roses de la Vie", value: "rosevie", agemin: 13, agemax: 16, nbCompetences: 2, nbCaracteristiques: 3, hasQuestionnaire: true, hasDebouches: true, hasMultiplier: false, canCompetencesOpt: false },
ageviril: { label: "L'Age Viril", value: "ageviril", agemin: 17, agemax: 17, nbCompetences: 9, nbCaracteristiques: 2, hasQuestionnaire: false, hasDebouches: false, hasMultiplier: true, canCompetencesOpt: true },
pouponniere: { label: "La Pouponnière", value: "pouponniere", agemin: 0, agemax: 6, nbCompetences: 2, nbCaracteristiques: 3, hasGenre: false, hasQuestionnaire: true, hasDebouches: false, hasMultiplier: false, canCompetencesOpt: false },
petitsgrimauds: { label: "La classe des Petits Grimauds", value: "petitsgrimauds", agemin: 7, agemax: 12, nbCompetences: 10, hasGenre: true, nbCaracteristiques: 3, hasDebouches: false, hasQuestionnaire: true, hasMultiplier: false, canCompetencesOpt: false },
rosevie: { label: "Les Roses de la Vie", value: "rosevie", agemin: 13, agemax: 16, nbCompetences: 2, nbCaracteristiques: 3, hasGenre: true, hasQuestionnaire: true, hasDebouches: true, hasMultiplier: false, canCompetencesOpt: false },
ageviril: { label: "L'Age Viril", value: "ageviril", agemin: 17, agemax: 17, nbCompetences: 9, nbCaracteristiques: 2, hasGenre: false, hasQuestionnaire: false, hasDebouches: false, hasMultiplier: true, canCompetencesOpt: true },
},
origineSociale: {
noblesseepee: { label: "Noblesse d'épée", id: "noblesseepee", caracteristiques: { entregent: 1, puissance: 1 }, cagnotte: 10, cagnotteUnit: "livres", value: 1 },
@@ -177,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

@@ -12,22 +12,63 @@ 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();
cr.init()
})
html.find('.header-actions').after(button)
$(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) {
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})` })
}
}
}
/* -------------------------------------------- */
@@ -92,6 +133,13 @@ export class TeDeumUtility {
Handlebars.registerHelper('isGM', function () {
return game.user.isGM
})
Handlebars.registerHelper('monnaie', function (value) {
let monnaie = game.system.tedeum.config.monnaieUnit[String(value)]
if (monnaie) {
return monnaie.label
}
return value
})
// Load compendium data
const competences = await TeDeumUtility.loadCompendium("fvtt-te-deum.competences")
@@ -160,6 +208,7 @@ export class TeDeumUtility {
formData.hasMultiplier = etape.hasMultiplier;
formData.hasDebouches = etape.hasDebouches;
formData.canCompetencesOpt = etape.canCompetencesOpt;
formData.hasGenre = etape.hasGenre;
}
/*-------------------------------------------- */
@@ -192,7 +241,7 @@ export class TeDeumUtility {
return actor
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/* -------------------------------------------- */
static async manageOpposition(rollData) {
if (!this.currentOpposition) {
// Store rollData as current GM opposition
@@ -200,29 +249,73 @@ export class TeDeumUtility {
ui.notifications.info("Opposition démarrée avec " + rollData.alias);
} else {
// Perform the opposition
let rWinner = this.currentOpposition
let rLooser = rollData
if (rWinner.total < rLooser.total) {
rWinner = rollData
rLooser = this.currentOpposition
let isAttackWinner = true
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 renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-opposition-result.hbs`, oppositionData)
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)
console.log("Rolldata result", 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) {
await this.appliquerDegats(rWinner)
}
console.log("Opposition result", rollData, isAttackWinner, oppositionData)
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async appliquerDegats(rollData) {
await this.processAttaqueMelee(rollData)
let defenderToken = canvas.tokens.placeables.find(t => t.id == rollData.defenderTokenId)
if (defenderToken) {
let actor = defenderToken.actor
await actor.appliquerDegats(rollData)
// 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é")
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async chatListeners(html) {
html.on("click", '.chat-command-button', event => {
$(html).on("click", '.chat-command-opposition', event => {
let messageId = TeDeumUtility.findChatMessageId(event.currentTarget)
let message = game.messages.get(messageId)
let rollData = message.getFlag("world", "te-deum-rolldata")
@@ -230,6 +323,25 @@ export class TeDeumUtility {
TeDeumUtility.manageOpposition(rollData, messageId)
}
})
$(html).on("click", '.chat-command-appliquer-degats', event => {
let messageId = TeDeumUtility.findChatMessageId(event.currentTarget)
let message = game.messages.get(messageId)
let rollData = message.getFlag("world", "te-deum-rolldata")
if (rollData) {
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';
}
})
}
/* -------------------------------------------- */
@@ -241,7 +353,7 @@ export class TeDeumUtility {
'systems/fvtt-te-deum/templates/items/partial-item-description.hbs',
'systems/fvtt-te-deum/templates/dialogs/partial-creator-status.hbs'
]
return loadTemplates(templatePaths);
return foundry.applications.handlebars.loadTemplates(templatePaths);
}
/* -------------------------------------------- */
@@ -318,7 +430,7 @@ export class TeDeumUtility {
let rollData = msg.data.rollData
if (game.user.isGM) {
let chatMsg = await this.createChatMessage(rollData.alias, "blindroll", {
content: await renderTemplate(msg.data.template, rollData),
content: await foundry.applications.handlebars.renderTemplate(msg.data.template, rollData),
whisper: game.user.id
})
chatMsg.setFlag("world", "tedeum-rolldata", rollData)
@@ -408,10 +520,11 @@ export class TeDeumUtility {
}
}
if (rollData.diceSum == 1) {
let critiqueRoll = await new Roll(rollData.carac.negativeDice).roll()
let critiqueRoll = await new Roll(rollData.carac.negativeDice)
await critiqueRoll.evaluate()
await this.showDiceSoNice(critiqueRoll, game.settings.get("core", "rollMode"))
rollData.critiqueRoll = foundry.utils.duplicate(critiqueRoll)
if (critiqueRoll.total > rollData.competence.score) {
if (critiqueRoll.total > rollData.competence.system.score) {
rollData.isEchecCritique = true
}
}
@@ -439,9 +552,18 @@ 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.competence.system.score
diceFormula = diceBase + "x + " + rollData.compScore
}
if (rollData.enableProvidence) {
diceFormula += " + " + rollData.providence.dice
@@ -451,32 +573,33 @@ 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) {
if (rollData.arme?.system.typeArme != "melee") {
return
}
if (rollData.isSuccess) {
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()
await this.showDiceSoNice(degatsRoll, game.settings.get("core", "rollMode"))
rollData.degatsRoll = foundry.utils.duplicate(degatsRoll)
rollData.degats = degatsRoll.total
}
await this.getLocalisation(rollData)
let actor = game.actors.get(rollData.actorId)
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
}
/* -------------------------------------------- */
@@ -489,12 +612,40 @@ export class TeDeumUtility {
await this.getLocalisation(rollData)
// Now the degats
let degatsRoll = await new Roll(rollData.arme.system.degats).roll()
await this.showDiceSoNice(locRoll, game.settings.get("core", "rollMode"))
await this.showDiceSoNice(rollData.degatsRoll, game.settings.get("core", "rollMode"))
rollData.degatsRoll = foundry.utils.duplicate(degatsRoll)
rollData.degats = degatsRoll.total
}
}
/* -------------------------------------------- */
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`)
}
}
if (ca.nbActions > 0) {
ca.nbActions -= 1
} else {
ui.notifications.error(`${actor.name} n'a plus d'actions disponibles`)
}
await combatant.setFlag("world", "available-actions", ca)
await combatant.update({ name: `${combatant.token.name} (${ca.nbActions} / ${ca.nbActionsMainGauche})` })
rollData.hasActions = true
rollData.remainingActions = ca.nbActions
rollData.remainingActionsMainGauche = ca.nbActionsMainGauche
}
/* -------------------------------------------- */
static async rollTeDeum(rollData) {
@@ -504,6 +655,18 @@ 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.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
}
}
let diceFormula = this.computeRollFormula(rollData, actor)
if (!diceFormula) return;
console.log("RollData", rollData, diceFormula)
@@ -519,10 +682,11 @@ export class TeDeumUtility {
await this.computeResults(rollData)
await this.processAttaqueDistance(rollData)
await this.processAttaqueMelee(rollData)
await this.manageCombatActions(actor, rollData)
let msg = await this.createChatWithRollMode(rollData.alias, {
content: await renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-generic-result.hbs`, rollData)
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-generic-result.hbs`, rollData)
})
await msg.setFlag("world", "te-deum-rolldata", rollData)
console.log("Rolldata result", rollData)
@@ -531,19 +695,6 @@ export class TeDeumUtility {
if (rollData.enableProvidence) {
actor.modifyProvidence(-1)
}
// Manage XP
if (rollData.isReussiteCritique || rollData.isEchecCritique) {
actor.modifyXP(rollData.carac.key, 1)
}
// gestion degats automatique
if (rollData.arme && rollData.defenderTokenId) {
let defenderToken = canvas.tokens.placeables.find(t => t.id == rollData.defenderTokenId)
if (defenderToken) {
let actor = defenderToken.actor
await actor.appliquerDegats(rollData)
}
}
}
/* -------------------------------------------- */

View File

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

View File

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

View File

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

View File

@@ -13,4 +13,10 @@ export class TeDeumEquipementSchema extends foundry.abstract.TypeDataModel {
return schema;
}
get monnaieLabel() {
console.log("monnaieLabel", this.monnaie,game.system.tedeum.config.monnaieUnit)
return game.system.tedeum.config.monnaieUnit[String(this.monnaie)]?.label;
}
}

View File

@@ -9,7 +9,8 @@ export class TeDeumMaladieSchema extends foundry.abstract.TypeDataModel {
schema.virulence = new fields.StringField({required: true, choices: ["fatigue", "epuisement", "souffrance", "agonie"], initial: "fatigue"});
schema.fievre = new fields.StringField({required: true, choices: ["aucune", "legere", "forte", "grave"], initial: "aucune"});
schema.symptomes = new fields.HTMLField({ required: true, blank: true });
schema.appliquee = new fields.BooleanField({initial: false}),
schema.complications = new fields.HTMLField({ required: true, blank: true });
schema.appliquee = new fields.BooleanField({initial: false});
schema.description = new fields.HTMLField({ required: true, blank: true });

View File

@@ -26,32 +26,35 @@ export class TeDeumPJSchema extends foundry.abstract.TypeDataModel {
obj[loc.id] = new fields.SchemaField({
armure: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0, max: 20 }),
touche: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0, max: 20 }),
blessures: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0, max: 20 })
blessures: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0, max: 20 })
});
return obj;
}, {})
);
schema.fortune = new fields.SchemaField({
"ecus": new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
"ecus": new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
"livres": new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) ,
"sous": new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) ,
"deniers": new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
"deniers": new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
});
schema.description = new fields.HTMLField({required: true, blank: true});
schema.notes = new fields.HTMLField({required: true, blank: true});
schema.connaissances = new fields.HTMLField({required: true, blank: true});
schema.histoire = new fields.HTMLField({required: true, blank: true});
schema.vetements = new fields.HTMLField({required: true, blank: true});
schema.equipmentfree = new fields.HTMLField({required: true, blank: true});
schema.genre = new fields.StringField({required: true, choices: game.system.tedeum.config.genre, initial: "Femme"});
schema.age = new fields.StringField({ required: false, blank: true, initial: undefined });
schema.statutocial = new fields.StringField({ required: false, blank: true, initial: undefined });
schema.chargestitre = new fields.StringField({ required: false, blank: true, initial: undefined });
schema.charges = new fields.StringField({ required: false, blank: true, initial: undefined });
schema.religion = new fields.StringField({ required: false, blank: true, initial: undefined });
schema.lieunaissance = new fields.StringField({ required: false, blank: true, initial: undefined });
schema.age = new fields.StringField({ required: false, blank: true, initial: "" });
schema.datenaissance = new fields.StringField({ required: false, blank: true, initial: "" });
schema.statutocial = new fields.StringField({ required: false, blank: true, initial: "" });
schema.chargestitre = new fields.StringField({ required: false, blank: true, initial: "" });
schema.charges = new fields.StringField({ required: false, blank: true, initial: "" });
schema.religion = new fields.StringField({ required: false, blank: true, initial: "" });
schema.lieunaissance = new fields.StringField({ required: false, blank: true, initial: "" });
return schema;
}
}

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

@@ -4,7 +4,7 @@ import { TeDeumUtility } from "../common/tedeum-utility.js";
* Extend the basic ItemSheet with some very simple modifications
* @extends {ItemSheet}
*/
export class TeDeumItemSheet extends ItemSheet {
export class TeDeumItemSheet extends foundry.appv1.sheets.ItemSheet {
/** @override */
static get defaultOptions() {
@@ -49,17 +49,16 @@ export class TeDeumItemSheet extends ItemSheet {
limited: this.object.limited,
options: this.options,
owner: this.document.isOwner,
description: await TextEditor.enrichHTML(this.object.system.description, { async: true }),
notes: await TextEditor.enrichHTML(this.object.system.notes, { async: true }),
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.description, { async: true }),
notes: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.notes, { async: true }),
isGM: game.user.isGM
}
if (this.object.type == "education") {
TeDeumUtility.prepareEducationContent(formData);
}
this.options.editable = !(this.object.origin == "embeddedItem");
console.log("ITEM DATA", formData, this);
return formData;
}
@@ -103,7 +102,7 @@ export class TeDeumItemSheet extends ItemSheet {
let levelIndex = Number($(ev.currentTarget).parents(".item").data("level-index"))
let choiceIndex = Number($(ev.currentTarget).parents(".item").data("choice-index"))
let featureId = $(ev.currentTarget).parents(".item").data("feature-id")
let itemData = this.object.system.levels[levelIndex].choices[choiceIndex].features[featureId]
if (itemData.name != 'None') {
@@ -157,7 +156,7 @@ export class TeDeumItemSheet extends ItemSheet {
let itemType = li.data("item-type");
});
}
}
/* -------------------------------------------- */
get template() {

View File

@@ -51,7 +51,7 @@ Hooks.once("init", async function () {
// preload handlebars templates
TeDeumUtility.preloadHandlebarsTemplates();
// Set an initiative formula for the system
// Set an initiative formula for the system
CONFIG.Combat.initiative = {
formula: "1d6",
decimals: 1
@@ -79,17 +79,19 @@ Hooks.once("init", async function () {
blessure: TeDeumBlessureSchema,
maladie: TeDeumMaladieSchema,
};
console.log("TeDeum RPG | Ready");
Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("fvtt-te-deum", TeDeumActorPJSheet, { types: ["pj"], makeDefault: true });
Actors.registerSheet("fvtt-te-deum", TeDeumActorPJSheet, { types: ["pnj"], makeDefault: true });
Items.unregisterSheet("core", ItemSheet);
Items.registerSheet("fvtt-te-deum", TeDeumItemSheet, { makeDefault: true });
foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet);
foundry.documents.collections.Actors.registerSheet("fvtt-te-deum", TeDeumActorPJSheet, { types: ["pj"], makeDefault: true });
foundry.documents.collections.Actors.registerSheet("fvtt-te-deum", TeDeumActorPJSheet, { types: ["pnj"], makeDefault: true });
TeDeumUtility.init()
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet);
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 !");
@@ -106,11 +109,11 @@ Hooks.once("ready", function () {
user: game.user._id
});
}
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();
@@ -134,4 +137,3 @@ Hooks.on("chatMessage", (html, content, msg) => {
}
return true;
});

Binary file not shown.

BIN
packs/aides/000136.ldb Normal file

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000006
MANIFEST-000157

View File

@@ -1,8 +1,7 @@
2025/02/13-22:35:49.582184 7fcc32ffd6c0 Recovering log #4
2025/02/13-22:35:49.633338 7fcc32ffd6c0 Delete type=3 #2
2025/02/13-22:35:49.633392 7fcc32ffd6c0 Delete type=0 #4
2025/02/13-22:42:05.161388 7fcc327fc6c0 Level-0 table #9: started
2025/02/13-22:42:05.161406 7fcc327fc6c0 Level-0 table #9: 0 bytes OK
2025/02/13-22:42:05.168017 7fcc327fc6c0 Delete type=0 #7
2025/02/13-22:42:05.168186 7fcc327fc6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)
2025/02/13-22:42:05.168210 7fcc327fc6c0 Manual compaction at level-1 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)
2025/09/24-15:09:29.187023 7f7d00dfa6c0 Recovering log #155
2025/09/24-15:09:29.197297 7f7d00dfa6c0 Delete type=3 #153
2025/09/24-15:09:29.197358 7f7d00dfa6c0 Delete type=0 #155
2025/09/24-15:11:47.439451 7f7cf9fff6c0 Level-0 table #160: started
2025/09/24-15:11:47.439482 7f7cf9fff6c0 Level-0 table #160: 0 bytes OK
2025/09/24-15:11:47.446526 7f7cf9fff6c0 Delete type=0 #158
2025/09/24-15:11:47.446682 7f7cf9fff6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)

View File

@@ -1,5 +1,7 @@
2025/02/05-20:07:00.726830 7ffae77fe6c0 Delete type=3 #1
2025/02/05-20:50:19.888688 7ffae6bff6c0 Level-0 table #5: started
2025/02/05-20:50:19.892050 7ffae6bff6c0 Level-0 table #5: 3651 bytes OK
2025/02/05-20:50:19.898356 7ffae6bff6c0 Delete type=0 #3
2025/02/05-20:50:19.924903 7ffae6bff6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)
2025/09/24-14:48:23.305998 7f7cfb7fe6c0 Recovering log #151
2025/09/24-14:48:23.315978 7f7cfb7fe6c0 Delete type=3 #149
2025/09/24-14:48:23.316051 7f7cfb7fe6c0 Delete type=0 #151
2025/09/24-15:08:26.608194 7f7cf9fff6c0 Level-0 table #156: started
2025/09/24-15:08:26.608240 7f7cf9fff6c0 Level-0 table #156: 0 bytes OK
2025/09/24-15:08:26.663875 7f7cf9fff6c0 Delete type=0 #154
2025/09/24-15:08:26.664085 7f7cf9fff6c0 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-000157 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
packs/armes/000239.ldb Normal file

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000109
MANIFEST-000260

View File

@@ -1,7 +1,7 @@
2025/02/13-22:35:49.132071 7fcc337fe6c0 Recovering log #107
2025/02/13-22:35:49.187037 7fcc337fe6c0 Delete type=3 #105
2025/02/13-22:35:49.187149 7fcc337fe6c0 Delete type=0 #107
2025/02/13-22:42:05.116041 7fcc327fc6c0 Level-0 table #112: started
2025/02/13-22:42:05.116121 7fcc327fc6c0 Level-0 table #112: 0 bytes OK
2025/02/13-22:42:05.122845 7fcc327fc6c0 Delete type=0 #110
2025/02/13-22:42:05.142173 7fcc327fc6c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)
2025/09/24-15:09:29.097777 7f7cfbfff6c0 Recovering log #258
2025/09/24-15:09:29.108008 7f7cfbfff6c0 Delete type=3 #256
2025/09/24-15:09:29.108079 7f7cfbfff6c0 Delete type=0 #258
2025/09/24-15:11:47.381009 7f7cf9fff6c0 Level-0 table #263: started
2025/09/24-15:11:47.381035 7f7cf9fff6c0 Level-0 table #263: 0 bytes OK
2025/09/24-15:11:47.387083 7f7cf9fff6c0 Delete type=0 #261
2025/09/24-15:11:47.393292 7f7cf9fff6c0 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/02/05-20:07:00.600917 7ffae7fff6c0 Recovering log #103
2025/02/05-20:07:00.611719 7ffae7fff6c0 Delete type=3 #101
2025/02/05-20:07:00.611830 7ffae7fff6c0 Delete type=0 #103
2025/02/05-20:50:19.838224 7ffae6bff6c0 Level-0 table #108: started
2025/02/05-20:50:19.838303 7ffae6bff6c0 Level-0 table #108: 0 bytes OK
2025/02/05-20:50:19.844606 7ffae6bff6c0 Delete type=0 #106
2025/02/05-20:50:19.863174 7ffae6bff6c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)
2025/09/24-14:48:23.211234 7f7cfaffd6c0 Recovering log #254
2025/09/24-14:48:23.220782 7f7cfaffd6c0 Delete type=3 #252
2025/09/24-14:48:23.220848 7f7cfaffd6c0 Delete type=0 #254
2025/09/24-15:08:26.052999 7f7cf9fff6c0 Level-0 table #259: started
2025/09/24-15:08:26.053039 7f7cf9fff6c0 Level-0 table #259: 0 bytes OK
2025/09/24-15:08:26.114659 7f7cf9fff6c0 Delete type=0 #257
2025/09/24-15:08:26.173656 7f7cf9fff6c0 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-000260 Normal file

Binary file not shown.

View File

View File

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
packs/armures/000238.ldb Normal file

Binary file not shown.

0
packs/armures/000261.log Normal file
View File

View File

@@ -1 +1 @@
MANIFEST-000109
MANIFEST-000259

View File

@@ -1,7 +1,7 @@
2025/02/13-22:35:49.200499 7fcc32ffd6c0 Recovering log #107
2025/02/13-22:35:49.256910 7fcc32ffd6c0 Delete type=3 #105
2025/02/13-22:35:49.256980 7fcc32ffd6c0 Delete type=0 #107
2025/02/13-22:42:05.134786 7fcc327fc6c0 Level-0 table #112: started
2025/02/13-22:42:05.134811 7fcc327fc6c0 Level-0 table #112: 0 bytes OK
2025/02/13-22:42:05.142066 7fcc327fc6c0 Delete type=0 #110
2025/02/13-22:42:05.142204 7fcc327fc6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)
2025/09/24-15:09:29.111050 7f7cfaffd6c0 Recovering log #257
2025/09/24-15:09:29.121636 7f7cfaffd6c0 Delete type=3 #255
2025/09/24-15:09:29.121696 7f7cfaffd6c0 Delete type=0 #257
2025/09/24-15:11:47.374855 7f7cf9fff6c0 Level-0 table #262: started
2025/09/24-15:11:47.374881 7f7cf9fff6c0 Level-0 table #262: 0 bytes OK
2025/09/24-15:11:47.380908 7f7cf9fff6c0 Delete type=0 #260
2025/09/24-15:11:47.393280 7f7cf9fff6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2025/02/05-20:07:00.616342 7ffaecbf96c0 Recovering log #103
2025/02/05-20:07:00.627971 7ffaecbf96c0 Delete type=3 #101
2025/02/05-20:07:00.628058 7ffaecbf96c0 Delete type=0 #103
2025/02/05-20:50:19.844802 7ffae6bff6c0 Level-0 table #108: started
2025/02/05-20:50:19.844850 7ffae6bff6c0 Level-0 table #108: 0 bytes OK
2025/02/05-20:50:19.851086 7ffae6bff6c0 Delete type=0 #106
2025/02/05-20:50:19.863187 7ffae6bff6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)
2025/09/24-14:48:23.223575 7f7d00dfa6c0 Recovering log #253
2025/09/24-14:48:23.234727 7f7d00dfa6c0 Delete type=3 #251
2025/09/24-14:48:23.234789 7f7d00dfa6c0 Delete type=0 #253
2025/09/24-15:08:26.173817 7f7cf9fff6c0 Level-0 table #258: started
2025/09/24-15:08:26.173861 7f7cf9fff6c0 Level-0 table #258: 0 bytes OK
2025/09/24-15:08:26.233062 7f7cf9fff6c0 Delete type=0 #256
2025/09/24-15:08:26.424194 7f7cf9fff6c0 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

View File

View File

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

View File

@@ -1 +1 @@
MANIFEST-000106
MANIFEST-000258

View File

@@ -1,7 +1,7 @@
2025/02/13-22:35:49.055633 7fcc38ffa6c0 Recovering log #104
2025/02/13-22:35:49.118535 7fcc38ffa6c0 Delete type=3 #102
2025/02/13-22:35:49.118612 7fcc38ffa6c0 Delete type=0 #104
2025/02/13-22:42:05.128785 7fcc327fc6c0 Level-0 table #109: started
2025/02/13-22:42:05.128812 7fcc327fc6c0 Level-0 table #109: 0 bytes OK
2025/02/13-22:42:05.134704 7fcc327fc6c0 Delete type=0 #107
2025/02/13-22:42:05.142195 7fcc327fc6c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at (end)
2025/09/24-15:09:29.084820 7f7d00dfa6c0 Recovering log #256
2025/09/24-15:09:29.094841 7f7d00dfa6c0 Delete type=3 #254
2025/09/24-15:09:29.094891 7f7d00dfa6c0 Delete type=0 #256
2025/09/24-15:11:47.367611 7f7cf9fff6c0 Level-0 table #261: started
2025/09/24-15:11:47.367694 7f7cf9fff6c0 Level-0 table #261: 0 bytes OK
2025/09/24-15:11:47.374747 7f7cf9fff6c0 Delete type=0 #259
2025/09/24-15:11:47.393269 7f7cf9fff6c0 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/02/05-20:07:00.587007 7ffaed3fa6c0 Recovering log #100
2025/02/05-20:07:00.596905 7ffaed3fa6c0 Delete type=3 #98
2025/02/05-20:07:00.596964 7ffaed3fa6c0 Delete type=0 #100
2025/02/05-20:50:19.857097 7ffae6bff6c0 Level-0 table #105: started
2025/02/05-20:50:19.857120 7ffae6bff6c0 Level-0 table #105: 0 bytes OK
2025/02/05-20:50:19.863064 7ffae6bff6c0 Delete type=0 #103
2025/02/05-20:50:19.863205 7ffae6bff6c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at (end)
2025/09/24-14:48:23.198206 7f7cfb7fe6c0 Recovering log #252
2025/09/24-14:48:23.208784 7f7cfb7fe6c0 Delete type=3 #250
2025/09/24-14:48:23.208841 7f7cfb7fe6c0 Delete type=0 #252
2025/09/24-15:08:25.940494 7f7cf9fff6c0 Level-0 table #257: started
2025/09/24-15:08:25.940624 7f7cf9fff6c0 Level-0 table #257: 0 bytes OK
2025/09/24-15:08:25.991041 7f7cf9fff6c0 Delete type=0 #255
2025/09/24-15:08:26.173621 7f7cf9fff6c0 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

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

View File

@@ -1 +1 @@
MANIFEST-000114
MANIFEST-000269

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