34 Commits

Author SHA1 Message Date
a37ce76ab8 Add release action
All checks were successful
Release Creation / build (release) Successful in 1m3s
2025-02-21 10:40:14 +01:00
bbc046bc66 Release version 2025-02-19 21:13:14 +01:00
fd0864cea6 Release version 2025-02-19 21:10:44 +01:00
bf7a9f9ea5 Fix actions/tour 2025-02-13 22:42:56 +01:00
86dfa54314 Fix defense rolls 2025-02-06 10:23:38 +01:00
891a6647b7 Roll shields 2025-02-06 10:23:24 +01:00
5d9a218e04 Init, competences de base, fix creation de perso, etc 2025-02-04 21:25:08 +01:00
a0733dc049 Init, competences de base, fix creation de perso, etc 2025-02-04 21:24:47 +01:00
c32be6b24d Init, competences de base, fix creation de perso, etc 2025-02-04 21:20:54 +01:00
6f278ab8eb Minor fixes 2025-02-04 15:24:40 +01:00
b2ab6ffaa7 Various fixes and enhancements 2025-02-04 08:13:48 +01:00
94d26e971e Various fixes and enhancements 2025-02-04 08:13:26 +01:00
7eed052645 Various fixes and enhancements 2025-02-04 08:07:12 +01:00
00c1d02b6b Various fixes and enhancements 2025-02-03 23:02:39 +01:00
92396da997 Various fixes and enhancements 2025-02-03 23:00:59 +01:00
a72e671f75 First full step for character creation 2025-01-31 11:54:52 +01:00
6331ab9736 Update ! 2025-01-28 21:40:20 +01:00
4a346a4386 Minor fixes for education 2024-12-19 19:15:43 +01:00
b8de37f388 Update education + logo pause 2024-12-05 22:48:23 +01:00
4fd537c9ea Update education + logo pause 2024-12-05 22:46:48 +01:00
3a2dc7be63 Ajout de 8 questions 2024-12-05 16:23:49 +01:00
ff1252dcf5 Ajout de 8 questions 2024-12-05 16:15:16 +01:00
7a768c5426 Fix title 2024-10-27 11:51:08 +01:00
9b2016d069 Fix education + simples 2024-09-17 16:10:22 +02:00
5d843af069 Fix education + simples 2024-09-17 16:05:50 +02:00
b3655d011e Add new options for education 2024-09-16 18:37:41 +02:00
0d7c4323b5 Enhance armes+armures 2024-09-15 09:10:35 +02:00
029ad04e26 Enhance armes+armures 2024-09-13 22:14:21 +02:00
9c93134d1c Arme à distance 2024-07-10 22:59:38 +02:00
37d8957448 New version 2024-07-08 21:44:34 +02:00
629d369693 Ajout multiples pour le combat et ameliorations des items 2024-07-08 07:54:53 +02:00
10b7fcac09 Gestion des jets opposés 2024-06-06 17:17:04 +02:00
de195aff1e Gestion des jets opposés 2024-06-06 17:16:53 +02:00
82e7a170c2 Gestion des jets opposés 2024-06-06 17:16:40 +02:00
136 changed files with 2832 additions and 3498 deletions

View File

@ -0,0 +1,52 @@
name: Release Creation
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner."
#- uses: actions/checkout@v3
- uses: RouxAntoine/checkout@v3.5.4
# get part of the tag after the `v`
- name: Extract tag version number
id: get_version
uses: battila7/get-version-action@v2
# Substitute the Manifest and Download URLs in the module.json
- name: Substitute Manifest and Download Links For Versioned Ones
id: sub_manifest_link_version
uses: microsoft/variable-substitution@v1
with:
files: 'system.json'
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
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
- run: |
apt update -y
apt install -y zip
- run: zip -r ./fvtt-te-deum-${{github.event.release.tag_name}}.zip system.json template.json README.md LICENSE.txt assets/ fonts/ images/ lang/ modules/ styles/ packs/ templates/ te-deum.mjs
- name: setup go
uses: https://github.com/actions/setup-go@v4
with:
go-version: '>=1.20.1'
- name: Use Go Action
id: use-go-action
uses: https://gitea.com/actions/release-action@main
with:
files: |-
./fvtt-te-deum-${{github.event.release.tag_name}}.zip
system.json
api_key: '${{secrets.ALLOW_PUSH_RELEASE}}'

View File

@ -1,4 +1,4 @@
Copyright 2023 Open Sesame Games
Copyright 2025 Open Sesame Games
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -1,37 +1,17 @@
# Te Deum Pour Un Massacre for FoundryVTT (French RPG, Open Sesam Games, Official)
This is a base game system with functionnal character sheets for the game Te Deum.
You can join the kickstarter and obtain the base books here : https://www.kickstarter.com/projects/osg-us/ecryme
# System overview
The game system in Foundry offers the following features :
- PC/NPC sheet
- Skill rolls
- Cephaly rolls (with Anency support)
- Confrontation management, with detailed result in the chat card
- Weapon rolls
- Trait management, with Spleen and Ideal also.
- Compendiums of items for the game
![System Snapshot](https://www.lahiette.com/leratierbretonnien/wp-content/uploads/2023/08/ecryme_snapshot_01.webp "System Snapshot")
# Système Foundry pour Te Deum pour un massacre (French RPG, Open Sesam 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/)
# Copyright mentions
Copyright 2023 Open Sesame Games
Copyright 2025 Open Sesame Games
All rights reserved
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Requests or Problems
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: 8.1 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
images/icons/blessure.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
images/icons/maladie.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
images/icons/simple.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
images/ui/femme_gauche.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

BIN
images/ui/homme_droit.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 KiB

View File

@ -1,175 +1,20 @@
{
"TYPES": {
"Actor":{
"pc": "Personnage Joueur",
"npc": "Personnage Non Joueur",
"annency": "Anence"
"pj": "Personnage Joueur",
"pnj": "Personnage Non Joueur"
},
"Item": {
"trait": "Trait",
"weapon": "Arme",
"equipment": "Equipement",
"maneuver": "Manoeuvre",
"specialization": "Spécialisation"
}
},
"ECRY": {
"settings": {
"cogs": "Engrenages",
"cephaly": "Céphalie",
"boheme": "Bohême",
"amertume": "Amertume",
"gamelevel": "Niveau de jeu"
},
"chat": {
"formula": "Formule",
"difficulty": "Difficulté",
"dicesum": "Dés",
"result": "Resultat",
"margin": "Marge",
"success": "Succés!",
"failure": "Echec!",
"specialization": "Spécialisation",
"traitbonus": "Trait bonus",
"traitmalus": "Trait malus",
"bonusmalustraits": "Bonus/Malus des Traits",
"spectranscend": "Dépassement de soi : ",
"confrontselected": "Confrontation selectionnée",
"sentogm": "La confrontation a été envoyée au MJ"
},
"rule": {
"cephaly-success-12": "Durée : 1 scène - Impact : Superficiel - Bonus : 1 - Elegie : 1",
"cephaly-success-4": "Durée : 1 semaine - Impact : Léger - Bonus : 2 - Elegie : 2",
"cephaly-success-6": "Durée : 1 mois - Impact : Grave - Bonus : 3 - Elegie : 3",
"cephaly-success-8": "Durée : 1 année - Impact : Majeur - Bonus : 4 - Elegie : 4",
"cephaly-success-10": "Durée : Permanent - Impact : Mort - Bonus : 5 - Elegie : 5",
"cephaly-failure-2": "Durée : 1 scène - Impact : Superficiel - Malus : 1 - Symptôme non visible et sans gravité - Altération bégigne difficilement repérable",
"cephaly-failure-4": "Durée : 1 semaine - Impact : Léger - Malus : 2 - Symptôme visible non incapacitant - Altération repérable",
"cephaly-failure-6": "Durée : 1 mois - Impact : Grave - Malus : 3 - Symptôme incapacitant - Altération repérable et fâcheuse",
"cephaly-failure-8": "Durée : 1 année - Impact : Majeur - Malus : 4 - Symptôme très incapacitant - Altération dangereuse",
"cephaly-failure-10": "Durée : Permanent - Impact : Mort/Folie - Malus : 5 - Symptôme spectaculaire et repoussant - Altération dangereuse globalement"
},
"warn": {
"notenoughdice": "L'Accomplissement et la Préservation doivent avoir 2 dés chacun"
},
"ui": {
"equipmentfree": "Equipements (saisie libre)",
"traitType": "Type de trait",
"niveauTrait": "Niveau du trait",
"effect": "Incidence",
"weight": "Poids",
"cost": "Prix",
"costUnit": "Unité",
"ingot": "Lingot",
"ingotin": "Lingotin",
"goldcoin": "Pièce d'or",
"lige": "Lige",
"hurle": "Hurle",
"coin": "Sous",
"notes": "Notes",
"bio": "Bio",
"bionotes": "Bio&Notes",
"skills": "Compétences",
"traits": "Traits",
"equipment": "Equipement",
"physical": "Physiques",
"mental": "Mentales",
"social": "Sociales",
"athletics": "Athlétisme",
"driving": "Conduite",
"fencing": "Escrime",
"brawling": "Pugilat",
"shooting": "Tir",
"anthropomecanology": "Anthropo-Mécanologie",
"ecrymology": "Écrymologie",
"traumatology": "Traumatologie",
"traversology": "Traversologie",
"urbatechnology": "Urbatechnologie",
"quibbling": "Argutie",
"creativity": "Créativité",
"loquacity": "Faconde",
"guile": "Maraude",
"performance" :"Représentation",
"skill": "Compétence",
"troublesome": "Malaisé",
"occasional": "Peu frequent",
"difficult": "Difficile",
"uncommon": "Atypique",
"verydifficult": "Très difficile",
"rare": "Rare",
"extremdifficult": "Extrêmement difficile",
"veryrare": "Très rare",
"increddifficult": "Incroyable",
"exceptrare": "Exceptionnel",
"none": "Aucun",
"roll": "Lancer les dés !",
"cancel": "Annuler",
"rolltitle": "Ou l'on teste ses compétences",
"spec": "Spécialisation",
"traitbonus": "Traits bonus",
"traitmalus": "Traits malus",
"applyideal": "Utiliser l'idéal",
"applyspleen": "Utiliser le spleen",
"skilltranscendence": "Dépassement de soi",
"confrontation": "Confrontation",
"rollnormal": "Normal (4d6)",
"rollspleen": "Avec le Spleen (5d6, 4 plus bas conservés)",
"rollideal": "Avec l'Idéal (5d6, 4 plus haut conservés)",
"superficial": "Superficiel",
"light": "Léger",
"serious": "Grave",
"major": "Majeur",
"impactType": "Type d'Impact",
"impactLevel": "Niveau d'impact",
"impactphysical": "Physique",
"impactmental": "Mental",
"impactsocial": "Social",
"impactmalus": "Malus d'Impact",
"ongoingconfront": "Confrontations en cours",
"confront":"Confrontation",
"launchconfront": "Lancer la confrontation",
"execution": "Accomplissement",
"preservation": "Préservation",
"dicepool": "Dés disponibles",
"selectconfront": "Sélectionner pour la Confrontation",
"transcendapply": "Appliquer la Transcendence à ",
"healthcombat": "Santé&Combat",
"name": "Nom",
"weapons": "Armes",
"weapon": "Arme",
"melee": "Mêlée",
"ranged": "A Distance",
"weapontype": "Type d'arme",
"type": "Type",
"applyimpact": "Appliquer l'impact",
"applybonus": "Appliquer le bonus",
"bonuspool": "Bonus disponibles",
"cephaly": "Cephalie",
"elegy": "Elégie",
"entelechy": "Entéléchie",
"mekany": "Mekanë",
"psyche": "Psyché",
"scoria": "Scorie",
"cephalydifficulty": "Difficulté de la Céphalie",
"maneuvers": "Manoeuvres",
"annency": "Anence",
"iscollective": "Collective",
"ismultiple": "Multiple",
"description": "Description",
"location": "Lieu",
"characters": "Personnages",
"enhancements": "Améliorations",
"oniricform": "Forme Onorique (Bohême)",
"ideals": "Idéaux",
"politic": "Idéaux politiques",
"boheme": "Bohême",
"annencybonus": "Bonus d'Anence",
"bornplace": "Lieu de naissance",
"residence": "Résidence",
"origin": "Origine",
"childhood": "Enfance",
"bonus": "Bonus"
"competence": "Competence",
"arme": "Arme",
"equipement": "Equipement",
"armure": "Armure",
"grace": "Grace",
"origine": "Origine",
"education": "Education",
"blessure": "Blessure",
"maladie": "Maladie",
"simple": "Simple"
}
}
}

View File

@ -11,7 +11,7 @@ export class TeDeumActorPJSheet extends ActorSheet {
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["fvtt-te-deum", "sheet", "actor"],
template: "systems/fvtt-te-deum/templates/actors/actor-sheet.hbs",
width: 860,
@ -33,16 +33,28 @@ export class TeDeumActorPJSheet extends ActorSheet {
name: this.actor.name,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
system: duplicate(this.object.system),
system: foundry.utils.duplicate(this.object.system),
limited: this.object.limited,
competences: this.actor.getCompetences(),
config: duplicate(game.system.tedeum.config),
config: foundry.utils.duplicate(game.system.tedeum.config),
armes: this.actor.getArmes(),
caracList: this.actor.prepareCaracteristiques(),
providence: this.actor.prepareProvidence(),
arbreCompetences: this.actor.prepareArbreCompetences(),
equipements: this.actor.getEquipements(),
armures: this.actor.getArmures(),
graces: this.actor.getGraces(),
blessures: this.actor.getBlessures(),
maladies: this.actor.getMaladies(),
poisons: this.actor.getPoisons(),
combat: this.actor.prepareCombat(),
bonusDegats: this.actor.getBonusDegats(),
nbActions: this.actor.getNbActions(),
initiative: this.actor.getInitiative(),
pointsArmuresLourdes: this.actor.getNbArmures(),
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 }),
options: this.options,
@ -115,6 +127,11 @@ export class TeDeumActorPJSheet extends ActorSheet {
const armeId = $(event.currentTarget).data("arme-id")
this.actor.rollArme(armeId)
});
html.find('.roll-degats').click((event) => {
const armeId = $(event.currentTarget).data("arme-id")
this.actor.rollDegatsArme(armeId)
});
html.find('.lock-unlock-sheet').click((event) => {
this.options.editScore = !this.options.editScore;

View File

@ -34,12 +34,24 @@ export class TeDeumActor extends Actor {
return actor;
}
if (data.type == 'pj') {
const skills = await TeDeumUtility.loadCompendium("fvtt-te-deum.competences")
data.items = data.items || []
for (let skill of skills) {
if (skill.system.isBase || skill.system.score == 1) {
data.items.push(skill.toObject())
}
}
}
return super.create(data, options);
}
/* -------------------------------------------- */
async prepareData() {
super.prepareData()
}
/* -------------------------------------------- */
@ -53,6 +65,62 @@ export class TeDeumActor extends Actor {
super._preUpdate(changed, options, user);
}
/* -------------------------------------------- */
_onUpdate(changed, options, userId) {
let updates = []
let memoriser = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mémoriser")
let newScore = this.getCommonBaseValue(this.system.caracteristiques.adresse.value)
if (memoriser && memoriser?.system.score != newScore) {
updates.push({ _id: memoriser.id, "system.score": Number(newScore) })
}
let perception = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "perception")
newScore = this.getCommonBaseValue(this.system.caracteristiques.sensibilite.value)
if (perception && perception.system.score != newScore) {
updates.push({ _id: perception.id, "system.score": Number(newScore) })
}
let charme = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "charme")
newScore = this.getCommonBaseValue(this.system.caracteristiques.entregent.value)
if (charme && charme?.system.score != newScore) {
updates.push({ _id: charme.id, "system.score": Number(newScore) })
}
let endurance = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "endurance")
newScore = this.getCommonBaseValue(this.system.caracteristiques.complexion.value)
if (endurance && endurance?.system.score != newScore) {
updates.push({ _id: endurance.id, "system.score": Number(newScore) })
}
let course = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "course")
newScore = this.getCommonBaseValue(this.system.caracteristiques.adresse.value)
if (course && course?.system.score != newScore) {
updates.push({ _id: course.id, "system.score": Number(newScore) })
}
let initiative = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "initiative")
newScore = this.getCommonBaseValue(this.system.caracteristiques.adresse.value)
if (initiative && initiative?.system.score != newScore) {
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) {
updates.push({ _id: effort.id, "system.score": Number(newScore) })
}
if (updates.length > 0) {
this.updateEmbeddedDocuments('Item', updates)
}
}
/* -------------------------------------------- */
async _preCreate(data, options, user) {
await super._preCreate(data, options, user);
@ -65,6 +133,13 @@ export class TeDeumActor extends Actor {
this.updateSource({ prototypeToken });
}
/* -------------------------------------------- */
getCommonBaseValue(value) {
return game.system.tedeum.config.COMMON_VALUE[value]?.value || 0
}
getInitiative() {
return game.system.tedeum.config.COMMON_VALUE[this.system.caracteristiques.adresse.value]?.value || 0
}
/* -------------------------------------------- */
getBonusDegats() {
return game.system.tedeum.config.BONUS_DEGATS[this.system.caracteristiques.puissance.value]
@ -76,51 +151,143 @@ export class TeDeumActor extends Actor {
getNbActions() {
return game.system.tedeum.config.ACTIONS_PAR_TOUR[this.system.caracteristiques.adresse.value]
}
getInitiative() {
return game.system.tedeum.config.ACTIONS_PAR_TOUR[this.system.caracteristiques.adresse.value]
}
getNbArmuresLourdesActuel() {
let armures = this.getArmures()
let nb = 0
for (let armure of armures) {
if (armure.system.equipe) {
nb += armure.system.coutArmureLourde
}
}
return nb
}
/* -------------------------------------------- */
getEducations() {
let educations = this.items.filter(item => item.type == 'education')
return educations
}
/* -------------------------------------------- */
getCompetences() {
let comp = duplicate(this.items.filter(item => item.type == 'competence') || [])
let comp = foundry.utils.duplicate(this.items.filter(item => item.type == 'competence') || [])
return comp;
}
/* -------------------------------------------- */
getGraces() {
let comp = duplicate(this.items.filter(item => item.type == 'grace') || [])
let comp = foundry.utils.duplicate(this.items.filter(item => item.type == 'grace') || [])
TeDeumUtility.sortArrayObjectsByName(comp)
return comp;
}
getArmes() {
let comp = duplicate(this.items.filter(item => item.type == 'arme') || [])
let comp = foundry.utils.duplicate(this.items.filter(item => item.type == 'arme') || [])
TeDeumUtility.sortArrayObjectsByName(comp)
return comp;
}
getEquipements() {
let comp = duplicate(this.items.filter(item => item.type == 'equipement') || [])
let comp = foundry.utils.duplicate(this.items.filter(item => item.type == 'equipement') || [])
TeDeumUtility.sortArrayObjectsByName(comp)
return comp;
}
getArmures() {
let comp = duplicate(this.items.filter(item => item.type == 'armure') || [])
let comp = foundry.utils.duplicate(this.items.filter(item => item.type == 'armure') || [])
TeDeumUtility.sortArrayObjectsByName(comp)
return comp;
}
getBlessures() {
let comp = foundry.utils.duplicate(this.items.filter(item => item.type == 'blessure') || [])
for (let c of comp) {
let blessDef = game.system.tedeum.config.blessures[c.system.typeBlessure]
c.malus = blessDef.modifier
}
TeDeumUtility.sortArrayObjectsByName(comp)
return comp;
}
getMaladies() {
let comp = foundry.utils.duplicate(this.items.filter(item => item.type == 'maladie') || [])
for (let c of comp) {
c.malus = "N/A"
if (c.system.appliquee) {
let malDef = game.system.tedeum.config.virulence[c.system.virulence]
c.malus = malDef.modifier
}
}
TeDeumUtility.sortArrayObjectsByName(comp)
return comp;
}
getPoisons() {
let comp = foundry.utils.duplicate(this.items.filter(item => item.type == 'poison') || [])
for (let c of comp) {
c.malus = "N/A"
if (c.system.appliquee) {
let poisDef = game.system.tedeum.config.virulencePoison[c.system.virulence]
c.malus = poisDef.modifier
}
}
TeDeumUtility.sortArrayObjectsByName(comp)
return comp;
}
/* -------------------------------------------- */
calculMalusBlessures() {
let modifierBlessures = 0
let nbBlessures = 0
// Cumul des malus de blessures
for (let locKey in this.system.localisation) {
let loc = this.system.localisation[locKey]
let bDef = game.system.tedeum.config.blessures[loc.blessures]
modifierBlessures += bDef.modifier
nbBlessures += bDef.count
getSanteModifier() {
let comp = foundry.utils.duplicate(this.items.filter(item => item.type == 'maladie') || [])
let modTotal = 0
for (let c of comp) {
if (c.system.appliquee) {
let maladieDef = game.system.tedeum.config.virulence[c.system.virulence]
modTotal += maladieDef.modifier
}
}
let simples = foundry.utils.duplicate(this.items.filter(item => item.type == 'simple') || [])
for (let c of simples) {
if (c.system.appliquee) {
let simpleDef = game.system.tedeum.config.virulencePoison[c.system.virulence]
modTotal += simpleDef.modifier
}
}
let blessures = foundry.utils.duplicate(this.items.filter(item => item.type == 'blessure') || [])
for (let c of blessures) {
let blessDef = game.system.tedeum.config.blessures[c.system.typeBlessure]
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 ( nbBlessures > endurance.system.score) {
modifierBlessures += -1
if (blessures.length > endurance.system.score) {
modTotal += -1
}
return modifierBlessures
return modTotal
}
/* -------------------------------------------- */
async appliquerDegats(rollData) {
let combat = this.prepareCombat()
rollData.defenderName = this.name
let touche = combat[rollData.loc.id].touche
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,
}
}
rollData.blessure = blessureObj
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)
})
await msg.setFlag("world", "te-deum-rolldata", rollData)
}
/* -------------------------------------------- */
@ -135,10 +302,11 @@ export class TeDeumActor extends Actor {
/* -------------------------------------------- */
prepareCaracteristiques() {
let carac = foundry.utils.deepClone(this.system.caracteristiques)
let carac = foundry.utils.deepClone(this.system.caracteristiques)
for (let key in carac) {
let c = carac[key]
this.updateCarac(c, key)
c.description = game.system.tedeum.config.caracteristiques[key].description
}
return carac
}
@ -146,22 +314,49 @@ 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
providence.qualite = game.system.tedeum.config.providence[providence.value].labelM
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
}
/* -------------------------------------------- */
prepareCombat() {
let combatLoc = foundry.utils.deepClone(this.system.localisation)
for (let key in combatLoc) {
combatLoc[key] = foundry.utils.mergeObject(combatLoc[key], game.system.tedeum.config.LOCALISATION[key])
combatLoc[key].armures = []
combatLoc[key].blessures = []
combatLoc[key].protectionTotal = 0
let armures = this.getArmures()
for (let armure of armures) {
if (armure.system.equipe && armure.system.localisation[key].protege) {
combatLoc[key].armures.push(armure)
combatLoc[key].protectionTotal += armure.system.protection
}
}
let blessures = this.getBlessures()
for (let blessure of blessures) {
if (blessure.system.localisation == key) {
combatLoc[key].blessures.push(blessure)
}
}
let endurance = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "endurance")
combatLoc[key].endurance = endurance.system.score + game.system.tedeum.config.LOCALISATION[key].locMod
combatLoc[key].touche = combatLoc[key].endurance + combatLoc[key].protectionTotal
}
return combatLoc
}
/* -------------------------------------------- */
modifyProvidence(value) {
let providence = foundry.utils.duplicate(this.system.providence)
providence.value = Math.min(Math.max(providence.value + value, 0), 6)
this.update( { "system.providence": providence } )
this.update({ "system.providence": providence })
}
/* -------------------------------------------- */
modifyXP(key, value) {
let xp = this.system.caracteristiques[key].experience
xp = Math.max(xp + value, 0)
this.update( { [`system.caracteristiques.${key}.experience`]: xp } )
this.update({ [`system.caracteristiques.${key}.experience`]: xp })
}
/* -------------------------------------------- */
@ -174,7 +369,8 @@ export class TeDeumActor extends Actor {
let caracDice = game.system.tedeum.config.descriptionValeur[this.system.caracteristiques[c.system.caracteristique].value].dice
c.system.formula = caracDice + "+" + c.system.score
})
return foundry.utils.deepClone( comp || {} )
comp = comp.sort((a, b) => a.name.localeCompare(b.name))
return foundry.utils.deepClone(comp || {})
}
/* -------------------------------------------- */
@ -192,7 +388,7 @@ export class TeDeumActor extends Actor {
getItemById(id) {
let item = this.items.find(item => item.id == id);
if (item) {
item = duplicate(item)
item = foundry.utils.duplicate(item)
}
return item;
}
@ -200,29 +396,58 @@ export class TeDeumActor extends Actor {
/* -------------------------------------------- */
async equipItem(itemId) {
let item = this.items.find(item => item.id == itemId)
if (item?.system) {
if (item.type == "armure") {
let armor = this.items.find(item => item.id != itemId && item.type == "armor" && item.system.equipped)
if (armor) {
ui.notifications.warn("You already have an armor equipped!")
return
if (!this.checkArmure(item)) {
return
}
let update = { _id: item.id, "system.equipe": !item.system.equipe };
await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
}
/* ------------------------------------------- */
checkArmure(item) {
if (item.type != "armure") {
return true
}
if (item.system.equipe) {
return true
}
let nbArmuresLourdes = this.getNbArmuresLourdesActuel()
if (nbArmuresLourdes + item.system.coutArmureLourde > this.getNbArmures().value) {
ui.notifications.warn("Impossible d'équiper cette armure, nombre d'armures lourdes maximum atteint")
return false
}
// Loop thru localisation
let armures = this.getArmures()
for (let loc in item.system.localisation) {
if (item.system.localisation[loc].protege) {
for (let armure of armures) {
if (armure.system.equipe && armure.system.localisation[loc].protege) {
let flag = true
//console.log("Check armure", armure, item)=
if (item.system.typeArmure == "cuir") {
flag = armure.system.superposableCuir
}
if (item.system.typeArmure == "maille") {
flag = armure.system.superposableMaille
}
if (item.system.typeArmure == "plate") {
flag = armure.system.superposablePlate
}
if (!flag) {
ui.notifications.warn("Impossible d'équiper cette armure, non superposable")
return flag
}
}
}
}
if (item.type == "shield") {
let shield = this.items.find(item => item.id != itemId && item.type == "shield" && item.system.equipped)
if (shield) {
ui.notifications.warn("You already have a shield equipped!")
return
}
}
let update = { _id: item.id, "system.equipped": !item.system.equipped };
await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
return true
}
}
/* ------------------------------------------- */
async buildContainerTree() {
let equipments = duplicate(this.items.filter(item => item.type == "equipment") || [])
let equipments = foundry.utils.duplicate(this.items.filter(item => item.type == "equipment") || [])
for (let equip1 of equipments) {
if (equip1.system.iscontainer) {
equip1.system.contents = []
@ -278,10 +503,13 @@ export class TeDeumActor extends Actor {
}
/* -------------------------------------------- */
getInitiativeScore(combatId, combatantId) {
let init = Math.floor((this.system.attributs.physique.value + this.system.attributs.habilite.value) / 2)
let subValue = new Roll("1d20").roll({ async: false })
return init + (subValue.total / 100)
getInitiativeScore() {
let initiative = this.items.find(it => it.type == "competence" && it.name.toLowerCase() == "initiative")
if (initiative) {
return initiative.system.score
}
ui.notifications.warn("Impossible de trouver la compétence Initiative pour l'acteur " + this.name)
return -1;
}
/* -------------------------------------------- */
@ -308,7 +536,7 @@ export class TeDeumActor extends Actor {
}
}
}
/* -------------------------------------------- */
getCommonRollData() {
let rollData = TeDeumUtility.getBasicRollData()
@ -317,7 +545,7 @@ export class TeDeumActor extends Actor {
rollData.actorId = this.id
rollData.img = this.img
rollData.providence = this.prepareProvidence()
rollData.malusBlessures = this.calculMalusBlessures()
rollData.santeModifier = this.getSanteModifier()
return rollData
}
@ -325,12 +553,12 @@ export class TeDeumActor extends Actor {
/* -------------------------------------------- */
getCommonCompetence(compId) {
let rollData = this.getCommonRollData()
let competence = duplicate(this.items.find(it => it.type =="competence" && it.id == compId))
let competence = foundry.utils.duplicate(this.items.find(it => it.type == "competence" && it.id == compId))
rollData.competence = competence
let c = foundry.utils.duplicate(this.system.caracteristiques[competence.system.caracteristique])
this.updateCarac( c, competence.system.caracteristique)
this.updateCarac(c, competence.system.caracteristique)
rollData.carac = c
rollData.img = competence.img
@ -345,17 +573,67 @@ export class TeDeumActor extends Actor {
this.startRoll(rollData).catch("Error on startRoll")
}
/* -------------------------------------------- */
rollArme(armeId) {
async rollDegatsArme(armeId) {
let weapon = this.items.get(armeId)
if (weapon) {
weapon = duplicate(weapon)
let bDegats = 0
if ( weapon.system.typeArme == "melee" ) {
bDegats = this.getBonusDegats()
}
let formula = weapon.system.degats + "+" + bDegats.value
let degatsRoll = await new Roll(formula).roll()
await TeDeumUtility.showDiceSoNice(degatsRoll, game.settings.get("core", "rollMode") )
let rollData = this.getCommonRollData()
rollData.mode = "degats"
rollData.formula = formula
rollData.arme = foundry.utils.duplicate(weapon)
rollData.degatsRoll = foundry.utils.duplicate(degatsRoll)
rollData.degats = degatsRoll.total
let msg = await TeDeumUtility.createChatWithRollMode(rollData.alias, {
content: await renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-degats-result.hbs`, rollData)
})
await msg.setFlag("world", "te-deum-rolldata", rollData)
console.log("Rolldata result", rollData)
}
}
/* -------------------------------------------- */
rollArme(armeId, compName = undefined) {
let weapon = this.items.get(armeId)
if (weapon) {
weapon = foundry.utils.duplicate(weapon)
let rollData = this.getCommonRollData()
rollData.mode = "arme"
rollData.isTir = weapon.system.typeArme == "tir"
rollData.arme = weapon
rollData.img = weapon.img
rollData.title = weapon.name
rollData.porteeTir = "courte"
rollData.porteeLabel = game.system.tedeum.config.ARME_PORTEES.courte.label
rollData.isViser = false
rollData.isMouvement = false
// Display warning if not target defined
if (!rollData.defenderTokenId) {
ui.notifications.warn("Vous attaquez avec une arme : afin de bénéficier des automatisations, il est conseillé de selectionner une cible")
}
// Setup competence + carac
if (!compName) {
compName = weapon.system.competence
}
let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == compName.toLowerCase())
if (competence) {
rollData.competence = competence
let c = foundry.utils.duplicate(this.system.caracteristiques[competence.system.caracteristique])
this.updateCarac(c, competence.system.caracteristique)
rollData.carac = c
} else {
ui.notifications.warn("Impossible de trouver la compétence " + compName)
return
}
this.startRoll(rollData).catch("Error on startRoll")
} else {
ui.notifications.warn("Impossible de trouver l'arme concernée ")

View File

@ -0,0 +1,604 @@
import { TeDeumUtility } from "../common/tedeum-utility.js";
import { TeDeumActor } from "../actors/tedeum-actor.js";
export class TeDeumCharacterCreator {
/*--------------------------------------------*/
async init() {
this.stages = {}
this.currentStage = "origineSociale"
this.sex = undefined
this.origineSociale = undefined
this.religion = undefined
this.caracBonus = {}
this.competenceBonus = {}
this.competences = TeDeumUtility.getCompetencesForDropDown()
for (let k in game.system.tedeum.config.caracteristiques) {
this.caracBonus[k] = { value: 0 }
}
for (let stage in game.system.tedeum.config.etapesEducation) {
this.stages[stage] = { selectedItem: null, items: [] }
}
const educations = await TeDeumUtility.loadCompendium("fvtt-te-deum.education")
for (let edu of educations) {
this.stages[edu.system.etape].items.push(edu)
}
this.processStage()
}
/*--------------------------------------------*/
increaseCompetence(compName) {
if (compName === "" || compName == undefined || compName == "undefined") { return }
compName = compName.toLowerCase()
if (!this.competenceBonus[compName]) {
this.competenceBonus[compName] = { value: 1 }
} else {
this.competenceBonus[compName].value += 1
}
}
/*--------------------------------------------*/
processReponses(question) {
let fullResponses = []
for (let key in question.reponses) {
let response = question.reponses[key]
fullResponses.push({ id: key, label: `${response.reponse} (${TeDeumUtility.upperFirst( response.compName)} +1)` })
}
return fullResponses
}
/*--------------------------------------------*/
processReponsesRadio(question) {
let fullResponses = {}
let selected = true
for (let key in question.reponses) {
let response = question.reponses[key]
if (response.toSelect) {
fullResponses[key] = { label: `${response.reponse}`, competences: response.compList, selected }
} else {
fullResponses[key] = { label: `${response.reponse} (${response.compName} +1)`, selected }
}
selected = false
}
return fullResponses
}
/*--------------------------------------------*/
async askStageName(context) {
const content = await 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"],
content,
buttons: [
{
label: context.label,
callback: (event, button, dialog) => {
const output = Array.from(button.form.elements).reduce((obj, input) => {
if (input.name) obj[input.name] = input.value
return obj
}, {})
return output
},
},
],
actions: {
},
rejectClose: false, // Click on Close button will not launch an error
render: (event, dialog) => {
$(".stage-selector").change(event => {
let stageId = event.target.value
let stage = context.choices.find(item => item.id === stageId)
let link = `<a class="content-link" draggable="true" data-link=""
data-uuid="Compendium.fvtt-te-deum.education.Item.${stageId}" data-id="${stageId}" data-type="Item"
data-pack="fvtt-te-deum.education" data-tooltip="Education Objet"><i class="fas fa-suitcase"></i>${stage.name}</a>`
$(".stage-main-details").html(`Voir le détail : ${link}`)
})
document.getElementById("stage-selector").dispatchEvent(new Event('change'))
}
})
return choiceResult
}
/*--------------------------------------------*/
processCompetences(compList) {
for (let compName in compList) {
this.increaseCompetence(compName)
}
}
/*--------------------------------------------*/
async askQuestionnaire(stage, context) {
context.subtitle = "Questionnaire"
for (let key in stage.system.questionnaire) {
let question = stage.system.questionnaire[key]
if (question.question === "") { break }
context.question = question.question
context.responses = this.processReponses(question)
context.responsesRadio = this.processReponsesRadio(question)
context.competences = {}
context.responseKey = "reponse1" // By default
const content = await 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"],
content,
buttons: [
{
label: context.label,
callback: (event, button, dialog) => {
const output = Array.from(button.form.elements).reduce((obj, input) => {
if (input.name) obj[input.name] = input.value
return obj
}, {})
return output
},
},
],
actions: {
},
rejectClose: false, // Click on Close button will not launch an error
render: (event, dialog) => {
$(".questionnaire-radio").click(event => {
let responseKey = $(event.target).data("response-key")
context.responseKey = responseKey
})
$(".questionnaire-select-competence").change(event => {
// Get the responseKey data
let responseKey = $(event.target).data("response-key")
let compName = event.target.value
console.log("Questionnaire Change", responseKey, compName)
context.competences[responseKey] = compName.toLowerCase()
})
}
})
if (choiceResult == null) {
this.currentStage = "cancelled"
return
}
let selectedResponse = question.reponses[context.responseKey]
let compName = context.competences[context.responseKey] || selectedResponse.compName
this.increaseCompetence(compName)
}
}
/*------------- -------------------------------*/
async askCompetences(stage, context) {
context.subtitle = "Choix des Compétences"
context.fixedCompetences = {}
context.selectCompetences = {}
for (let compKey in stage.system.competences) {
let comp = stage.system.competences[compKey]
if (comp.valid && comp.compName !== "") {
if (comp.toSelect) {
context.hasSelectCompetences = true
context.selectCompetences[comp.compName] = TeDeumUtility.upperFirst(comp.compName)
} else {
context.fixedCompetences[comp.compName] = TeDeumUtility.upperFirst(comp.compName)
}
}
}
const content = await 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"],
content,
buttons: [
{
label: context.label,
callback: (event, button, dialog) => {
const output = Array.from(button.form.elements).reduce((obj, input) => {
if (input.name) obj[input.name] = input.value
return obj
}, {})
return output
},
},
],
actions: {
},
rejectClose: false, // Click on Close button will not launch an error
render: (event, dialog) => {
}
})
if (choiceResult == null) {
this.currentStage = "cancelled"
return
}
context.fixedCompetences[choiceResult.selectedCompetence] = choiceResult.selectedCompetence
this.processCompetences(context.fixedCompetences)
// Handle specific case when multiple skills can be selected (ie compagnon case)
if ( stage.system.hasCompetencesOpt ) {
context.fixedCompetences = []
context.hasSelectCompetences = true
for (let i = 0; i < stage.system.competencesOptNumber; i++) {
context.competences = {}
context.selectCompetences = {}
for (let compKey in stage.system.competencesOpt) {
let comp = stage.system.competencesOpt[compKey]
if (comp.compName !== "") {
context.selectCompetences[comp.compName] = TeDeumUtility.upperFirst(comp.compName)
}
}
const content = await 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"],
content,
buttons: [
{
label: context.label,
callback: (event, button, dialog) => {
const output = Array.from(button.form.elements).reduce((obj, input) => {
if (input.name) obj[input.name] = input.value
return obj
}, {})
return output
},
},
],
actions: {
},
rejectClose: false, // Click on Close button will not launch an error
render: (event, dialog) => {
}
})
if (choiceResult == null) {
this.currentStage = "cancelled"
return
}
context.fixedCompetences[choiceResult.selectedCompetence] = choiceResult.selectedCompetence
this.processCompetences(context.fixedCompetences)
}
}
}
/*------------- -------------------------------*/
async askCarac(stage, context) {
context.subtitle = "Choix des Caractéristiques"
let selected = []
for (let i = 0; i < stage.system.nbChoixCarac; i++) {
context.caracList = []
for (let caracKey in stage.system.caracteristiques) {
let carac = stage.system.caracteristiques[caracKey]
if (selected.includes(carac.caracId)) { continue }
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 choiceResult = await foundry.applications.api.DialogV2.wait({
window: { title: context.title },
classes: ["fvtt-te-deum"],
content,
buttons: [
{
label: context.label,
callback: (event, button, dialog) => {
const output = Array.from(button.form.elements).reduce((obj, input) => {
if (input.name) obj[input.name] = input.value
return obj
}, {})
return output
},
},
],
actions: {
},
rejectClose: false, // Click on Close button will not launch an error
render: (event, dialog) => {
}
})
if (choiceResult == null) {
this.currentStage = "cancelled"
return
}
this.caracBonus[choiceResult.carac].value += 1
selected.push(choiceResult.carac)
}
}
/*--------------------------------------------*/
async renderOrigineSociale(stage) {
let context = {
title: "Création de personnage",
subtitle: "Origine Sociale",
sexeChoice: { "Homme": "Homme", "Femme": "Femme" },
religionChoice: { "catholique": "Catholique", "protestante": "Protestante" },
origineChoice: game.system.tedeum.config.origineSociale
}
const content = await 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 },
classes: ["fvtt-te-deum"],
content,
buttons: [
{
label: label,
callback: (event, button, dialog) => {
const output = Array.from(button.form.elements).reduce((obj, input) => {
if (input.name) obj[input.name] = input.value
return obj
}, {})
return output
},
},
],
actions: {
},
rejectClose: false, // Click on Close button will not launch an error
render: (event, dialog) => { }
})
if (choiceResult == null) {
this.currentStage = "cancelled"
return
}
this.sexe = choiceResult.sexe
this.religion = choiceResult.religion
this.origineSociale = foundry.utils.duplicate(game.system.tedeum.config.origineSociale[choiceResult.origineSociale])
for (let key in this.origineSociale.caracteristiques) {
this.caracBonus[key].value += this.origineSociale.caracteristiques[key]
}
this.currentStage = "pouponniere"
}
/*--------------------------------------------*/
async renderPouponniere(stage) {
// Filter available pouponniere from origineSociale
let pouponniereItems = stage.items.filter(item => item.system.accessible[this.origineSociale.id].isaccessible)
let context = {
title: "Création de personnage - La Pouponnière",
subtitle: "Choix de la Pouponnière",
label: "Valider le choix de la Pouponnière",
choices: pouponniereItems,
caracBonus: this.caracBonus,
competenceBonus: this.competenceBonus
}
let choiceResult = await this.askStageName(context)
if (choiceResult == null) {
this.currentStage = "cancelled"
return
}
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);
context.label = "Valider l'augmentation de caracteristique"
await this.askCarac(this.pouponniere, context)
context.label = "Valider l'augmentation de compétences"
await this.askCompetences(this.pouponniere, context)
context.label = "Valider cette réponse"
await this.askQuestionnaire(this.pouponniere, context)
this.currentStage = "petitsgrimauds"
}
/*--------------------------------------------*/
async renderPetitsGrimauds(stage) {
// Filter available pouponniere from origineSociale
let grimaudsItems = stage.items.filter(item => item.system.accessible[this.origineSociale.id].isaccessible)
let context = {
title: "Les Petits Grimauds",
label: "Valider le choix des Petits Grimauds",
choices: grimaudsItems,
caracBonus: this.caracBonus,
competenceBonus: this.competenceBonus
}
let choiceResult = await this.askStageName(context)
if (choiceResult == null) {
this.currentStage = "cancelled"
return
}
this.grimauds = foundry.utils.duplicate(stage.items.find(item => item.id === choiceResult.selectedItem))
context.title = `LesPetits Grimauds - ${this.grimauds.name}`
TeDeumUtility.prepareEducationContent(this.grimauds);
context.label = "Valider l'augmentation de caracteristique"
await this.askCarac(this.grimauds, context)
context.label = "Valider l'augmentation de compétences"
await this.askCompetences(this.grimauds, context)
context.label = "Valider cette réponse"
await this.askQuestionnaire(this.grimauds, context)
this.currentStage = "rosevie"
}
/*--------------------------------------------*/
async renderRosesDeLaVie(stage) {
// Filter available pouponniere from origineSociale
let rosesItems = stage.items.filter(item => item.system.accessible[this.origineSociale.id].isaccessible)
let context = {
title: "Création de personnage - Les Roses de la Vie",
label: "Valider le choix des Roses de la Vie",
choices: rosesItems,
caracBonus: this.caracBonus,
competenceBonus: this.competenceBonus
}
let choiceResult = await this.askStageName(context)
if (choiceResult == null) {
this.currentStage = "cancelled"
return
}
this.roses = foundry.utils.duplicate(stage.items.find(item => item.id === choiceResult.selectedItem))
context.title = `Les Roses de la Vie - ${this.roses.name}`
TeDeumUtility.prepareEducationContent(this.roses);
context.label = "Valider l'augmentation de caracteristique"
await this.askCarac(this.roses, context)
context.label = "Valider l'augmentation de compétences"
await this.askCompetences(this.roses, context)
context.label = "Valider cette réponse"
await this.askQuestionnaire(this.roses, context)
this.currentStage = "ageviril"
}
/*--------------------------------------------*/
async renderAgeViril(stage) {
let virilDebouche = this.roses.system.debouches
let ageVirilItems = []
for (let key in virilDebouche) {
let debouche = virilDebouche[key]
if (debouche.debouche === "") { continue }
let deboucheItem = stage.items.find(item => item.name.toLowerCase().includes(debouche.debouche.toLowerCase()))
if (deboucheItem) {
ageVirilItems.push(deboucheItem)
} else {
console.log(`Debouche ${debouche.debouche} not found !`)
}
}
let context = {
title: "Création de personnage - L'Age Viril",
label: "Valider le choix de l'Age Viril",
choices: ageVirilItems,
caracBonus: this.caracBonus,
competenceBonus: this.competenceBonus
}
let choiceResult = await this.askStageName(context)
if (choiceResult == null) {
this.currentStage = "cancelled"
return
}
this.ageViril = foundry.utils.duplicate(stage.items.find(item => item.id === choiceResult.selectedItem))
context.title = `L'Age Viril - ${this.ageViril.name}`
TeDeumUtility.prepareEducationContent(this.ageViril);
context.label = "Valider l'augmentation de caracteristique"
await this.askCarac(this.ageViril, context)
context.label = "Valider l'augmentation de compétences"
await this.askCompetences(this.ageViril, context)
this.currentStage = "finished"
}
/*--------------------------------------------*/
async processStage() {
while (this.currentStage !== "finished") {
let stage = this.stages[this.currentStage]
switch (this.currentStage) {
case "origineSociale":
await this.renderOrigineSociale(stage)
break
case "pouponniere":
await this.renderPouponniere(stage)
break
case "petitsgrimauds":
await this.renderPetitsGrimauds(stage)
break
case "rosevie":
await this.renderRosesDeLaVie(stage)
break
case "ageviril":
await this.renderAgeViril(stage)
break
case "cancelled":
return
break
}
}
console.log("Carac Bonus", this.caracBonus)
console.log("Competence Bonus", this.competenceBonus)
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.genre'] = this.sexe
updates['system.religion'] = TeDeumUtility.upperFirst(this.religion)
updates['system.statutocial'] = this.origineSociale.label
updates['system.equipmentfree'] = this.ageViril.system.trousseau
actor.update( updates);
// Process competences : increase know skills
let updateComp = []
let toAdd = []
for (let compName in this.competenceBonus) {
let comp = actor.items.find( i => i.type == "competence" && i.name.toLowerCase() === compName.toLowerCase())
if (comp) {
updateComp.push({ _id: comp._id, "system.score": this.competenceBonus[compName].value })
} else {
toAdd.push( compName)
}
}
actor.updateEmbeddedDocuments("Item", updateComp)
// Process adding skills
let compendiumSkill = TeDeumUtility.getCompetences()
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
compToAdd.push(comp)
}
await actor.createEmbeddedDocuments('Item', compToAdd)
let newArgent = this.origineSociale.cagnotte * this.ageViril.system.cagnotteMultiplier
newArgent /= this.ageViril.system.cagnotteDivider
await actor.update({ [`system.fortune.${this.origineSociale.cagnotteUnit}`]: newArgent})
actor.render(true)
const content = await 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 },
classes: ["fvtt-te-deum"],
content,
buttons: [
{
label: label,
callback: (event, button, dialog) => {
const output = Array.from(button.form.elements).reduce((obj, input) => {
if (input.name) obj[input.name] = input.value
return obj
}, {})
return output
},
},
],
actions: {
},
rejectClose: false, // Click on Close button will not launch an error
render: (event, dialog) => { }
})
}
}

View File

@ -5,21 +5,17 @@ export class TeDeumCombat extends Combat {
/* -------------------------------------------- */
async rollInitiative(ids, formula = undefined, messageOptions = {} ) {
console.log("Roll INIT !")
ids = typeof ids === "string" ? [ids] : ids;
for (let cId = 0; cId < ids.length; cId++) {
const c = this.combatants.get(ids[cId]);
let id = c._id || c.id;
let initBonus = c.actor ? c.actor.getInitiativeScore( this.id, id ) : -1;
await this.updateEmbeddedDocuments("Combatant", [ { _id: id, initiative: initBonus } ]);
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 } ]);
}
return this;
}
/* -------------------------------------------- */
_onUpdate(changed, options, userId) {
}
/* -------------------------------------------- */
static async checkTurnPosition() {
while (game.combat.turn > 0) {

View File

@ -4,35 +4,35 @@ 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 }],
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, id: "pieddroit", nbArmure: 1 },
"jambedroite": { label: "Jambe Droite", value: 1, id: "jambedroite", nbArmure: 1 },
"jambegauche": { label: "Jambe Gauche", value: 1, id: "jambegauche", nbArmure: 1 },
"piedgauche": { label: "Pied Gauche", value: 1, id: "piedgauche", nbArmure: 1 },
"piedgauche": { label: "Pied Gauche", value: 1, id: "piedgauche", nbArmure: 1 },
"maindroite": { label: "Main Droite", value: 1, id: "maindroite", nbArmure: 1 },
"maingauche": { label: "Main Gauche", value: 1, id: "maingauche", nbArmure: 1 },
"brasdroit": { label: "Bras Droit", value: 1, id: "brasdroit", nbArmure: 2 },
"brasgauche": { label: "Bras Gauche", value: 1, id: "brasgauche", nbArmure: 2 },
"corps": { label: "Corps", value: 1, id: "corps", nbArmure: 2 },
"tete": { label: "Tête", value: 1, id: "tete", nbArmure: 2 },
"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 } },
},
ARME_SPECIFICITE: {
"encombrante": { label: "Encombrante", id: "encombrante", melee: true, tir: true},
"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},
"peutlancer": { label: "Peut être lancée", id: "peutlancer", melee: true, tir: false},
"pasboutportant": { label: "Inutilisable à bout portant", id: "pasboutportant", melee: false, tir: true},
"rechargearquebusade": { label: "Retrancher l'Arquebusade au temps de recharge", id: "rechargearquebusade", melee: false, tir: true },
"coupassomant": { label: "Coup assomant", id: "coupassomant", melee: true, tir: false },
"peutlancer": { label: "Peut être lancée", id: "peutlancer", melee: true, tir: false },
"pasboutportant": { label: "Inutilisable à bout portant", id: "pasboutportant", melee: false, tir: true },
"mitraille": { label: "Mitraille", id: "mitraille", melee: false, tir: true },
"degatscharge": { label: "Dégâts accrus à la charge", id: "degatscharge", melee: true, tir: false },
"crochecavalier": { label: "Croche-cavalier", id: "crochecavalier", melee: true, tir: false },
@ -43,18 +43,23 @@ export const TEDEUM_CONFIG = {
},
ARME_PORTEES: {
"brulepourpoint": { label: "Brûle-pourpoint", difficulty: "facile", id: "brulepourpoint"},
"courte": { label: "Courte", difficulty: "pardefaut", id: "courte"},
"moyenne": { label: "Moyenne", difficulty: "difficile", id: "moyenne"},
"longue": { label: "Longue", difficulty: "perilleux", id: "longue"},
"extreme": { label: "Extrême", difficulty: "desespere", id: "extreme"},
"brulepourpoint": { label: "Brûle-pourpoint", difficulty: "facile", id: "brulepourpoint" },
"courte": { label: "Courte", difficulty: "pardefaut", id: "courte" },
"moyenne": { label: "Moyenne", difficulty: "difficile", id: "moyenne" },
"longue": { label: "Longue", difficulty: "perilleux", id: "longue" },
"extreme": { label: "Extrême", difficulty: "desespere", id: "extreme" },
},
genre: {
Homme: { label: "Homme", value: "Homme" },
Femme: { label: "Femme", value: "Femme" }
},
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" },
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" },
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" },
6: { valeur: 6, qualite: "Bon", dice: "d10", negativeDice: "d8", savoir: "Lettré", sensibilite: "Fin", entregent: "Disert", puissance: "Vigoureux", complexion: "Gaillard", adresse: "Leste" },
7: { valeur: 7, qualite: "Excellent", dice: "d12", negativeDice: "d6", savoir: "Docte", sensibilite: "Subtil", entregent: "Galant", puissance: "Musculeux", complexion: "Sanguin", adresse: "Preste" },
@ -72,23 +77,28 @@ export const TEDEUM_CONFIG = {
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" },
},
diceValeur: [ "d4", "d6", "d8", "d10", "d12", "d20" ],
degatsArmure : {
sansarmure : { label: "Sans armure"},
cuir : { label: "Cuir"},
plates : { label: "Plates"},
mailles : { label: "Mailles"},
diceValeur: ["d4", "d6", "d8", "d10", "d12", "d20"],
degatsArmure: {
sansarmure: { label: "Sans armure" },
cuir: { label: "Cuir" },
plates: { label: "Plates" },
mailles: { label: "Mailles" },
},
caracteristiques: {
savoir: { id: "savoir", value: "savoir", label: "Savoir" },
sensibilite: { id: "sensibilite", value: "sensibilite", label: "Sensibilité" },
entregent: { id: "entregent", value: "entregent", label: "Entregent" },
complexion: { id: "complexion", value: "complexion", label: "Complexion" },
puissance: { id: "puissance", value: "puissance", label: "Puissance" },
adresse: { id: "adresse", value: "adresse", label: "Adresse" },
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." },
puissance: { id: "puissance", value: "puissance", label: "Puissance", description: "Cette caractéristique correspond à la force physique du personnage. Elle permet d'évaluer la compétence de base Effort, le bonus de dégâts au corps à corps, ainsi que le nombre de pièces d'armure lourde qu'un per- sonnage peut endosser sans être trop ralenti." },
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 } },
},
providence: [
{ labelM: "Brebis égarée", labelF: "Brebis égarée", value: 0, diceValue: "0" },
{ labelM: "Pauvre pêcheur", labelF: "Pauvre pêcheresse", value: 1, diceValue: "d4" },
@ -98,7 +108,11 @@ export const TEDEUM_CONFIG = {
{ labelM: "Oint du Seigneur", labelF: "Ointe du Seigneur", value: 5, diceValue: "d12" },
{ labelM: "Dans la main de Dieu", labelF: "Dans la main de Dieu", value: 6, diceValue: "d20" },
],
armureTypes: {
cuir: { label: "Cuir", value: "cuir" },
maille: { label: "Maille", value: "maille" },
plate: { label: "Plate", value: "plate" },
},
armeTypes: {
melee: { label: "Mêlée", value: "melee" },
tir: { label: "Tir", value: "tir" }
@ -107,7 +121,7 @@ export const TEDEUM_CONFIG = {
courte: { label: "Courte", value: "courte" },
moyenne: { label: "Moyenne", value: "moyenne" },
longue: { label: "Longue", value: "longue" },
treslongue: { label: "Très longue", value: "treslongue"}
treslongue: { label: "Très longue", value: "treslongue" }
},
armeCompetences: {
bagarre: { label: "Bagarre", value: "bagarre" },
@ -118,14 +132,20 @@ export const TEDEUM_CONFIG = {
archerie: { label: "Archerie", value: "archerie" },
arquebusade: { label: "Arquebusade", value: "arquebusade" }
},
competencesRecharge: {
aucune: { label: "Aucune", value: "aucune" },
archerie: { label: "Archerie", value: "archerie" },
arquebusade: { label: "Arquebusade", value: "arquebusade" }
},
difficulte: {
routine: { label: "Routine", value: 3 },
facile: { label: "Facile", value: 5 },
pardefaut: { label: "Par Défaut", value: 7 },
malaise: { label: "Malaisé", value: 9 },
difficile: { label: "difficile", value: 11 },
perilleux: { label: "Perilleux", value: 13 },
desespere: { label: "Désespéré", value: 15 }
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 }
},
monnaie: {
denier: { label: "Deniers", id: "denier", value: 1 },
@ -133,37 +153,57 @@ export const TEDEUM_CONFIG = {
livre: { label: "Livres", id: "livre", value: 100 }
},
etapesEducation: {
pouponniere: { label: "La Pouponnière", value: "pouponniere", agemin: 0, agemax: 6, nbCompetences: 2, nbCaracteristiques: 3, hasQuestionnaire: true, hasMultiplier: false },
petitsgrimauds: { label: "La classe des Petits Grimauds", value: "petitsgrimauds", agemin: 7, agemax: 12,nbCompetences: 2, nbCaracteristiques: 3, hasQuestionnaire: true, hasMultiplier: false },
rosevie: { label: "Les Roses de la Vie", value: "rosevie", agemin: 13, agemax: 16, nbCompetences: 2, nbCaracteristiques: 3, hasQuestionnaire: true, hasMultiplier: false },
ageviril: { label: "L'Age Viril", value: "ageviril", agemin: 17, agemax: 17, nbCompetences: 9, nbCaracteristiques: 2, hasQuestionnaire: false, hasMultiplier: true },
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 },
},
origineSociale: {
noblesseepee: { label: "Noblesse d'épée", id: "noblesseepee", value: 1 },
noblessecloche: { label: "Noblesse de cloche", id: "noblessecloche", value: 2 },
hautenoblesse: { label: "Haute noblesse (Illégitime)", id: "hautenoblesse", value: 3 },
hautebourgeoisie: { label: "Haute bourgeoisie", id: "hautebourgeoisie", value: 4 },
petitebourgeoisie: { label: "Petite bourgeoisie (Marchands)", id: "petitebourgeoisie", value: 5 },
artisan: { label: "Artisans", id: "artisan", value: 6 },
laboureur: { label: "Laboureurs", id: "laboureur", value: 7 },
domesticite: { label: "Domesticité", id: "domesticite", value: 8 },
paysannerie: { label: "Paysannerie", id: "paysannerie", value: 9 },
gueux: { label: "Gueux", id: "gueux", value: 10 },
noblesseepee: { label: "Noblesse d'épée", id: "noblesseepee", caracteristiques: { entregent: 1, puissance: 1 }, cagnotte: 10, cagnotteUnit: "livres", value: 1 },
noblessecloche: { label: "Noblesse de cloche", id: "noblessecloche", caracteristiques: { entregent: 1, savoir: 1 }, cagnotte: 50, cagnotteUnit: "livres", value: 2 },
hautenoblesse: { label: "Haute noblesse (Illégitime)", id: "hautenoblesse", caracteristiques: { complexion: 1, puissance: 1 }, cagnotte: 20, cagnotteUnit: "livres", value: 3 },
hautebourgeoisie: { label: "Haute bourgeoisie", id: "hautebourgeoisie", caracteristiques: { savoir: 1, sensibilite: 1 }, cagnotte: 60, cagnotteUnit: "livres", value: 4 },
petitebourgeoisie: { label: "Petite bourgeoisie (Marchands)", caracteristiques: { entregent: 1, sensibilite: 1 }, cagnotte: 20, cagnotteUnit: "livres", id: "petitebourgeoisie", value: 5 },
artisan: { label: "Artisans", id: "artisan", caracteristiques: { adresse: 1, sensibilite: 1 }, cagnotte: 10, cagnotteUnit: "livres", value: 6 },
laboureur: { label: "Laboureurs", id: "laboureur", caracteristiques: { entregent: 1, complexion: 1 }, cagnotte: 10, cagnotteUnit: "livres", value: 7 },
domesticite: { label: "Domesticité", id: "domesticite", caracteristiques: { entregent: 1, adresse: 1 }, cagnotte: 2, cagnotteUnit: "sous", value: 8 },
paysannerie: { label: "Paysannerie", id: "paysannerie", caracteristiques: { puissance: 1, complexion: 1 }, cagnotte: 1, cagnotteUnit: "sous", value: 9 },
gueux: { label: "Gueux", id: "gueux", caracteristiques: { adresse: 1, complexion: 1 }, cagnotte: 4, cagnotteUnit: "deniers", value: 10 },
},
bonusMalus: [
{ value: "-2", label: "-2 niveaux" },
{ value: "-1", label: "-1 niveau" },
{ value: "0", label: "Aucun" },
{ value: "1", label: "+1 niveau" },
{ value: "2", label: "+2 niveaux" }
],
blessures: [
{ value: 0, label: "Indemne", degatsMax: -1, count: 0, modifier: 0 },
{ value: 1, label: "Estafilade/Contusion", degatsMax: 2, count: 1, modifier: 0 },
{ value: 2, label: "Plaie", degatsMax: 4, count: 1, modifier: -1 },
{ value: 3, label: "Plaie béante", degatsMax: 6, count: 1, modifier: -2 },
{ value: 4, label: "Plaie atroce", degatsMax: 6, count: 1, horsCombat: true, modifier: -12 },
{ value: 5, label: "Tué net", degatsMax: 100, count: 1, horsCombat: true, mort: true, modifier: -12 }
]
{ value: "-2", label: "-2 niveaux" },
{ value: "-1", label: "-1 niveau" },
{ value: "0", label: "Aucun" },
{ value: "1", label: "+1 niveau" },
{ value: "2", label: "+2 niveaux" }
],
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 }
},
virulence: {
aucune: { label: "Aucune", value: "aucune", modifier: 0 },
fatigue: { label: "Fatigue", value: "fatigue", modifier: 0 },
epuisement: { label: "Epuisement", value: "epuisement", modifier: -1 },
souffrance: { label: "Souffrance", value: "souffrance", modifier: -2 },
agonie: { label: "Agonie", value: "agonie", modifier: -3 }
},
fievre: {
aucune: { label: "Aucune", value: "aucune" },
legere: { label: "Légère", value: "legere" },
forte: { label: "Forte", value: "forte" },
grave: { label: "Grave", value: "grave" }
},
virulencePoison: {
aucune: { label: "Aucune", value: "aucune", modifier: 0 },
nausee: { label: "Nausées & Vertiges", value: "nausee", modifier: 0 },
inflammation: { label: "Inflammations & Vomissements", value: "inflammation", modifier: -1 },
elancement: { label: "Elancements & Hémorragies", value: "elancement", modifier: -2 },
convulsion: { label: "Convulsions & Délire hallucinatoire", value: "convulsion", modifier: -3 },
mort: { label: "Inconscience & Mort", value: "mort", modifier: -12 }
}
}

View File

@ -5,7 +5,28 @@ export class TeDeumUtility {
/* -------------------------------------------- */
static async init() {
CONFIG.Actor.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp"
CONFIG.Item.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp"
CONFIG.Scene.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp"
CONFIG.JournalEntry.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp"
CONFIG.Macro.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp"
CONFIG.Adventure.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp"
Hooks.on('renderChatLog', (log, html, data) => TeDeumUtility.chatListeners(html));
Hooks.on("renderActorDirectory", (app, html, data) => {
if (game.user.can('ACTOR_CREATE')) {
const button = document.createElement('button');
button.style.width = '90%';
button.innerHTML = 'Créer un Personnage'
button.addEventListener('click', () => {
let cr = new game.system.tedeum.TeDeumCharacterCreator();
cr.init()
})
html.find('.header-actions').after(button)
}
})
//Hooks.on("getChatLogEntryContext", (html, options) => TeDeumUtility.chatMenuManager(html, options));
}
@ -46,20 +67,27 @@ export class TeDeumUtility {
accum += block.fn(i);
return accum;
})
Handlebars.registerHelper('getConfigLabel', function (configName, key) {
Handlebars.registerHelper('getConfigLabel', function (configName, key) {
//console.log("getConfigLabel", configName, key)
return game.system.tedeum.config[configName][key].label
})
Handlebars.registerHelper('getConfigLabelArray', function (configName, key) {
//console.log("getConfigLabel", configName, key)
return game.system.tedeum.config[configName][key].label
})
Handlebars.registerHelper('isSpecArmeType', function (key, armeType) {
return game.system.tedeum.config.ARME_SPECIFICITE[key][armeType]
})
Handlebars.registerHelper('getConfigLabelWithGender', function (configName, key, genderKey) {
return game.system.tedeum.config[configName][key]["label"+genderKey]
Handlebars.registerHelper('getConfigLabelWithGender', function (configName, key, genderKey) {
return game.system.tedeum.config[configName][key]["label" + genderKey]
})
Handlebars.registerHelper('getCaracDescription', function (key, value) {
Handlebars.registerHelper('getCaracDescription', function (key, value) {
return game.system.tedeum.config.descriptionValeur[Number(value)][key]
})
Handlebars.registerHelper('getEducationEtape', function (key) {
return game.system.tedeum.config.etapesEducation[key].label
})
Handlebars.registerHelper('isGM', function () {
return game.user.isGM
@ -70,7 +98,35 @@ export class TeDeumUtility {
this.competences = competences.map(i => i.toObject())
this.competencesList = {}
for (let i of this.competences) {
this.competencesList[i.name.toLowerCase()] = {name:i.name, id: i._id}
this.competencesList[i.name.toLowerCase()] = { name: i.name, id: i._id }
}
this.competencesList = Object.entries(this.competencesList).sort().reduce((o, [k, v]) => (o[k] = v, o), {})
}
/* -------------------------------------------- */
static async importDefaultScene() {
let exists = game.scenes.find(j => j.name == "Te Deum");
if (!exists) {
const scenes = await TeDeumUtility.loadCompendium("fvtt-te-deum.scenes")
let newDocuments = scenes.filter(i => i.name == "Te Deum");
if (newDocuments) {
await game.scenes.documentClass.create(newDocuments);
game.scenes.find(i => i.name == "Te Deum").activate();
}
}
}
/* -------------------------------------------- */
static welcomeMessage() {
if (game.user.isGM) {
ChatMessage.create({
user: game.user.id,
whisper: [game.user.id],
content: `<div id="chat-welcome welcome-message-tedeum"><span class="rdd-roll-part">
<strong>Bienvenu dans Te Deum Pour Un Massacre !</strong>
<div class="chat-welcome">Ce système vous est proposé par Open Sesame Games.<br>
Vous trouverez de l'aide dans @UUID[Compendium.fvtt-te-deum.aides.JournalEntry.uNwJgi4kXBCiZmAH]{Aide pour Te Deum}<br>
ainsi que sur le Discord de Foundry FR : https://discord.gg/pPSDNJk</div>` });
}
}
@ -85,22 +141,25 @@ export class TeDeumUtility {
/*-------------------------------------------- */
static prepareEducationContent(formData) {
let nbCompetences = game.system.tedeum.config.etapesEducation[formData.system.etape].nbCompetences
let etape = game.system.tedeum.config.etapesEducation[formData.system.etape]
let nbCompetences = etape.nbCompetences
for (let key in formData.system.competences) {
formData.system.competences[key].valid = false
}
for (let i = 1; i <= nbCompetences; i++) {
formData.system.competences[`comp${i}`].valid = true
}
let nbCaracteristiques = game.system.tedeum.config.etapesEducation[formData.system.etape].nbCaracteristiques
let nbCaracteristiques = etape.nbCaracteristiques
for (let key in formData.system.caracteristiques) {
formData.system.caracteristiques[key].valid = false
}
for (let i = 1; i <= nbCaracteristiques; i++) {
formData.system.caracteristiques[`carac${i}`].valid = true
}
formData.hasQuestionnaire = game.system.tedeum.config.etapesEducation[formData.system.etape].hasQuestionnaire;
formData.hasMultiplier = game.system.tedeum.config.etapesEducation[formData.system.etape].hasMultiplier;
formData.hasQuestionnaire = etape.hasQuestionnaire;
formData.hasMultiplier = etape.hasMultiplier;
formData.hasDebouches = etape.hasDebouches;
formData.canCompetencesOpt = etape.canCompetencesOpt;
}
/*-------------------------------------------- */
@ -133,45 +192,54 @@ export class TeDeumUtility {
return actor
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async manageOpposition(rollData) {
if (!this.currentOpposition) {
// Store rollData as current GM opposition
this.currentOpposition = rollData
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
}
this.currentOpposition = undefined // Reset opposition
let oppositionData = {
winner: rWinner,
looser: rLooser
}
let msg = await this.createChatWithRollMode(rollData.alias, {
content: await 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)
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async chatListeners(html) {
html.on("click", '.button-select-confront', event => {
html.on("click", '.chat-command-button', event => {
let messageId = TeDeumUtility.findChatMessageId(event.currentTarget)
let message = game.messages.get(messageId)
let rollData = message.getFlag("world", "te-deum-rolldata")
ui.notifications.info( game.i18n.localize("ECRY.chat.confrontselect"))
TeDeumUtility.manageConfrontation(rollData)
if (rollData) {
TeDeumUtility.manageOpposition(rollData, messageId)
}
})
html.on("click", '.button-apply-cephaly-difficulty', event => {
let messageId = TeDeumUtility.findChatMessageId(event.currentTarget)
let message = game.messages.get(messageId)
let rollData = message.getFlag("world", "te-deum-rolldata")
let difficulty = $("#" + rollData.rollId + "-cephaly-difficulty").val()
TeDeumUtility.manageCephalyDifficulty(rollData, difficulty)
})
html.on("click", '.button-apply-impact', event => {
let messageId = TeDeumUtility.findChatMessageId(event.currentTarget)
let message = game.messages.get(messageId)
let actor = game.actors.get($(event.currentTarget).data("actor-id"))
actor.modifyImpact($(event.currentTarget).data("impact-type"), $(event.currentTarget).data("impact"), 1)
})
html.on("click", '.button-apply-bonus', event => {
let messageId = TeDeumUtility.findChatMessageId(event.currentTarget)
let message = game.messages.get(messageId)
let actor = game.actors.get($(event.currentTarget).data("actor-id"))
actor.modifyConfrontBonus($(event.currentTarget).data("bonus"))
})
}
/* -------------------------------------------- */
static async preloadHandlebarsTemplates() {
const templatePaths = [
'systems/fvtt-te-deum/templates/actors/editor-notes-gm.hbs',
'systems/fvtt-te-deum/templates/items/partial-item-nav.hbs',
'systems/fvtt-te-deum/templates/items/partial-item-description.hbs'
'systems/fvtt-te-deum/templates/items/partial-item-description.hbs',
'systems/fvtt-te-deum/templates/dialogs/partial-creator-status.hbs'
]
return loadTemplates(templatePaths);
}
@ -248,7 +316,7 @@ export class TeDeumUtility {
console.log("SOCKET MESSAGE", msg)
if (msg.name == "msg_gm_chat_message") {
let rollData = msg.data.rollData
if ( game.user.isGM ) {
if (game.user.isGM) {
let chatMsg = await this.createChatMessage(rollData.alias, "blindroll", {
content: await renderTemplate(msg.data.template, rollData),
whisper: game.user.id
@ -343,7 +411,7 @@ export class TeDeumUtility {
let critiqueRoll = await new Roll(rollData.carac.negativeDice).roll()
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.score) {
rollData.isEchecCritique = true
}
}
@ -352,15 +420,27 @@ export class TeDeumUtility {
/* -------------------------------------------- */
static modifyDice(dice, bonusMalus) {
let newIndex = game.system.tedeum.config.diceValeur.indexOf(dice) + Number(bonusMalus)
if (newIndex < 0) {
ui.notifications.error("Vos blessures ou maladies vous empêchent de réaliser cette action, vous êtes trop faibles")
return undefined
}
newIndex = Math.min(Math.max(newIndex, 0), game.system.tedeum.config.diceValeur.length - 1)
return game.system.tedeum.config.diceValeur[newIndex]
}
/* -------------------------------------------- */
static computeRollFormula(rollData, actor, isConfrontation = false) {
let diceFormula = ""
if (rollData.competence) {
let diceBase = this.modifyDice(rollData.carac.dice, rollData.bonusMalus+rollData.malusBlessures)
let localModifier = 0
if (rollData.isViser) {
localModifier += 1
}
if (rollData.isMouvement) {
localModifier -= 1
}
let diceBase = this.modifyDice(rollData.carac.dice, localModifier + Number(rollData.bonusMalus) + rollData.santeModifier)
if (!diceBase) return;
diceFormula = diceBase + "x + " + rollData.competence.system.score
}
if (rollData.enableProvidence) {
@ -369,17 +449,64 @@ export class TeDeumUtility {
return diceFormula
}
/* -------------------------------------------- */
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
}
}
}
/* -------------------------------------------- */
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
}
}
/* -------------------------------------------- */
static async processAttaqueDistance(rollData) {
if (rollData.arme?.system.typeArme != "tir") {
return
}
if (rollData.isSuccess) {
// Roll the location
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"))
rollData.degatsRoll = foundry.utils.duplicate(degatsRoll)
rollData.degats = degatsRoll.total
}
}
/* -------------------------------------------- */
static async rollTeDeum(rollData) {
let actor = game.actors.get(rollData.actorId)
// Fix difficulty
if (!rollData.difficulty || rollData.difficulty == "-") {
rollData.difficulty = 7
rollData.difficulty = "pardefaut"
}
rollData.difficulty = game.system.tedeum.config.difficulte[rollData.difficulty].value
let diceFormula = this.computeRollFormula(rollData, actor)
if (!diceFormula) return;
console.log("RollData", rollData, diceFormula)
// Performs roll
let myRoll = await new Roll(diceFormula).roll()
@ -391,6 +518,9 @@ export class TeDeumUtility {
await this.computeResults(rollData)
await this.processAttaqueDistance(rollData)
await this.processAttaqueMelee(rollData)
let msg = await this.createChatWithRollMode(rollData.alias, {
content: await renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-generic-result.hbs`, rollData)
})
@ -405,6 +535,15 @@ export class TeDeumUtility {
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)
}
}
}
/* -------------------------------------------- */
@ -471,7 +610,7 @@ export class TeDeumUtility {
}
return array;
}
/* -------------------------------------------- */
static async createChatMessage(name, rollMode, chatOptions) {
switch (rollMode) {
@ -493,15 +632,15 @@ export class TeDeumUtility {
/* -------------------------------------------- */
static getBasicRollData() {
let rollData = {
rollId: randomID(16),
rollId: foundry.utils.randomID(16),
type: "roll-data",
rollMode: game.settings.get("core", "rollMode"),
difficulty: "pardefaut",
bonusMalus : "0",
isReroll : false,
enableProvidence : false,
bonusMalus: "0",
isReroll: false,
enableProvidence: false,
malusBlessures: 0,
config: duplicate(game.system.tedeum.config)
config: foundry.utils.duplicate(game.system.tedeum.config)
}
TeDeumUtility.updateWithTarget(rollData)
return rollData

View File

@ -34,11 +34,14 @@ export class TeDeumArmeSchema extends foundry.abstract.TypeDataModel {
});
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.valeurEchecCritique = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 });
schema.initiativeBonus = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 });
schema.degats = new fields.StringField({ required: false, blank: true, initial: undefined });
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);
@ -48,7 +51,9 @@ export class TeDeumArmeSchema extends foundry.abstract.TypeDataModel {
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 });
return schema;

View File

@ -6,6 +6,8 @@ export class TeDeumArmureSchema extends foundry.abstract.TypeDataModel {
const schema = {};
schema.typeArmure = new fields.StringField({required: true, choices: ["cuir", "maille", "plate"], initial: "cuir"});
schema.localisation = new fields.SchemaField(
Object.values(game.system.tedeum.config.LOCALISATION).reduce((obj, loc) => {
obj[loc.id] = new fields.SchemaField({
@ -15,10 +17,18 @@ export class TeDeumArmureSchema extends foundry.abstract.TypeDataModel {
}, {})
);
schema.coutArmureLourde = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 });
schema.superposableCuir = new fields.BooleanField({initial: false});
schema.superposableMaille = new fields.BooleanField({initial: false});
schema.superposablePlate = new fields.BooleanField({initial: false});
schema.protection = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 });
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 });

View File

@ -0,0 +1,14 @@
export class TeDeumBlessureSchema extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
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.description = new fields.HTMLField({ required: true, blank: true });
return schema;
}
}

View File

@ -14,35 +14,66 @@ export class TeDeumEducationSchema extends foundry.abstract.TypeDataModel {
return obj;
}, {})
);
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({
caracId: new fields.StringField({ required: true, blank: false, initial: "entregent" })
});
return caracs;
}, {}));
schema.competences = new fields.SchemaField(Array.fromRange(9, 1).reduce((comps, i) => {
schema.competences = new fields.SchemaField(Array.fromRange(10, 1).reduce((comps, i) => {
comps[`comp${i}`] = new fields.SchemaField({
compName: new fields.StringField({ required: true, blank: true, initial: "" }),
toSelect: new fields.BooleanField({ initial: false })
});
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) => {
comps[`comp${i}`] = new fields.SchemaField({
compName: new fields.StringField({ required: true, blank: true, initial: "" })
});
return comps;
}, {}));
schema.questionnaire = new fields.SchemaField(Array.fromRange(4, 1).reduce((questions, i) => {
schema.questionnaire = new fields.SchemaField(Array.fromRange(8, 1).reduce((questions, i) => {
questions[`question${i}`] = new fields.SchemaField({
question: new fields.StringField({ required: true, blank: true, initial: "" }),
reponses: new fields.SchemaField( Array.fromRange(6, 1).reduce((resp, i) => {
resp[`reponse${i}`] = new fields.SchemaField({
num: new fields.NumberField({ ...requiredInteger, initial: i, min:i }),
reponse: new fields.StringField({ required: true, blank: true, initial: "" }),
compName: 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) => {
comps[`comp${i}`] = new fields.SchemaField({
compName: new fields.StringField({ required: true, blank: true, initial: "" }),
});
return comps;
}, {}))
});
return resp;
}, {}))
});
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: "" })
})
return debouches;
}, {}));
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: "" });
return schema;
}

View File

@ -0,0 +1,18 @@
export class TeDeumMaladieSchema extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
const requiredInteger = { required: true, nullable: false, integer: true };
const schema = {};
schema.transmission = new fields.HTMLField({ required: true, blank: true });
schema.difficulteEndurance = new fields.StringField({required:true, initial:"routine"});
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.description = new fields.HTMLField({ required: true, blank: true });
return schema;
}
}

View File

@ -23,7 +23,9 @@ export class TeDeumPJSchema extends foundry.abstract.TypeDataModel {
schema.localisation = new fields.SchemaField(
Object.values(game.system.tedeum.config.LOCALISATION).reduce((obj, loc) => {
obj[loc.id] =new fields.SchemaField({
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 })
});
return obj;
@ -31,7 +33,7 @@ export class TeDeumPJSchema extends foundry.abstract.TypeDataModel {
);
schema.fortune = new fields.SchemaField({
"ecu": 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 })
@ -40,13 +42,16 @@ export class TeDeumPJSchema extends foundry.abstract.TypeDataModel {
schema.description = new fields.HTMLField({required: true, blank: true});
schema.connaissances = new fields.HTMLField({required: true, blank: true});
schema.vetements = new fields.HTMLField({required: true, blank: true});
//schema.descriptiongraces = new fields.HTMLField({required: true, blank: true});
schema.genre = new fields.StringField({required: true, choices: ["Homme", "Femme"], initial: "Femme"});
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 });
return schema;
}
}

View File

@ -0,0 +1,20 @@
export class TeDeumMaladieSchema extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
const requiredInteger = { required: true, nullable: false, integer: true };
const schema = {};
schema.difficulteEndurance = new fields.StringField({required:true, initial:"aucun"});
schema.virulence = new fields.StringField({required: true, choices: ["nausee", "inflammation", "elancement", "convulsion", "mort"], initial: "aucune"});
schema.vertus = new fields.HTMLField({ required: true, blank: true });
schema.toxicite = new fields.HTMLField({ required: true, blank: true });
schema.appliquee = new fields.BooleanField({initial: false}),
schema.prix = new fields.NumberField({ ...requiredDouble, initial: 0, min: 0 });
schema.monnaie = new fields.StringField({ required: true, blank: false, initial: "denier" });
schema.description = new fields.HTMLField({ required: true, blank: true });
return schema;
}
}

View File

@ -69,6 +69,18 @@ export class TeDeumRollDialog extends Dialog {
html.find('#roll-enable-providence').change((event) => {
this.rollData.enableProvidence = event.currentTarget.checked
})
html.find('#roll-portee-tir').change((event) => {
this.rollData.porteeTir = event.currentTarget.value
this.rollData.difficulty = game.system.tedeum.config.ARME_PORTEES[this.rollData.porteeTir].difficulty
this.rollData.porteeLabel = game.system.tedeum.config.ARME_PORTEES[this.rollData.porteeTir].label
})
html.find('#roll-tir-viser').change((event) => {
this.rollData.isViser = event.currentTarget.checked
})
html.find('#roll-tir-mouvement').change((event) => {
this.rollData.isMouvement = event.currentTarget.checked
})
}

View File

@ -8,7 +8,7 @@ export class TeDeumItemSheet extends ItemSheet {
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["fvtt-te-deum", "sheet", "item"],
template: "systems/fvtt-te-deum/templates/item-sheet.hbs",
dragDrop: [{ dragSelector: null, dropSelector: null }],
@ -43,8 +43,8 @@ export class TeDeumItemSheet extends ItemSheet {
name: this.object.name,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
system: duplicate(this.object.system),
config: duplicate(game.system.tedeum.config),
system: foundry.utils.duplicate(this.object.system),
config: foundry.utils.duplicate(game.system.tedeum.config),
competences: TeDeumUtility.getCompetencesForDropDown(),
limited: this.object.limited,
options: this.options,

View File

@ -7,6 +7,9 @@ export const defaultItemImg = {
competence: "systems/fvtt-te-deum/images/icons/competence.webp",
education: "systems/fvtt-te-deum/images/icons/education.webp",
grace: "systems/fvtt-te-deum/images/icons/grace.webp",
blessure: "systems/fvtt-te-deum/images/icons/blessure.webp",
maladie: "systems/fvtt-te-deum/images/icons/maladie.webp",
simple: "systems/fvtt-te-deum/images/icons/simple.webp",
}
/**

View File

@ -19,12 +19,15 @@ import { TeDeumEquipementSchema } from "./data/tedeum-schema-equipement.js";
import { TeDeumOrigineSchema } from "./data/tedeum-schema-origine.js";
import { TeDeumEducationSchema } from "./data/tedeum-schema-education.js";
import { TeDeumGraceSchema } from "./data/tedeum-schema-grace.js";
import { TeDeumBlessureSchema } from "./data/tedeum-schema-blessure.js";
import { TeDeumMaladieSchema } from "./data/tedeum-schema-maladie.js";
import { TeDeumItem } from "./items/tedeum-item.js";
import { TeDeumItemSheet } from "./items/tedeum-item-sheet.js";
import { TeDeumHotbar } from "./app/tedeum-hotbar.js"
import { TeDeumCombat } from "./app/tedeum-combat.js";
import { TeDeumCharacterCreator } from "./app/tedeum-character-creator.js"
import { TeDeumUtility } from "./common/tedeum-utility.js";
import { TEDEUM_CONFIG } from "./common/tedeum-config.js";
@ -40,6 +43,7 @@ Hooks.once("init", async function () {
game.system.tedeum = {
config: TEDEUM_CONFIG,
TeDeumCharacterCreator,
TeDeumHotbar
}
console.log(`Initializing TeDeum RPG 2`);
@ -57,7 +61,7 @@ Hooks.once("init", async function () {
TeDeumUtility.onSocketMesssage(data)
});
//CONFIG.Combat.documentClass = TeDeumCombat
CONFIG.Combat.documentClass = TeDeumCombat
CONFIG.Actor.documentClass = TeDeumActor;
CONFIG.Item.documentClass = TeDeumItem
CONFIG.Actor.dataModels = {
@ -71,7 +75,9 @@ Hooks.once("init", async function () {
armure: TeDeumArmureSchema,
origine: TeDeumOrigineSchema,
education: TeDeumEducationSchema,
grace: TeDeumGraceSchema
grace: TeDeumGraceSchema,
blessure: TeDeumBlessureSchema,
maladie: TeDeumMaladieSchema,
};
console.log("TeDeum RPG | Ready");
@ -86,16 +92,6 @@ Hooks.once("init", async function () {
TeDeumUtility.init()
});
/* -------------------------------------------- */
function welcomeMessage() {
if (game.user.isGM) {
ChatMessage.create({
user: game.user.id,
whisper: [game.user.id],
content: `<div id="welcome-message-tedeum"><span class="rdd-roll-part">
<strong>Bienvenu dans Te Deum Pour Un Massacre !</strong>` });
}
}
/* -------------------------------------------- */
/* Foundry VTT Initialization */
@ -119,7 +115,8 @@ Hooks.once("ready", function () {
)
TeDeumUtility.ready();
welcomeMessage();
TeDeumUtility.importDefaultScene()
TeDeumUtility.welcomeMessage();
})

BIN
packs/aides/000005.ldb Normal file

Binary file not shown.

1
packs/aides/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000006

8
packs/aides/LOG Normal file
View File

@ -0,0 +1,8 @@
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)

5
packs/aides/LOG.old Normal file
View File

@ -0,0 +1,5 @@
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)

BIN
packs/aides/MANIFEST-000006 Normal file

Binary file not shown.

BIN
packs/armes/000080.ldb Normal file

Binary file not shown.

1
packs/armes/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000109

0
packs/armes/LOCK Normal file
View File

7
packs/armes/LOG Normal file
View File

@ -0,0 +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)

7
packs/armes/LOG.old Normal file
View File

@ -0,0 +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)

BIN
packs/armes/MANIFEST-000109 Normal file

Binary file not shown.

BIN
packs/armures/000080.ldb Normal file

Binary file not shown.

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

1
packs/armures/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000109

0
packs/armures/LOCK Normal file
View File

7
packs/armures/LOG Normal file
View File

@ -0,0 +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)

7
packs/armures/LOG.old Normal file
View File

@ -0,0 +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)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

View File

@ -1 +1 @@
MANIFEST-000097
MANIFEST-000106

View File

@ -1,8 +1,7 @@
2024/06/04-21:04:01.195163 7f1e64e006c0 Recovering log #94
2024/06/04-21:04:01.205547 7f1e64e006c0 Delete type=3 #92
2024/06/04-21:04:01.205638 7f1e64e006c0 Delete type=0 #94
2024/06/04-21:04:48.464146 7f1e5da006c0 Level-0 table #100: started
2024/06/04-21:04:48.464176 7f1e5da006c0 Level-0 table #100: 0 bytes OK
2024/06/04-21:04:48.500422 7f1e5da006c0 Delete type=0 #98
2024/06/04-21:04:48.500602 7f1e5da006c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!zwC0H39ar5Pl1l92' @ 0 : 0; will stop at (end)
2024/06/04-21:04:48.500619 7f1e5da006c0 Manual compaction at level-1 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!zwC0H39ar5Pl1l92' @ 0 : 0; will stop at (end)
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)

View File

@ -1,15 +1,7 @@
2024/06/02-20:22:04.658032 7f2f302006c0 Recovering log #90
2024/06/02-20:22:04.712047 7f2f302006c0 Delete type=3 #88
2024/06/02-20:22:04.712099 7f2f302006c0 Delete type=0 #90
2024/06/02-20:58:31.396230 7f2f2ee006c0 Level-0 table #95: started
2024/06/02-20:58:31.399756 7f2f2ee006c0 Level-0 table #95: 28482 bytes OK
2024/06/02-20:58:31.406774 7f2f2ee006c0 Delete type=0 #93
2024/06/02-20:58:31.406940 7f2f2ee006c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!zwC0H39ar5Pl1l92' @ 0 : 0; will stop at (end)
2024/06/02-20:58:31.406967 7f2f2ee006c0 Manual compaction at level-1 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!zwC0H39ar5Pl1l92' @ 0 : 0; will stop at '!items!zwC0H39ar5Pl1l92' @ 390 : 1
2024/06/02-20:58:31.406972 7f2f2ee006c0 Compacting 1@1 + 1@2 files
2024/06/02-20:58:31.410472 7f2f2ee006c0 Generated table #96@1: 113 keys, 15164 bytes
2024/06/02-20:58:31.410495 7f2f2ee006c0 Compacted 1@1 + 1@2 files => 15164 bytes
2024/06/02-20:58:31.416350 7f2f2ee006c0 compacted to: files[ 0 0 1 0 0 0 0 ]
2024/06/02-20:58:31.416439 7f2f2ee006c0 Delete type=2 #5
2024/06/02-20:58:31.416583 7f2f2ee006c0 Delete type=2 #95
2024/06/02-20:58:31.416682 7f2f2ee006c0 Manual compaction at level-1 from '!items!zwC0H39ar5Pl1l92' @ 390 : 1 .. '!items!zwC0H39ar5Pl1l92' @ 0 : 0; will stop at (end)
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)

Binary file not shown.

Binary file not shown.

BIN
packs/education/000055.ldb Normal file

Binary file not shown.

View File

1
packs/education/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000114

0
packs/education/LOCK Normal file
View File

7
packs/education/LOG Normal file
View File

@ -0,0 +1,7 @@
2025/02/13-22:35:49.263823 7fcc33fff6c0 Recovering log #112
2025/02/13-22:35:49.318056 7fcc33fff6c0 Delete type=3 #110
2025/02/13-22:35:49.318131 7fcc33fff6c0 Delete type=0 #112
2025/02/13-22:42:05.122931 7fcc327fc6c0 Level-0 table #117: started
2025/02/13-22:42:05.122950 7fcc327fc6c0 Level-0 table #117: 0 bytes OK
2025/02/13-22:42:05.128697 7fcc327fc6c0 Delete type=0 #115
2025/02/13-22:42:05.142187 7fcc327fc6c0 Manual compaction at level-0 from '!folders!9PQi3Lv54rpcxavo' @ 72057594037927935 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at (end)

7
packs/education/LOG.old Normal file
View File

@ -0,0 +1,7 @@
2025/02/05-20:07:00.631061 7ffae77fe6c0 Recovering log #108
2025/02/05-20:07:00.640688 7ffae77fe6c0 Delete type=3 #106
2025/02/05-20:07:00.640754 7ffae77fe6c0 Delete type=0 #108
2025/02/05-20:50:19.869892 7ffae6bff6c0 Level-0 table #113: started
2025/02/05-20:50:19.869921 7ffae6bff6c0 Level-0 table #113: 0 bytes OK
2025/02/05-20:50:19.876430 7ffae6bff6c0 Delete type=0 #111
2025/02/05-20:50:19.888577 7ffae6bff6c0 Manual compaction at level-0 from '!folders!9PQi3Lv54rpcxavo' @ 72057594037927935 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at (end)

Binary file not shown.

View File

@ -1 +0,0 @@
MANIFEST-000158

View File

@ -1,7 +0,0 @@
2024/06/04-21:04:01.182320 7f1e5f4006c0 Recovering log #156
2024/06/04-21:04:01.193373 7f1e5f4006c0 Delete type=3 #154
2024/06/04-21:04:01.193473 7f1e5f4006c0 Delete type=0 #156
2024/06/04-21:04:48.422044 7f1e5da006c0 Level-0 table #161: started
2024/06/04-21:04:48.422074 7f1e5da006c0 Level-0 table #161: 0 bytes OK
2024/06/04-21:04:48.463998 7f1e5da006c0 Delete type=0 #159
2024/06/04-21:04:48.500588 7f1e5da006c0 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)

View File

@ -1,7 +0,0 @@
2024/06/02-20:22:04.602737 7f2f2f8006c0 Recovering log #152
2024/06/02-20:22:04.655957 7f2f2f8006c0 Delete type=3 #150
2024/06/02-20:22:04.656073 7f2f2f8006c0 Delete type=0 #152
2024/06/02-20:58:31.369733 7f2f2ee006c0 Level-0 table #157: started
2024/06/02-20:58:31.369760 7f2f2ee006c0 Level-0 table #157: 0 bytes OK
2024/06/02-20:58:31.376040 7f2f2ee006c0 Delete type=0 #155
2024/06/02-20:58:31.376155 7f2f2ee006c0 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)

Binary file not shown.

BIN
packs/graces/000009.ldb Normal file

Binary file not shown.

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

1
packs/graces/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000108

0
packs/graces/LOCK Normal file
View File

7
packs/graces/LOG Normal file
View File

@ -0,0 +1,7 @@
2025/02/13-22:35:49.333807 7fcc38ffa6c0 Recovering log #106
2025/02/13-22:35:49.390442 7fcc38ffa6c0 Delete type=3 #104
2025/02/13-22:35:49.390520 7fcc38ffa6c0 Delete type=0 #106
2025/02/13-22:42:05.142328 7fcc327fc6c0 Level-0 table #111: started
2025/02/13-22:42:05.142350 7fcc327fc6c0 Level-0 table #111: 0 bytes OK
2025/02/13-22:42:05.149259 7fcc327fc6c0 Delete type=0 #109
2025/02/13-22:42:05.168150 7fcc327fc6c0 Manual compaction at level-0 from '!items!17mjvwS8R3B6LloG' @ 72057594037927935 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at (end)

7
packs/graces/LOG.old Normal file
View File

@ -0,0 +1,7 @@
2025/02/05-20:07:00.649375 7ffaed3fa6c0 Recovering log #102
2025/02/05-20:07:00.660182 7ffaed3fa6c0 Delete type=3 #100
2025/02/05-20:07:00.660251 7ffaed3fa6c0 Delete type=0 #102
2025/02/05-20:50:19.851179 7ffae6bff6c0 Level-0 table #107: started
2025/02/05-20:50:19.851201 7ffae6bff6c0 Level-0 table #107: 0 bytes OK
2025/02/05-20:50:19.857001 7ffae6bff6c0 Delete type=0 #105
2025/02/05-20:50:19.863196 7ffae6bff6c0 Manual compaction at level-0 from '!items!17mjvwS8R3B6LloG' @ 72057594037927935 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at (end)

Binary file not shown.

BIN
packs/maladies/000009.ldb Normal file

Binary file not shown.

View File

1
packs/maladies/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000108

0
packs/maladies/LOCK Normal file
View File

7
packs/maladies/LOG Normal file
View File

@ -0,0 +1,7 @@
2025/02/13-22:35:49.396011 7fcc337fe6c0 Recovering log #106
2025/02/13-22:35:49.449719 7fcc337fe6c0 Delete type=3 #104
2025/02/13-22:35:49.449798 7fcc337fe6c0 Delete type=0 #106
2025/02/13-22:42:05.155275 7fcc327fc6c0 Level-0 table #111: started
2025/02/13-22:42:05.155292 7fcc327fc6c0 Level-0 table #111: 0 bytes OK
2025/02/13-22:42:05.161323 7fcc327fc6c0 Delete type=0 #109
2025/02/13-22:42:05.168175 7fcc327fc6c0 Manual compaction at level-0 from '!items!1icaxIywAwDXQcMz' @ 72057594037927935 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at (end)

7
packs/maladies/LOG.old Normal file
View File

@ -0,0 +1,7 @@
2025/02/05-20:07:00.663190 7ffae7fff6c0 Recovering log #102
2025/02/05-20:07:00.673484 7ffae7fff6c0 Delete type=3 #100
2025/02/05-20:07:00.673553 7ffae7fff6c0 Delete type=0 #102
2025/02/05-20:50:19.863283 7ffae6bff6c0 Level-0 table #107: started
2025/02/05-20:50:19.863350 7ffae6bff6c0 Level-0 table #107: 0 bytes OK
2025/02/05-20:50:19.869776 7ffae6bff6c0 Delete type=0 #105
2025/02/05-20:50:19.888563 7ffae6bff6c0 Manual compaction at level-0 from '!items!1icaxIywAwDXQcMz' @ 72057594037927935 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at (end)

Binary file not shown.

BIN
packs/scenes/000005.ldb Normal file

Binary file not shown.

BIN
packs/scenes/000009.ldb Normal file

Binary file not shown.

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

1
packs/scenes/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000046

0
packs/scenes/LOCK Normal file
View File

7
packs/scenes/LOG Normal file
View File

@ -0,0 +1,7 @@
2025/02/13-22:35:49.519066 7fcc33fff6c0 Recovering log #44
2025/02/13-22:35:49.574033 7fcc33fff6c0 Delete type=3 #42
2025/02/13-22:35:49.574112 7fcc33fff6c0 Delete type=0 #44
2025/02/13-22:42:05.168348 7fcc327fc6c0 Level-0 table #49: started
2025/02/13-22:42:05.168374 7fcc327fc6c0 Level-0 table #49: 0 bytes OK
2025/02/13-22:42:05.174222 7fcc327fc6c0 Delete type=0 #47
2025/02/13-22:42:05.199806 7fcc327fc6c0 Manual compaction at level-0 from '!scenes!FJXugdbkBpEJEdR6' @ 72057594037927935 : 1 .. '!scenes!FJXugdbkBpEJEdR6' @ 0 : 0; will stop at (end)

7
packs/scenes/LOG.old Normal file
View File

@ -0,0 +1,7 @@
2025/02/05-20:07:00.692354 7ffae77fe6c0 Recovering log #40
2025/02/05-20:07:00.702369 7ffae77fe6c0 Delete type=3 #38
2025/02/05-20:07:00.702455 7ffae77fe6c0 Delete type=0 #40
2025/02/05-20:50:19.882562 7ffae6bff6c0 Level-0 table #45: started
2025/02/05-20:50:19.882585 7ffae6bff6c0 Level-0 table #45: 0 bytes OK
2025/02/05-20:50:19.888444 7ffae6bff6c0 Delete type=0 #43
2025/02/05-20:50:19.888601 7ffae6bff6c0 Manual compaction at level-0 from '!scenes!FJXugdbkBpEJEdR6' @ 72057594037927935 : 1 .. '!scenes!FJXugdbkBpEJEdR6' @ 0 : 0; will stop at (end)

Binary file not shown.

BIN
packs/simples/000009.ldb Normal file

Binary file not shown.

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

1
packs/simples/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000108

0
packs/simples/LOCK Normal file
View File

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