Compare commits
65 Commits
fvtt-te-de
...
13.0.6
Author | SHA1 | Date | |
---|---|---|---|
e794611bf3 | |||
529a62045e | |||
d462d22a0a | |||
710ee54531 | |||
7994aa7db4 | |||
5176b4ce87 | |||
3d6f195fc2 | |||
3693d68c24 | |||
16ccd2f3e1 | |||
631eb280ca | |||
88ca98945f | |||
edfb2105d3 | |||
84cc59c57d | |||
e9c0fbd818 | |||
aaabb7ed75 | |||
fee7a3a9fb | |||
31517030f6 | |||
c5cbf2a6d1 | |||
a30f813d94 | |||
090f6be601 | |||
60db1f65e4 | |||
d532765d2b | |||
b6016742ae | |||
761f95d6d9 | |||
c24f4fe502 | |||
caedcf5e21 | |||
fe0814e498 | |||
544f9f467a | |||
ce5771f930 | |||
93b8325bb9 | |||
48be65e7fd | |||
a37ce76ab8 | |||
bbc046bc66 | |||
fd0864cea6 | |||
bf7a9f9ea5 | |||
86dfa54314 | |||
891a6647b7 | |||
5d9a218e04 | |||
a0733dc049 | |||
c32be6b24d | |||
6f278ab8eb | |||
b2ab6ffaa7 | |||
94d26e971e | |||
7eed052645 | |||
00c1d02b6b | |||
92396da997 | |||
a72e671f75 | |||
6331ab9736 | |||
4a346a4386 | |||
b8de37f388 | |||
4fd537c9ea | |||
3a2dc7be63 | |||
ff1252dcf5 | |||
7a768c5426 | |||
9b2016d069 | |||
5d843af069 | |||
b3655d011e | |||
0d7c4323b5 | |||
029ad04e26 | |||
9c93134d1c | |||
37d8957448 | |||
629d369693 | |||
10b7fcac09 | |||
de195aff1e | |||
82e7a170c2 |
52
.gitea/workflows/release.yaml
Normal 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/${{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}}'
|
@@ -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:
|
||||
|
||||
|
29
README.md
@@ -1,37 +1,26 @@
|
||||
# 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
|
||||
|
||||

|
||||
# Système Foundry pour Te Deum pour un Massacre (French RPG, Open Sesame Games, Official)
|
||||
|
||||
This is a base game system with functionnal character sheets for the game Te Deum pour un massacre.
|
||||
|
||||
# Contributions
|
||||
|
||||
- Original code realised by Uberwald (https://www.uberwald.me/)
|
||||
|
||||
Snapshot of the system :
|
||||
|
||||

|
||||
|
||||
|
||||
# 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.
|
||||
|
||||
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
|
||||
|
||||
|
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 171 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 107 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 29 KiB |
BIN
assets/scenes/FJXugdbkBpEJEdR6-thumb.webp
Normal file
After Width: | Height: | Size: 8.1 KiB |
29
changelog.md
@@ -0,0 +1,29 @@
|
||||
# 13.0.0
|
||||
|
||||
- Support de Foundry v13
|
||||
|
||||
# 12.0.23
|
||||
|
||||
- Correction sur les jets réussie en tir
|
||||
- Correction sur le dés négatif pour les échecs critiques
|
||||
- Correction sur l'XP et édition de l'XP en mode MJ
|
||||
|
||||
# 12.0.22
|
||||
|
||||
- Correction pour les armes d'hast
|
||||
- Correction sur la zone libre d'équipement
|
||||
- Bouton + pour créer un équipement à nouveau opérationnel
|
||||
- Modification de la gestion des jets en combat, avec gestion opposition ou degats immédiats
|
||||
- Gestion du genre dans la création de personnage
|
||||
|
||||
# 12.0.21
|
||||
|
||||
- Creation de PNJ OK
|
||||
|
||||
# 12.0.20
|
||||
|
||||
- Corrections sur la création de perso
|
||||
|
||||
# 12.0.19
|
||||
|
||||
- Initial release !
|
BIN
images/icons/appliquer-degats.webp
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
images/icons/blessure.webp
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
images/icons/maladie.webp
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
images/icons/opposition.webp
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
images/icons/simple.webp
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
images/icons/xpplus1.webp
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
images/ui/compendium_banner.webp
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
images/ui/femme_gauche.webp
Normal file
After Width: | Height: | Size: 160 KiB |
BIN
images/ui/homme_droit.webp
Normal file
After Width: | Height: | Size: 288 KiB |
BIN
images/ui/logo_tedeum_pause.webp
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
images/ui/tdeum_welcome_page_01.webp
Normal file
After Width: | Height: | Size: 720 KiB |
179
lang/fr.json
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,16 +6,16 @@
|
||||
import { TeDeumUtility } from "../common/tedeum-utility.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class TeDeumActorPJSheet extends ActorSheet {
|
||||
export class TeDeumActorPJSheet extends foundry.appv1.sheets.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,
|
||||
height:680,
|
||||
height: 680,
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "skills" }],
|
||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
|
||||
editScore: true
|
||||
@@ -33,18 +33,33 @@ 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(),
|
||||
simples: this.actor.getSimples(),
|
||||
armures: this.actor.getArmures(),
|
||||
graces: this.actor.getGraces(),
|
||||
description: await TextEditor.enrichHTML(this.object.system.description, { async: true }),
|
||||
notes: await TextEditor.enrichHTML(this.object.system.notes, { async: true }),
|
||||
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 foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.description, { async: true }),
|
||||
equipmentfree: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.equipmentfree, { async: true }),
|
||||
notes: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.notes, { async: true }),
|
||||
histoire: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.histoire, { async: true }),
|
||||
options: this.options,
|
||||
owner: this.document.isOwner,
|
||||
editScore: this.options.editScore,
|
||||
@@ -52,7 +67,6 @@ export class TeDeumActorPJSheet extends ActorSheet {
|
||||
}
|
||||
this.formData = formData;
|
||||
|
||||
console.log("PC : ", formData, this.object);
|
||||
return formData;
|
||||
}
|
||||
|
||||
@@ -64,16 +78,16 @@ export class TeDeumActorPJSheet extends ActorSheet {
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
html.bind("keydown", function(e) { // Ignore Enter in actores sheet
|
||||
|
||||
html.bind("keydown", function (e) { // Ignore Enter in actores sheet
|
||||
if (e.keyCode === 13) return false;
|
||||
});
|
||||
});
|
||||
|
||||
// Update Inventory Item
|
||||
html.find('.item-edit').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item-id")
|
||||
let itemId = li.data("item-id")
|
||||
const item = this.actor.items.get( itemId );
|
||||
const item = this.actor.items.get(itemId);
|
||||
item.sheet.render(true);
|
||||
});
|
||||
// Delete Inventory Item
|
||||
@@ -83,16 +97,25 @@ export class TeDeumActorPJSheet extends ActorSheet {
|
||||
})
|
||||
html.find('.item-add').click(ev => {
|
||||
let dataType = $(ev.currentTarget).data("type")
|
||||
this.actor.createEmbeddedDocuments('Item', [{ name: "NewItem", type: dataType }], { renderSheet: true })
|
||||
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouveau " + dataType, type: dataType }], { renderSheet: true })
|
||||
})
|
||||
|
||||
html.find('.blessure-add').click(ev => {
|
||||
let dataType = $(ev.currentTarget).data("type")
|
||||
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvelle " + dataType, type: dataType, system: { typeBlessure: "estafilade", localisation: "corps", value: 0, appliquee: true, description: "" } }], { renderSheet: true })
|
||||
})
|
||||
html.find('.competence-add').click(ev => {
|
||||
let dataType = $(ev.currentTarget).data("type")
|
||||
let caracKey = $(ev.currentTarget).data("carac-key")
|
||||
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvelle " + dataType, type: dataType, system: { caracteristique: caracKey } }], { renderSheet: true })
|
||||
})
|
||||
|
||||
html.find('.subactor-edit').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
let actorId = li.data("actor-id");
|
||||
let actor = game.actors.get( actorId );
|
||||
let actor = game.actors.get(actorId);
|
||||
actor.sheet.render(true);
|
||||
});
|
||||
|
||||
|
||||
html.find('.subactor-delete').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
let actorId = li.data("actor-id");
|
||||
@@ -100,38 +123,43 @@ export class TeDeumActorPJSheet extends ActorSheet {
|
||||
});
|
||||
html.find('.quantity-minus').click(event => {
|
||||
const li = $(event.currentTarget).parents(".item");
|
||||
this.actor.incDecQuantity( li.data("item-id"), -1 );
|
||||
} );
|
||||
this.actor.incDecQuantity(li.data("item-id"), -1);
|
||||
});
|
||||
html.find('.quantity-plus').click(event => {
|
||||
const li = $(event.currentTarget).parents(".item");
|
||||
this.actor.incDecQuantity( li.data("item-id"), +1 );
|
||||
} );
|
||||
this.actor.incDecQuantity(li.data("item-id"), +1);
|
||||
});
|
||||
|
||||
html.find('.roll-competence').click((event) => {
|
||||
let compId = $(event.currentTarget).data("comp-id")
|
||||
this.actor.rollCompetence(compId)
|
||||
});
|
||||
});
|
||||
html.find('.roll-arme').click((event) => {
|
||||
const armeId = $(event.currentTarget).data("arme-id")
|
||||
this.actor.rollArme(armeId)
|
||||
});
|
||||
|
||||
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;
|
||||
this.render(true);
|
||||
});
|
||||
});
|
||||
html.find('.item-equip').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
this.actor.equipItem( li.data("item-id") );
|
||||
this.render(true);
|
||||
this.actor.equipItem(li.data("item-id"));
|
||||
this.render(true);
|
||||
});
|
||||
html.find('.update-field').change(ev => {
|
||||
const fieldName = $(ev.currentTarget).data("field-name");
|
||||
let value = Number(ev.currentTarget.value);
|
||||
this.actor.update( { [`${fieldName}`]: value } );
|
||||
});
|
||||
this.actor.update({ [`${fieldName}`]: value });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
setPosition(options = {}) {
|
||||
|
@@ -14,8 +14,8 @@ export class TeDeumActor extends Actor {
|
||||
/**
|
||||
* Override the create() function to provide additional SoS functionality.
|
||||
*
|
||||
* This overrided create() function adds initial items
|
||||
* Namely: Basic skills, money,
|
||||
* This overrided create() function adds initial items
|
||||
* Namely: Basic skills, money,
|
||||
*
|
||||
* @param {Object} data Barebones actor data which this function adds onto.
|
||||
* @param {Object} options (Unused) Additional options which customize the creation workflow.
|
||||
@@ -34,12 +34,24 @@ export class TeDeumActor extends Actor {
|
||||
return actor;
|
||||
}
|
||||
|
||||
if (data.type == 'pj' || data.type == 'pnj') {
|
||||
const skills = await TeDeumUtility.loadCompendium("fvtt-te-deum.competences")
|
||||
data.items = data.items || []
|
||||
for (let skill of skills) {
|
||||
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,95 @@ export class TeDeumActor extends Actor {
|
||||
super._preUpdate(changed, options, user);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getCompetenceScore(compName) {
|
||||
let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == compName.toLowerCase())
|
||||
if (competence) {
|
||||
if (competence.system.isBase) {
|
||||
return this.system.caracteristiques[competence.system.caracteristique].value
|
||||
}
|
||||
return competence.system.score
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getMeilleureCompetenceMainGauche(comp) {
|
||||
let compScore = this.getCompetenceScore(comp.name)
|
||||
let mainGaucheScore = this.getCompetenceScore("main gauche")
|
||||
if (mainGaucheScore < compScore) {
|
||||
ui.notifications.info(`${actor.name} : Utilisation de la compétence Main Gauche au lieu de ${comp.name}`)
|
||||
let mainGaucheComp = this.itms.find(item => item.type == "competence" && item.name.toLowerCase() == "main gauche")
|
||||
if (!mainGaucheComp) {
|
||||
// Create a fake competence object
|
||||
mainGaucheComp = foundry.utils.duplicate(comp)
|
||||
mainGaucheComp.name = "Main Gauche"
|
||||
mainGaucheComp.system.isBase = false
|
||||
mainGaucheComp.system.score = 0
|
||||
mainGaucheComp.system.caracteristique = "adresse"
|
||||
mainGaucheComp.system.description = "Compétence Main Gauche (automatique)"
|
||||
mainGaucheComp.system.isMainGauche = true
|
||||
return mainGaucheComp
|
||||
} else {
|
||||
return mainGaucheComp
|
||||
}
|
||||
} else {
|
||||
return comp
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_onUpdate(changed, options, userId) {
|
||||
let updates = []
|
||||
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 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)
|
||||
}
|
||||
|
||||
super._onUpdate(changed, options, userId);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _preCreate(data, options, user) {
|
||||
await super._preCreate(data, options, user);
|
||||
@@ -65,62 +166,248 @@ export class TeDeumActor extends Actor {
|
||||
this.updateSource({ prototypeToken });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getCommonBaseValue(value) {
|
||||
return game.system.tedeum.config.COMMON_VALUE[value]?.value || 0
|
||||
}
|
||||
getInitiativeValue() {
|
||||
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]
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
getAttaqueBonusDegats(rollData = undefined) {
|
||||
let base = game.system.tedeum.config.BONUS_DEGATS[this.system.caracteristiques.puissance.value].value
|
||||
let additionalBonus = 0
|
||||
if (rollData) {
|
||||
// Spécificité armes naturelle avec gantelet
|
||||
if (rollData?.arme?.system.specificites?.poing?.hasSpec && this.items.find(item => item.type == "armure" && item.name.toLowerCase() == "gantelet" && item.system.equipe)) {
|
||||
additionalBonus += 1
|
||||
rollData.gantelet = true
|
||||
}
|
||||
if (rollData.isChargeAPied) {
|
||||
additionalBonus += this.getCompetenceScore("course")
|
||||
} else if (rollData.isChargeACheval) {
|
||||
additionalBonus += this.getCompetenceScore("equitation")
|
||||
}
|
||||
}
|
||||
return base + additionalBonus
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
getNbArmures() {
|
||||
return game.system.tedeum.config.MAX_ARMURES_LOURDES[this.system.caracteristiques.puissance.value]
|
||||
}
|
||||
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;
|
||||
}
|
||||
getSimples() {
|
||||
let comp = foundry.utils.duplicate(this.items.filter(item => item.type == 'simple') || [])
|
||||
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
|
||||
let enduranceScore = this.getCompetenceScore("endurance")
|
||||
if (blessures.length > enduranceScore) {
|
||||
modTotal += -1
|
||||
}
|
||||
return modifierBlessures
|
||||
return modTotal
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
async appliquerBlessure(blessureId, locId, comment = "") {
|
||||
let blessure = game.system.tedeum.config.blessures[blessureId]
|
||||
if (!blessure) {
|
||||
ui.notifications.warn("Type de blessure inconnu : " + blessureId)
|
||||
console.error("Type de blessure inconnu : " + blessureId)
|
||||
return
|
||||
}
|
||||
// Create a new blessure object
|
||||
let blessureObj = {
|
||||
name: blessure.label,
|
||||
type: "blessure",
|
||||
system: {
|
||||
typeBlessure: blessureId,
|
||||
localisation: locId || "maindroite",
|
||||
value: blessure.value,
|
||||
appliquee: true,
|
||||
description: comment,
|
||||
}
|
||||
}
|
||||
this.createEmbeddedDocuments('Item', [blessureObj]);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getArmorDegatsModifier(rollData, combat) {
|
||||
let loc = combat[rollData.loc.id]
|
||||
// Sans armure
|
||||
if (loc.armures.length == 0) {
|
||||
return rollData.arme.system.degatsArmure.sansarmure
|
||||
}
|
||||
// Avec armure de cuir
|
||||
if (loc.armures.find(a => a.system.typeArmure == "cuir")) {
|
||||
return rollData.arme.system.degatsArmure.cuir
|
||||
}
|
||||
// Avec armure de maille
|
||||
if (loc.armures.find(a => a.system.typeArmure == "maille")) {
|
||||
return rollData.arme.system.degatsArmure.mailles
|
||||
}
|
||||
// Avec armure de plate
|
||||
if (loc.armures.find(a => a.system.typeArmure == "plate")) {
|
||||
return rollData.arme.system.degatsArmure.plates
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async appliquerDegats(rollData) {
|
||||
let combat = this.prepareCombat()
|
||||
rollData.defenderName = this.name
|
||||
let touche = combat[rollData.loc.id].touche
|
||||
let armorDegatModifier = this.getArmorDegatsModifier(rollData, combat)
|
||||
rollData.degats += armorDegatModifier
|
||||
rollData.armorDegatModifier = armorDegatModifier
|
||||
|
||||
let blessureId = "indemne"
|
||||
if (rollData.degats > 0 && rollData.degats > touche) {
|
||||
let diff = rollData.degats - touche
|
||||
for (let bId in game.system.tedeum.config.blessures) {
|
||||
let blessure = game.system.tedeum.config.blessures[bId]
|
||||
if (diff >= blessure.degatsMin && diff <= blessure.degatsMax) {
|
||||
if (rollData.isReussiteCritique) {
|
||||
bId = game.system.tedeum.config.blessuresOrder[blessure.value + 1]
|
||||
}
|
||||
blessureId = bId
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rollData.isReussiteCritique && blessureId == "indemne") { // Critical success without degats => lightest blessure
|
||||
blessureId = "estafilade"
|
||||
}
|
||||
console.log("Appliquer dégats", rollData, combat, blessureId)
|
||||
if (blessureId != "indemne") {
|
||||
let blessure = game.system.tedeum.config.blessures[blessureId]
|
||||
// Create a new blessure object
|
||||
let blessureObj = {
|
||||
name: blessure.label,
|
||||
type: "blessure",
|
||||
system: {
|
||||
typeBlessure: blessureId,
|
||||
localisation: rollData.loc.id,
|
||||
value: blessure.value,
|
||||
appliquee: true,
|
||||
description: "Blessure infligée par un coup de " + rollData.arme.name + " de " + rollData.alias,
|
||||
}
|
||||
}
|
||||
rollData.blessure = blessureObj
|
||||
rollData.touche = touche
|
||||
this.createEmbeddedDocuments('Item', [blessureObj]);
|
||||
}
|
||||
// Display the relevant chat message
|
||||
let msg = await TeDeumUtility.createChatWithRollMode(rollData.alias, {
|
||||
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-blessure-result.hbs`, rollData)
|
||||
})
|
||||
await msg.setFlag("world", "te-deum-rolldata", rollData)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -128,17 +415,22 @@ export class TeDeumActor extends Actor {
|
||||
c.key = key
|
||||
c.name = game.system.tedeum.config.caracteristiques[key].label
|
||||
c.generalqualite = game.system.tedeum.config.descriptionValeur[c.value].qualite
|
||||
c.qualite = game.system.tedeum.config.descriptionValeur[c.value][key]
|
||||
if (this.system.genre.toLowerCase() == "homme") {
|
||||
c.qualite = game.system.tedeum.config.descriptionValeur[c.value][key]
|
||||
} else {
|
||||
c.qualite = game.system.tedeum.config.descriptionValeurFemme[c.value][key]
|
||||
}
|
||||
c.dice = game.system.tedeum.config.descriptionValeur[c.value].dice
|
||||
c.negativeDice = game.system.tedeum.config.descriptionValeur[c.value].negativeDice
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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 +438,56 @@ export class TeDeumActor extends Actor {
|
||||
prepareProvidence() {
|
||||
let providence = foundry.utils.deepClone(this.system.providence)
|
||||
providence.name = "Providence"
|
||||
providence.qualite = game.system.tedeum.config.providence[providence.value].labelM
|
||||
if (this.system.genre.toLowerCase() == "homme") {
|
||||
providence.qualite = game.system.tedeum.config.providence[providence.value].labelM
|
||||
} else {
|
||||
providence.qualite = game.system.tedeum.config.providence[providence.value].labelF
|
||||
}
|
||||
providence.dice = game.system.tedeum.config.providence[providence.value].diceValue
|
||||
providence.description = "La Providence représente la Volonté Divine à l'œuvre pour guider ou sauver un être humain. Les PJ montent dans l’échelle de la Providence en menant à bien leurs missions et en se montrant vertueux. Les points de Providence peuvent servir à augmenter temporairement une caractéris- tique, à modifier la gravité d'une blessure, et à résister au vieillissement. Chaque person- nage commence avec un score initial de 1 en Providence (au niveau Pauvre pécheur)."
|
||||
return providence
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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) {
|
||||
async modifyXP(key, value) {
|
||||
let xp = this.system.caracteristiques[key].experience
|
||||
xp = Math.max(xp + value, 0)
|
||||
this.update( { [`system.caracteristiques.${key}.experience`]: xp } )
|
||||
await this.update({ [`system.caracteristiques.${key}.experience`]: xp })
|
||||
this.sheet?.render(true)
|
||||
ui.notifications.info(`+${value} XP en ${game.system.tedeum.config.caracteristiques[key].label}`)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -174,7 +500,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 +519,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 +527,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 +634,17 @@ 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.getInitiativeValue()
|
||||
// Vérifie les armes avec bonus d'initiative
|
||||
let armes = this.getArmes()
|
||||
for (let arme of armes) {
|
||||
if (arme.system.equipe && Number(arme.system.initiativeBonus) && Number(arme.system.initiativeBonus) != 0) {
|
||||
ui.notifications.info("L'arme " + arme.name + " vous confère un bonus d'initiative de " + arme.system.initiativeBonus)
|
||||
initiative += arme.system.initiativeBonus
|
||||
}
|
||||
}
|
||||
return initiative
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -308,7 +671,7 @@ export class TeDeumActor extends Actor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getCommonRollData() {
|
||||
let rollData = TeDeumUtility.getBasicRollData()
|
||||
@@ -317,7 +680,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 +688,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
|
||||
|
||||
@@ -342,20 +705,77 @@ export class TeDeumActor extends Actor {
|
||||
let rollData = this.getCommonCompetence(compId)
|
||||
rollData.mode = "competence"
|
||||
rollData.title = rollData.competence.name
|
||||
rollData.compScore = rollData.competence.system.isBase ? this.system.caracteristiques[rollData.competence.system.caracteristique].value : rollData.competence.system.score
|
||||
this.startRoll(rollData).catch("Error on startRoll")
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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) {
|
||||
let compIdx = weapon.system.competence
|
||||
compName = game.system.tedeum.config.armeCompetences[compIdx]?.label
|
||||
}
|
||||
let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == compName.toLowerCase())
|
||||
if (competence) {
|
||||
rollData.competence = competence
|
||||
rollData.compScore = rollData.competence.system.isBase ? this.system.caracteristiques[rollData.competence.system.caracteristique].value : rollData.competence.system.score
|
||||
let c = foundry.utils.duplicate(this.system.caracteristiques[competence.system.caracteristique])
|
||||
this.updateCarac(c, competence.system.caracteristique)
|
||||
rollData.carac = c
|
||||
rollData.allongeLabel = game.system.tedeum.config.armeAllonges[weapon.system.allonge].label
|
||||
rollData.allongeId = "courte"
|
||||
rollData.allonges = foundry.utils.duplicate(game.system.tedeum.config.allonges[weapon.system.allonge])
|
||||
|
||||
} else {
|
||||
ui.notifications.warn("Impossible de trouver la compétence " + compName)
|
||||
return
|
||||
}
|
||||
this.startRoll(rollData).catch("Error on startRoll")
|
||||
} else {
|
||||
ui.notifications.warn("Impossible de trouver l'arme concernée ")
|
||||
|
669
modules/app/tedeum-character-creator.js
Normal file
@@ -0,0 +1,669 @@
|
||||
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.sexe = undefined
|
||||
this.origineSociale = undefined
|
||||
this.religion = undefined
|
||||
this.caracBonus = {}
|
||||
this.competenceBonus = {}
|
||||
this.suiviReponses = []
|
||||
this.competences = TeDeumUtility.getCompetencesForDropDown()
|
||||
this.choiceSummary = {}
|
||||
|
||||
for (let k in game.system.tedeum.config.caracteristiques) {
|
||||
this.caracBonus[k] = { value: 0 }
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
this.choiceSummary[this.currentStage].competences[compName] = 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 foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-stage-name.hbs", context)
|
||||
const choiceResult = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: context.title },
|
||||
classes: ["fvtt-te-deum"],
|
||||
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"
|
||||
this.choiceSummary[this.currentStage].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 foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-questions.hbs", context)
|
||||
const choiceResult = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: context.title },
|
||||
classes: ["fvtt-te-deum"],
|
||||
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)
|
||||
|
||||
this.suiviReponses.push({ key: this.currentStage, etape: stage.name, question: question.question, reponse: selectedResponse.reponse, compName: compName })
|
||||
}
|
||||
}
|
||||
|
||||
/*------------- -------------------------------*/
|
||||
async askCompetences(stage, context) {
|
||||
context.subtitle = "Choix des Compétences"
|
||||
this.choiceSummary[this.currentStage].competences = {}
|
||||
|
||||
context.fixedCompetences = {}
|
||||
context.selectCompetences = {}
|
||||
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 foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-competences.hbs", context)
|
||||
const choiceResult = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: context.title },
|
||||
classes: ["fvtt-te-deum"],
|
||||
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 foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-competences.hbs", context)
|
||||
const choiceResult = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: context.title },
|
||||
classes: ["fvtt-te-deum"],
|
||||
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"
|
||||
this.choiceSummary[this.currentStage] = {
|
||||
caracBonus : {},
|
||||
competences : {}
|
||||
}
|
||||
|
||||
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 foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-select-carac.hbs", context)
|
||||
const choiceResult = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: context.title },
|
||||
classes: ["fvtt-te-deum"],
|
||||
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)
|
||||
this.choiceSummary[this.currentStage].caracBonus[choiceResult.carac] = 1
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------*/
|
||||
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 foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-origine.hbs", context)
|
||||
const label = "Valider le choix de l'Origine Sociale"
|
||||
const choiceResult = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: context.title },
|
||||
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.choiceSummary['origineSociale'] = {
|
||||
sexe: this.sexe,
|
||||
religion: this.religion,
|
||||
origineSociale: this.origineSociale.label,
|
||||
caracBonus: this.caracBonus,
|
||||
}
|
||||
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",
|
||||
hasGenre: false,
|
||||
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);
|
||||
this.choiceSummary['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 && (item.system.genre === this.sexe || item.system.genre === "Mixte"))
|
||||
|
||||
let context = {
|
||||
title: "Les Petits Grimauds",
|
||||
label: "Valider le choix des Petits Grimauds",
|
||||
hasGenre: true,
|
||||
choices: grimaudsItems,
|
||||
caracBonus: this.caracBonus,
|
||||
competenceBonus: this.competenceBonus
|
||||
}
|
||||
|
||||
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 && (item.system.genre === this.sexe || item.system.genre === "Mixte"))
|
||||
|
||||
let context = {
|
||||
title: "Création de personnage - Les Roses de la Vie",
|
||||
label: "Valider le choix des Roses de la Vie",
|
||||
choices: rosesItems,
|
||||
hasGenre: true,
|
||||
caracBonus: this.caracBonus,
|
||||
competenceBonus: this.competenceBonus
|
||||
|
||||
}
|
||||
|
||||
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,
|
||||
hasGenre: false,
|
||||
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})
|
||||
|
||||
let histoire = ""
|
||||
for ( let key in this.choiceSummary) {
|
||||
let stageSummary = this.choiceSummary[key]
|
||||
if (stageSummary.sexe) {
|
||||
histoire += `<h3>Origine Sociale</h3>`
|
||||
histoire += `<p>${stageSummary.sexe} - ${stageSummary.religion} - ${stageSummary.origineSociale}</p>`
|
||||
} else {
|
||||
histoire += `<h3>${game.system.tedeum.config.etapesEducation[key].label}</h3>`
|
||||
}
|
||||
if (stageSummary.caracBonus) {
|
||||
histoire += `<p><strong>Caractéristiques : </strong><ul>`
|
||||
for (let caracKey in stageSummary.caracBonus) {
|
||||
histoire += `<li>${TeDeumUtility.upperFirst(caracKey)} +1</li>`
|
||||
}
|
||||
histoire += `</ul></p>`
|
||||
}
|
||||
if (stageSummary.competences) {
|
||||
histoire += `<p><strong>Compétences : </strong><ul>`
|
||||
for (let compName in stageSummary.competences) {
|
||||
histoire += `<li>${TeDeumUtility.upperFirst(compName)} +1</li>`
|
||||
}
|
||||
histoire += `</ul></p>`
|
||||
}
|
||||
let questions = this.suiviReponses.filter( r => r.key === key)
|
||||
if (questions.length > 0) {
|
||||
histoire += `<p><strong>Réponses au questionnaire : </strong><ul>`
|
||||
for (let question of questions) {
|
||||
histoire += `<li>${question.question} : <i>${question.reponse}</i> (${TeDeumUtility.upperFirst(question.compName)}+1)</li>`
|
||||
}
|
||||
histoire += `</ul></p>`
|
||||
}
|
||||
}
|
||||
await actor.update({ "system.histoire": histoire})
|
||||
actor.render(true)
|
||||
|
||||
context.pointsCompetence = {
|
||||
"savoir": { score: actor.getCompetenceScore("Mémoriser"), label: "Savoir" },
|
||||
"sensibilite": { score: actor.getCompetenceScore("Perception"), label: "Sensibilité" },
|
||||
"entregent": { score: actor.getCompetenceScore("Charme"), label: "Entregent" },
|
||||
"puissance": { score: actor.getCompetenceScore("Effort"), label: "Puissance" },
|
||||
"complexion": { score: actor.getCompetenceScore("Endurance"), label: "Complexion" },
|
||||
"adresse": { score: actor.getCompetenceScore("Initiative"), label: "Adresse" },
|
||||
}
|
||||
|
||||
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/character-creator-finished.hbs", context)
|
||||
const label = "Terminer"
|
||||
const choiceResult = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: context.title },
|
||||
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) => { }
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -2,22 +2,37 @@ import { TeDeumUtility } from "../common/tedeum-utility.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class TeDeumCombat extends Combat {
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollInitiative(ids, formula = undefined, messageOptions = {} ) {
|
||||
async rollInitiative(ids, formula = undefined, messageOptions = {}) {
|
||||
//console.log("Roll INIT !")
|
||||
ids = typeof ids === "string" ? [ids] : ids;
|
||||
for (let cId = 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) {
|
||||
async modifyAction(combatantId, delta, isMainGauche = false) {
|
||||
let combatant = this.combatants.get(combatantId)
|
||||
if (!combatant) return;
|
||||
let ca = combatant.getFlag("world", "available-actions")
|
||||
if (!ca) {
|
||||
ca = { nbActions: 1, nbActionsMainGauche: 0 }
|
||||
}
|
||||
if (isMainGauche) {
|
||||
ca.nbActionsMainGauche += delta
|
||||
} else {
|
||||
ca.nbActions += delta
|
||||
}
|
||||
if (ca.nbActionsMainGauche < 0) ca.nbActionsMainGauche = 0
|
||||
if (ca.nbActions < 0) ca.nbActions = 0
|
||||
await combatant.setFlag("world", "available-actions", ca)
|
||||
await combatant.update({ name: `${combatant.token.name} (${ca.nbActions} / ${ca.nbActionsMainGauche})` })
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@@ -9,30 +9,46 @@ export const TEDEUM_CONFIG = {
|
||||
{ value: 7 }, { value: 9 }, { value: 11 }],
|
||||
ACTIONS_PAR_TOUR: [{}, { value: 1 }, { value: 2 }, { value: 2 },
|
||||
{ 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 }],
|
||||
|
||||
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", categorie: "pied", nbArmure: 1, score: { min: 1, max: 1 }, coord: { top: 500, left: 0 } },
|
||||
"jambedroite": { label: "Jambe Droite", value: 1, locMod: -1, id: "jambedroite", categorie: "jambe", nbArmure: 1, score: { min: 3, max: 4 }, coord: { top: 400, left: 100 } },
|
||||
"jambegauche": { label: "Jambe Gauche", value: 1, locMod: -1, id: "jambegauche", categorie: "jambe", nbArmure: 1, score: { min: 5, max: 6 }, coord: { top: 400, left: 300 } },
|
||||
"piedgauche": { label: "Pied Gauche", value: 1, locMod: 0, id: "piedgauche", categorie: "pied", nbArmure: 1, score: { min: 2, max: 2 }, coord: { top: 500, left: 400 } },
|
||||
"maindroite": { label: "Main Droite", value: 1, locMod: 0, id: "maindroite", categorie: "main", nbArmure: 1, score: { min: 7, max: 7 }, coord: { top: 0, left: 0 } },
|
||||
"maingauche": { label: "Main Gauche", value: 1, locMod: 0, id: "maingauche", categorie: "main", nbArmure: 1, score: { min: 8, max: 8 }, coord: { top: 0, left: 400 } },
|
||||
"brasdroit": { label: "Bras Droit", value: 1, locMod: -1, id: "brasdroit", categorie: "bras", nbArmure: 2, score: { min: 9, max: 10 }, coord: { top: 200, left: 0 } },
|
||||
"brasgauche": { label: "Bras Gauche", value: 1, locMod: -1, id: "brasgauche", categorie: "bras", nbArmure: 2, score: { min: 11, max: 12 }, coord: { top: 200, left: 400 } },
|
||||
"corps": { label: "Corps", value: 1, id: "corps", categorie: "corps", locMod: -2, nbArmure: 2, score: { min: 13, max: 17 }, coord: { top: 200, left: 200 } },
|
||||
"tete": { label: "Tête", value: 1, id: "tete", categorie: "tete", locMod: -2, nbArmure: 2, score: { min: 18, max: 20 }, coord: { top: 0, left: 200 } },
|
||||
},
|
||||
|
||||
ATTAQUE_CIBLEES: {
|
||||
"aucune": { label: "Aucune", id: "aucune", locMod: 0, description: "Attaque non ciblée" },
|
||||
"pieddroit": { label: "Pied Droit", id: "pieddroit", locMod: 0, description: "Attaque ciblée sur le pied droit" },
|
||||
"jambedroite": { label: "Jambe Droite", id: "jambedroite", locMod: -1, description: "Attaque ciblée sur la jambe droite" },
|
||||
"jambegauche": { label: "Jambe Gauche", id: "jambegauche", locMod: -1, description: "Attaque ciblée sur la jambe gauche" },
|
||||
"piedgauche": { label: "Pied Gauche", id: "piedgauche", locMod: 0, description: "Attaque ciblée sur le pied gauche" },
|
||||
"maindroite": { label: "Main Droite", id: "maindroite", locMod: 0, description: "Attaque ciblée sur la main droite" },
|
||||
"maingauche": { label: "Main Gauche", id: "maingauche", locMod: 0, description: "Attaque ciblée sur la main gauche" },
|
||||
"brasdroit": { label: "Bras Droit", id: "brasdroit", locMod: -1, description: "Attaque ciblée sur le bras droit" },
|
||||
"brasgauche": { label: "Bras Gauche", id: "brasgauche", locMod: -1, description: "Attaque ciblée sur le bras gauche" },
|
||||
"corps": { label: "Corps", id: "corps", locMod: -2, description: "Attaque ciblée sur le corps" },
|
||||
"tete": { label: "Tête", id: "tete", locMod: -2, description: "Attaque ciblée sur la tête" },
|
||||
},
|
||||
|
||||
ARME_SPECIFICITE: {
|
||||
"encombrante": { label: "Encombrante", id: "encombrante", melee: true, tir: true},
|
||||
"poing": { label: "Poings", id: "poing", melee: true, tir: false },
|
||||
"pied": { label: "Pieds", id: "pied", melee: true, tir: false },
|
||||
"encombrante": { label: "Encombrante", id: "encombrante", melee: true, tir: true },
|
||||
"maintiendistance": { label: "Maintien à distance", id: "maintiendistance", melee: true, tir: false },
|
||||
"coupassomant": { label: "Coup assomant", id: "coupassomant", melee: true, tir: false},
|
||||
"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 +59,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" },
|
||||
2: { valeur: 2, qualite: "Médiocre", dice: "d6", negativeDice: "d12", savoir: "Limité", sensibilite: "Etriqué", entregent: "Fruste", puissance: "Délicat", complexion: "Languide", adresse: "Gauche" },
|
||||
3: { valeur: 3, qualite: "Correct", dice: "d8", negativeDice: "d10", savoir: "Mêlé", sensibilite: "Ouvert", entregent: "Badin", puissance: "Membru", complexion: "Dispos", adresse: "Ingambe" },
|
||||
4: { valeur: 4, qualite: "Bon", dice: "d10", negativeDice: "d8", savoir: "Lettré", sensibilite: "Fin", entregent: "Disert", puissance: "Vigoureux", complexion: "Gaillard", adresse: "Leste" },
|
||||
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" },
|
||||
@@ -66,29 +87,42 @@ export const TEDEUM_CONFIG = {
|
||||
},
|
||||
descriptionValeur: {
|
||||
1: { valeur: 1, qualite: "Mauvais", dice: "d4", negativeDice: "d20", savoir: "Sot", sensibilite: "Obtus", entregent: "Rustaud", puissance: "Menu", complexion: "Anémique", adresse: "Empesé" },
|
||||
2: { valeur: 2, qualite: "Médiocre", dice: "d6", negativeDice: "d12", savoir: "Limité", sensibilite: "Etriqué", entregent: "Frustre", puissance: "Délicat", complexion: "Languide", adresse: "Gauche" },
|
||||
2: { valeur: 2, qualite: "Médiocre", dice: "d6", negativeDice: "d12", savoir: "Limité", sensibilite: "Etriqué", entregent: "Fruste", puissance: "Délicat", complexion: "Languide", adresse: "Gauche" },
|
||||
3: { valeur: 3, qualite: "Correct", dice: "d8", negativeDice: "d10", savoir: "Mêlé", sensibilite: "Ouvert", entregent: "Badin", puissance: "Membru", complexion: "Dispos", adresse: "Ingambe" },
|
||||
4: { valeur: 4, qualite: "Bon", dice: "d10", negativeDice: "d8", savoir: "Lettré", sensibilite: "Fin", entregent: "Disert", puissance: "Vigoureux", complexion: "Gaillard", adresse: "Leste" },
|
||||
5: { valeur: 5, qualite: "Excellent", dice: "d12", negativeDice: "d6", savoir: "Docte", sensibilite: "Subtil", entregent: "Galant", puissance: "Musculeux", complexion: "Sanguin", adresse: "Preste" },
|
||||
6: { valeur: 6, qualite: "Admirable", dice: "d20", negativeDice: "d4", savoir: "Humaniste", sensibilite: "Spirituel", entregent: "Sémillant", puissance: "Hercule", complexion: "Aguerri", adresse: "Alerte" },
|
||||
},
|
||||
diceValeur: [ "d4", "d6", "d8", "d10", "d12", "d20" ],
|
||||
degatsArmure : {
|
||||
sansarmure : { label: "Sans armure"},
|
||||
cuir : { label: "Cuir"},
|
||||
plates : { label: "Plates"},
|
||||
mailles : { label: "Mailles"},
|
||||
descriptionValeurFemme: {
|
||||
1: { valeur: 1, qualite: "Mauvais", dice: "d4", negativeDice: "d20", savoir: "Sotte", sensibilite: "Obtuse", entregent: "Rustaude", puissance: "Menue", complexion: "Anémique", adresse: "Empesée" },
|
||||
2: { valeur: 2, qualite: "Médiocre", dice: "d6", negativeDice: "d12", savoir: "Limitée", sensibilite: "Etriquée", entregent: "Fruste", puissance: "Délicate", complexion: "Languide", adresse: "Gauche" },
|
||||
3: { valeur: 3, qualite: "Correct", dice: "d8", negativeDice: "d10", savoir: "Mêlée", sensibilite: "Ouverte", entregent: "Badine", puissance: "Membrue", complexion: "Dispose", adresse: "Ingambe" },
|
||||
4: { valeur: 4, qualite: "Bon", dice: "d10", negativeDice: "d8", savoir: "Lettrée", sensibilite: "Fine", entregent: "Diserte", puissance: "Vigoureuse", complexion: "Gaillarde", adresse: "Leste" },
|
||||
5: { valeur: 5, qualite: "Excellent", dice: "d12", negativeDice: "d6", savoir: "Docte", sensibilite: "Subtile", entregent: "Galante", puissance: "Musculeuse", complexion: "Sanguine", adresse: "Preste" },
|
||||
6: { valeur: 6, qualite: "Admirable", dice: "d20", negativeDice: "d4", savoir: "Humaniste", sensibilite: "Spirituelle", entregent: "Sémillante", puissance: "Hercule", complexion: "Aguerrie", adresse: "Alerte" },
|
||||
},
|
||||
diceValeur: ["d4", "d6", "d8", "d10", "d12", "d20"],
|
||||
degatsArmure: {
|
||||
sansarmure: { label: "Sans armure" },
|
||||
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: { label: "Courte (0)", malus: 0 }, moyenne: { label: "Moyenne (-1)", malus: -1 }, longue: { label: "Longue (-2)", malus: -2 }, treslongue: { label: "Très longue (0, 2 Esquives)", malus: 0, esquive: 2 } },
|
||||
moyenne: { courte: { label: "Courte (0)", malus: 0 }, moyenne: { label: "Moyenne (0)", malus: 0 }, longue: { label: "Longue (-1)", malus: -1 }, treslongue: { label: "Très longue (0, 2 Esquives)", malus: 0, esquive: 2 } },
|
||||
longue: { courte: { label: "Courte (-2)", malus: -2 }, moyenne: { label: "Moyenne (-1)", malus: -1 }, longue: { label: "Longue (0)", malus: 0 }, treslongue: { label: "Très longue (-1, 2 Esquives)", malus: -1, esquive: 1 } },
|
||||
treslongue: { courte: { label: "Courte (0, 2 Esquives)", malus: 0, esquive: 2 }, moyenne: { label: "Moyenne (0, 2 Esquives)", malus: 0, esquive: 2 }, longue: { label: "Longue (0, 1 Esquive)", malus: 0, esquive: 1 }, treslongue: { label: "Très longue (0)", malus: 0 } },
|
||||
},
|
||||
|
||||
providence: [
|
||||
{ labelM: "Brebis égarée", labelF: "Brebis égarée", value: 0, diceValue: "0" },
|
||||
{ labelM: "Pauvre pêcheur", labelF: "Pauvre pêcheresse", value: 1, diceValue: "d4" },
|
||||
@@ -98,16 +132,25 @@ 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" }
|
||||
},
|
||||
genreEducation: {
|
||||
"homme": { label: "Homme", value: "Homme" },
|
||||
"femme": { label: "Femme", value: "Femme" },
|
||||
"mixte": { label: "Mixte", value: "Mixte" }
|
||||
},
|
||||
armeAllonges: {
|
||||
courte: { label: "Courte", value: "courte" },
|
||||
moyenne: { label: "Moyenne", value: "moyenne" },
|
||||
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,52 +161,84 @@ 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 (3)", key: "routine", value: 3 },
|
||||
facile: { label: "Facile (5)", key: "facile", value: 5 },
|
||||
pardefaut: { label: "Par Défaut (7)", key: "pardefaut", value: 7 },
|
||||
malaise: { label: "Malaisé (9)", key: "malaise", value: 9 },
|
||||
difficile: { label: "Difficile (11)", key: "difficile", value: 11 },
|
||||
perilleux: { label: "Perilleux (13)", key: "perilleux", value: 13 },
|
||||
desespere: { label: "Désespéré (15)", key: "desespere", value: 15 }
|
||||
},
|
||||
monnaie: {
|
||||
denier: { label: "Deniers", id: "denier", value: 1 },
|
||||
sol: { label: "Sols", id: "sol", value: 10 },
|
||||
livre: { label: "Livres", id: "livre", value: 100 }
|
||||
},
|
||||
monnaieUnit: {
|
||||
"1": { label: "Deniers", id: "denier", value: 1 },
|
||||
"10": { label: "Sols", id: "sol", value: 10 },
|
||||
"100": { label: "Livres", id: "livre", value: 100 }
|
||||
},
|
||||
etapesEducation: {
|
||||
pouponniere: { label: "La Pouponnière", value: "pouponniere", agemin: 0, agemax: 6, nbCompetences: 2, nbCaracteristiques: 3, hasQuestionnaire: true, 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, hasGenre: false, hasQuestionnaire: true, hasDebouches: false, hasMultiplier: false, canCompetencesOpt: false },
|
||||
petitsgrimauds: { label: "La classe des Petits Grimauds", value: "petitsgrimauds", agemin: 7, agemax: 12, nbCompetences: 10, hasGenre: true, nbCaracteristiques: 3, hasDebouches: false, hasQuestionnaire: true, hasMultiplier: false, canCompetencesOpt: false },
|
||||
rosevie: { label: "Les Roses de la Vie", value: "rosevie", agemin: 13, agemax: 16, nbCompetences: 2, nbCaracteristiques: 3, hasGenre: true, hasQuestionnaire: true, hasDebouches: true, hasMultiplier: false, canCompetencesOpt: false },
|
||||
ageviril: { label: "L'Age Viril", value: "ageviril", agemin: 17, agemax: 17, nbCompetences: 9, nbCaracteristiques: 2, hasGenre: false, hasQuestionnaire: false, hasDebouches: false, hasMultiplier: true, canCompetencesOpt: true },
|
||||
},
|
||||
origineSociale: {
|
||||
noblesseepee: { label: "Noblesse d'épée", id: "noblesseepee", 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" }
|
||||
],
|
||||
blessuresOrder: ["indemne", "estafilade", "plaie", "plaiebeante", "plaieatroce", "tuenet", "tuenet", "tuenet", "tuenet", "tuenet"],
|
||||
blessures: {
|
||||
indemne: { value: 0, label: "Indemne", key: "indemne", degatsMax: -1, count: 0, modifier: 0 },
|
||||
estafilade: { value: 1, label: "Estafilade", key: "estafilade", degatsMin: 0, degatsMax: 2, count: 1, modifier: 0 },
|
||||
plaie: { value: 2, label: "Plaie", key: "plaie", degatsMin: 3, degatsMax: 4, count: 1, modifier: -1 },
|
||||
plaiebeante: { value: 3, label: "Plaie béante", key: "plaiebeante", degatsMin: 5, degatsMax: 6, count: 1, modifier: -2 },
|
||||
plaieatroce: { value: 4, label: "Plaie atroce", key: "plaieatroce", degatsMin: 7, degatsMax: 8, count: 1, horsCombat: true, modifier: -12 },
|
||||
tuenet: { value: 5, label: "Tué net", key: "tuenet", degatsMin: 9, degatsMax: 100, count: 1, horsCombat: true, mort: true, modifier: -100 }
|
||||
},
|
||||
virulence: {
|
||||
aucune: { label: "Aucune", value: "aucune", modifier: 0 },
|
||||
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 }
|
||||
}
|
||||
}
|
@@ -5,8 +5,70 @@ 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"
|
||||
}
|
||||
|
||||
static installHooks() {
|
||||
Hooks.on('renderChatLog', (log, html, data) => TeDeumUtility.chatListeners(html));
|
||||
//Hooks.on("getChatLogEntryContext", (html, options) => TeDeumUtility.chatMenuManager(html, options));
|
||||
|
||||
Hooks.on("renderActorDirectory", (app, html, data) => {
|
||||
if (game.user.can('ACTOR_CREATE')) {
|
||||
const button = document.createElement('button');
|
||||
button.style.width = '60%';
|
||||
button.classList.add('tedeum-create-character');
|
||||
button.innerHTML = 'Créer un Personnage'
|
||||
button.addEventListener('click', () => {
|
||||
let cr = new game.system.tedeum.TeDeumCharacterCreator();
|
||||
cr.init()
|
||||
})
|
||||
$(html).find('.header-actions').after(button)
|
||||
}
|
||||
})
|
||||
|
||||
Hooks.on("combatStart", async (combat, updateData, options) => {
|
||||
this.resetCombatActions(combat)
|
||||
});
|
||||
|
||||
Hooks.on("combatRound", (combat, updateData, updateOptions) => {
|
||||
// List all actors related to combatant
|
||||
if (game.user.isGM) {
|
||||
this.resetCombatActions(combat)
|
||||
}
|
||||
})
|
||||
|
||||
Hooks.on("getCombatTrackerContextOptions", (html, options) => {
|
||||
console.log("Get Combat Tracker Context", html, options)
|
||||
this.pushCombatOptions(html, options);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static pushCombatOptions(html, options) {
|
||||
options.push({ name: "Actions +1", condition: true, icon: '<i class="fas fa-plus"></i>', callback: target => { game.combat.modifyAction($(target).data('combatant-id'), 1); } })
|
||||
options.push({ name: "Actions -1", condition: true, icon: '<i class="fas fa-minus"></i>', callback: target => { game.combat.modifyAction($(target).data('combatant-id'), -1); } })
|
||||
options.push({ name: "Actions MG +1", condition: true, icon: '<i class="fas fa-plus"></i>', callback: target => { game.combat.modifyAction($(target).data('combatant-id'), 1, true); } })
|
||||
options.push({ name: "Actions MG -1", condition: true, icon: '<i class="fas fa-minus"></i>', callback: target => { game.combat.modifyAction($(target).data('combatant-id'), -1, true); } })
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async resetCombatActions(combat) {
|
||||
for (let c of combat.combatants) {
|
||||
let actor = game.actors.get(c.actorId)
|
||||
if (actor) {
|
||||
let nbActions = actor.getNbActions()?.value || 0
|
||||
let isMainGauche = (actor.getCompetenceScore("Main gauche") > 0)
|
||||
let nbActionsMainGauche = isMainGauche ? nbActions : 0
|
||||
await c.setFlag("world", "available-actions", { nbActions, nbActionsMainGauche })
|
||||
await c.update({ name: `${c.token.name} (${nbActions} / ${nbActionsMainGauche})` })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -46,31 +108,73 @@ 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
|
||||
})
|
||||
Handlebars.registerHelper('monnaie', function (value) {
|
||||
let monnaie = game.system.tedeum.config.monnaieUnit[String(value)]
|
||||
if (monnaie) {
|
||||
return monnaie.label
|
||||
}
|
||||
return value
|
||||
})
|
||||
|
||||
// Load compendium data
|
||||
const competences = await TeDeumUtility.loadCompendium("fvtt-te-deum.competences")
|
||||
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 +189,26 @@ 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;
|
||||
formData.hasGenre = etape.hasGenre;
|
||||
}
|
||||
|
||||
/*-------------------------------------------- */
|
||||
@@ -133,47 +241,119 @@ 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 isAttackWinner = true
|
||||
let rWinner, rLooser
|
||||
if (this.currentOpposition.total <= rollData.total) {
|
||||
rWinner = foundry.utils.duplicate(rollData)
|
||||
rLooser = foundry.utils.duplicate(this.currentOpposition)
|
||||
isAttackWinner = false
|
||||
} else {
|
||||
rWinner = foundry.utils.duplicate(this.currentOpposition)
|
||||
rLooser = foundry.utils.duplicate(rollData)
|
||||
isAttackWinner = true
|
||||
}
|
||||
this.currentOpposition = undefined // Reset opposition
|
||||
let oppositionData = {
|
||||
winner: rWinner,
|
||||
looser: rLooser
|
||||
}
|
||||
// Update difficulty
|
||||
rWinner.difficulty = rLooser.total
|
||||
rLooser.difficulty = rWinner.total
|
||||
await this.computeResults(rWinner)
|
||||
await this.computeResults(rLooser)
|
||||
// Auto XP management when opposed
|
||||
if (rWinner.isReussiteCritique) {
|
||||
let actor = this.getActorFromRollData(rWinner)
|
||||
actor.modifyXP(rWinner.carac.key, 1)
|
||||
}
|
||||
if (rLooser.isEchecCritique) {
|
||||
let actor = this.getActorFromRollData(rLooser)
|
||||
actor.modifyXP(rLooser.carac.key, 1)
|
||||
}
|
||||
|
||||
let msg = await this.createChatWithRollMode(rollData.alias, {
|
||||
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-opposition-result.hbs`, oppositionData)
|
||||
})
|
||||
await msg.setFlag("world", "te-deum-rolldata", rollData)
|
||||
|
||||
// Si le gagnant est l'attaquant, appliquer les dégats sur la victime
|
||||
if (isAttackWinner && rWinner.isSuccess && rWinner.mode == "arme" && rWinner.arme?.system.typeArme == "melee" && rWinner.defenderTokenId) {
|
||||
await this.appliquerDegats(rWinner)
|
||||
}
|
||||
|
||||
console.log("Opposition result", rollData, isAttackWinner, oppositionData)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */ /* -------------------------------------------- */
|
||||
static async appliquerDegats(rollData) {
|
||||
await this.processAttaqueMelee(rollData)
|
||||
let defenderToken = canvas.tokens.placeables.find(t => t.id == rollData.defenderTokenId)
|
||||
if (defenderToken) {
|
||||
let actor = defenderToken.actor
|
||||
await actor.appliquerDegats(rollData)
|
||||
// Attaque naturelle avec dégats inférieur à -2
|
||||
if ((rollData?.arme?.system.specificites?.poing?.hasSpec || rollData?.arme?.system.specificites?.pied?.hasSpec) && rollData.degats < -2) {
|
||||
let attacker = this.getActorFromRollData(rollData)
|
||||
attacker.appliquerBlessure("estafilade", "maindroite", "Contusion suite à une attaque naturelle")
|
||||
ui.notifications.info(`${attacker.name} subit 1 contusion en infligeant ${rollData.degats} dégâts à mains nues`)
|
||||
}
|
||||
} else {
|
||||
ui.notifications.error("Impossible de trouver la cible de l'attaque, aucun degats appliqué")
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */ /* -------------------------------------------- */
|
||||
static async chatListeners(html) {
|
||||
|
||||
html.on("click", '.button-select-confront', event => {
|
||||
$(html).on("click", '.chat-command-opposition', event => {
|
||||
let messageId = TeDeumUtility.findChatMessageId(event.currentTarget)
|
||||
let message = game.messages.get(messageId)
|
||||
let rollData = message.getFlag("world", "te-deum-rolldata")
|
||||
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 => {
|
||||
$(html).on("click", '.chat-command-appliquer-degats', event => {
|
||||
let messageId = TeDeumUtility.findChatMessageId(event.currentTarget)
|
||||
let message = game.messages.get(messageId)
|
||||
let rollData = message.getFlag("world", "te-deum-rolldata")
|
||||
let difficulty = $("#" + rollData.rollId + "-cephaly-difficulty").val()
|
||||
TeDeumUtility.manageCephalyDifficulty(rollData, difficulty)
|
||||
if (rollData) {
|
||||
TeDeumUtility.appliquerDegats(rollData, messageId)
|
||||
}
|
||||
})
|
||||
html.on("click", '.button-apply-impact', event => {
|
||||
$(html).on("click", '.chat-command-gain-xp', 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)
|
||||
let rollData = message.getFlag("world", "te-deum-rolldata")
|
||||
if (rollData) {
|
||||
let actor = TeDeumUtility.getActorFromRollData(rollData)
|
||||
actor.modifyXP(rollData.carac.key, 1)
|
||||
// Hide this button
|
||||
event.currentTarget.style.display = 'none';
|
||||
}
|
||||
})
|
||||
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);
|
||||
return foundry.applications.handlebars.loadTemplates(templatePaths);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -248,9 +428,9 @@ 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),
|
||||
content: await foundry.applications.handlebars.renderTemplate(msg.data.template, rollData),
|
||||
whisper: game.user.id
|
||||
})
|
||||
chatMsg.setFlag("world", "tedeum-rolldata", rollData)
|
||||
@@ -340,10 +520,11 @@ export class TeDeumUtility {
|
||||
}
|
||||
}
|
||||
if (rollData.diceSum == 1) {
|
||||
let critiqueRoll = await new Roll(rollData.carac.negativeDice).roll()
|
||||
let critiqueRoll = await new Roll(rollData.carac.negativeDice)
|
||||
await critiqueRoll.evaluate()
|
||||
await this.showDiceSoNice(critiqueRoll, game.settings.get("core", "rollMode"))
|
||||
rollData.critiqueRoll = foundry.utils.duplicate(critiqueRoll)
|
||||
if (critiqueRoll.total > rollData.competence.score) {
|
||||
if (critiqueRoll.total > rollData.competence.system.score) {
|
||||
rollData.isEchecCritique = true
|
||||
}
|
||||
}
|
||||
@@ -352,16 +533,37 @@ 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)
|
||||
diceFormula = diceBase + "x + " + rollData.competence.system.score
|
||||
let localModifier = 0
|
||||
if (rollData.isViser) {
|
||||
localModifier += 1
|
||||
}
|
||||
if (rollData.isMouvement) {
|
||||
localModifier -= 1
|
||||
}
|
||||
if (rollData.arme && rollData.allongeId) {
|
||||
localModifier += rollData.allonges[rollData.allongeId].malus
|
||||
rollData.allongeMalus = rollData.allonges[rollData.allongeId].malus
|
||||
rollData.nbEsquives = rollData.allonges[rollData.allongeId]?.esquive || 0
|
||||
}
|
||||
if (rollData.attaqueCiblee && rollData.attaqueCiblee != "aucune") {
|
||||
localModifier -= 1
|
||||
rollData.loc = foundry.utils.duplicate(game.system.tedeum.config.LOCALISATION[rollData.attaqueCiblee])
|
||||
}
|
||||
let diceBase = this.modifyDice(rollData.carac.dice, localModifier + Number(rollData.bonusMalus) + rollData.santeModifier)
|
||||
if (!diceBase) return;
|
||||
diceFormula = diceBase + "x + " + rollData.compScore
|
||||
}
|
||||
if (rollData.enableProvidence) {
|
||||
diceFormula += " + " + rollData.providence.dice
|
||||
@@ -369,17 +571,105 @@ export class TeDeumUtility {
|
||||
return diceFormula
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async getLocalisation(rollData) {
|
||||
let locRoll
|
||||
if (rollData.loc) {
|
||||
locRoll = await new Roll(String(rollData.loc.score.min)).roll()
|
||||
} else {
|
||||
locRoll = await new Roll("1d20").roll()
|
||||
await this.showDiceSoNice(locRoll, game.settings.get("core", "rollMode"))
|
||||
for (let key in game.system.tedeum.config.LOCALISATION) {
|
||||
let loc = game.system.tedeum.config.LOCALISATION[key]
|
||||
if (locRoll.total >= loc.score.min && locRoll.total <= loc.score.max) {
|
||||
rollData.loc = foundry.utils.duplicate(loc)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
rollData.locRoll = foundry.utils.duplicate(locRoll)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async processAttaqueMelee(rollData) {
|
||||
await this.getLocalisation(rollData)
|
||||
let actor = game.actors.get(rollData.actorId)
|
||||
let bDegats = actor.getAttaqueBonusDegats(rollData)
|
||||
rollData.degatsFormula = rollData.arme.system.degats + "+" + bDegats
|
||||
let degatsRoll = await new Roll(rollData.degatsFormula).roll()
|
||||
await this.showDiceSoNice(degatsRoll, game.settings.get("core", "rollMode"))
|
||||
rollData.degatsRoll = foundry.utils.duplicate(degatsRoll)
|
||||
rollData.degats = degatsRoll.total
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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(rollData.degatsRoll, game.settings.get("core", "rollMode"))
|
||||
rollData.degatsRoll = foundry.utils.duplicate(degatsRoll)
|
||||
rollData.degats = degatsRoll.total
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async manageCombatActions(actor, rollData) {
|
||||
let combat = game.combats.active
|
||||
if (!combat) return;
|
||||
let combatant = combat.getCombatantByActor(actor)
|
||||
if (!combatant) return;
|
||||
let ca = combatant.getFlag("world", "available-actions")
|
||||
if (!ca) return;
|
||||
if (rollData.mode == "arme" && rollData.isMainGauche) {
|
||||
if (ca.nbActionsMainGauche > 0) {
|
||||
ca.nbActionsMainGauche -= 1
|
||||
ca.nbActions = Math.max(ca.nbActions - 1, 0)
|
||||
} else {
|
||||
ui.notifications.error(`${actor.name} n'a plus d'actions disponibles à la main gauche`)
|
||||
}
|
||||
}
|
||||
if (ca.nbActions > 0) {
|
||||
ca.nbActions -= 1
|
||||
} else {
|
||||
ui.notifications.error(`${actor.name} n'a plus d'actions disponibles`)
|
||||
}
|
||||
await combatant.setFlag("world", "available-actions", ca)
|
||||
await combatant.update({ name: `${combatant.token.name} (${ca.nbActions} / ${ca.nbActionsMainGauche})` })
|
||||
rollData.hasActions = true
|
||||
rollData.remainingActions = ca.nbActions
|
||||
rollData.remainingActionsMainGauche = ca.nbActionsMainGauche
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async rollTeDeum(rollData) {
|
||||
|
||||
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
|
||||
|
||||
// Compute the real competence score
|
||||
if (rollData.competence) {
|
||||
if (rollData.isMainGauche) {
|
||||
rollData.competence = actor.getMeilleureCompetenceMainGauche(rollData.competence)
|
||||
}
|
||||
if (rollData.competence.system.isBase) {
|
||||
rollData.compScore = actor.system.caracteristiques[rollData.competence.system.caracteristique].value
|
||||
} else {
|
||||
rollData.compScore = rollData.competence.system.score
|
||||
}
|
||||
}
|
||||
let diceFormula = this.computeRollFormula(rollData, actor)
|
||||
if (!diceFormula) return;
|
||||
console.log("RollData", rollData, diceFormula)
|
||||
|
||||
// Performs roll
|
||||
let myRoll = await new Roll(diceFormula).roll()
|
||||
@@ -391,8 +681,12 @@ export class TeDeumUtility {
|
||||
|
||||
await this.computeResults(rollData)
|
||||
|
||||
await this.processAttaqueDistance(rollData)
|
||||
|
||||
await this.manageCombatActions(actor, rollData)
|
||||
|
||||
let msg = await this.createChatWithRollMode(rollData.alias, {
|
||||
content: await renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-generic-result.hbs`, rollData)
|
||||
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-generic-result.hbs`, rollData)
|
||||
})
|
||||
await msg.setFlag("world", "te-deum-rolldata", rollData)
|
||||
console.log("Rolldata result", rollData)
|
||||
@@ -401,10 +695,6 @@ export class TeDeumUtility {
|
||||
if (rollData.enableProvidence) {
|
||||
actor.modifyProvidence(-1)
|
||||
}
|
||||
// Manage XP
|
||||
if (rollData.isReussiteCritique || rollData.isEchecCritique) {
|
||||
actor.modifyXP(rollData.carac.key, 1)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -471,7 +761,7 @@ export class TeDeumUtility {
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async createChatMessage(name, rollMode, chatOptions) {
|
||||
switch (rollMode) {
|
||||
@@ -493,15 +783,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
|
||||
|
@@ -1,17 +1,17 @@
|
||||
export class TeDeumArmeSchema extends foundry.abstract.TypeDataModel {
|
||||
export class TeDeumArmeSchema extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
const requiredInteger = { required: true, nullable: false, integer: true };
|
||||
const requiredDouble = { required: true, nullable: false, integer: false };
|
||||
const schema = {};
|
||||
|
||||
schema.typeArme = new fields.StringField({required: true, choices: ["melee", "tir"], initial: "melee"});
|
||||
schema.allonge = new fields.StringField({required: true, choices: ["courte", "moyenne", "longue", "treslongue"], initial: "courte"});
|
||||
schema.typeArme = new fields.StringField({ required: true, choices: ["melee", "tir"], initial: "melee" });
|
||||
schema.allonge = new fields.StringField({ required: true, choices: ["courte", "moyenne", "longue", "treslongue"], initial: "courte" });
|
||||
|
||||
schema.specificites = new fields.SchemaField(
|
||||
Object.values((game.system.tedeum.config.ARME_SPECIFICITE)).reduce((obj, spec) => {
|
||||
obj[spec.id] = new fields.SchemaField({
|
||||
hasSpec: new fields.BooleanField({initial: false}),
|
||||
hasSpec: new fields.BooleanField({ initial: false }),
|
||||
});
|
||||
return obj;
|
||||
}, {})
|
||||
@@ -26,30 +26,35 @@ export class TeDeumArmeSchema extends foundry.abstract.TypeDataModel {
|
||||
}, {})
|
||||
);
|
||||
|
||||
schema.degatsArmure = new fields.SchemaField( {
|
||||
sansarmure : new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
cuir : new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
plates : new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
mailles : new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
schema.degatsArmure = new fields.SchemaField({
|
||||
sansarmure: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
cuir: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
plates: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
mailles: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
});
|
||||
|
||||
|
||||
schema.tempsRecharge = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 });
|
||||
schema.competenceRecharge = new fields.StringField({ required: false, choices: ["aucune", "archerie", "arquebusade"], initial: "aucune", blank: true });
|
||||
schema.valeurEchecCritique = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 });
|
||||
|
||||
schema.initiativeBonus = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 });
|
||||
schema.initiativeBonus = new fields.NumberField({ ...requiredInteger, initial: 0 });
|
||||
|
||||
schema.degats = new fields.StringField({ required: false, blank: true, initial: "0" });
|
||||
schema.degatscrosse = new fields.StringField({ required: false, blank: true, initial: "0" });
|
||||
|
||||
schema.degats = new fields.StringField({ required: false, blank: true, initial: undefined });
|
||||
let comp = []
|
||||
for (let key of Object.keys(game.system.tedeum.config.armeCompetences)) {
|
||||
comp.push(key);
|
||||
}
|
||||
schema.competence = new fields.StringField({ required: true, choices:comp, initial: "bagarre" });
|
||||
schema.competence2 = new fields.StringField({ required: false, choices:comp, initial: "", blank: true });
|
||||
schema.competence = new fields.StringField({ required: true, choices: comp, initial: "bagarre" });
|
||||
schema.competence2 = new fields.StringField({ required: false, choices: comp, initial: "", blank: true });
|
||||
|
||||
schema.prix = new fields.NumberField({ ...requiredDouble, initial: 0, min: 0 });
|
||||
schema.monnaie = new fields.StringField({ required: true, blank: false, initial: "denier" });
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, blank: true });
|
||||
schema.equipe = new fields.BooleanField({ initial: false }),
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, blank: true });
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
@@ -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 });
|
||||
|
||||
|
15
modules/data/tedeum-schema-blessure.js
Normal file
@@ -0,0 +1,15 @@
|
||||
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.value = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
schema.localisation = new fields.StringField({ required: true, choices: ["piedgauche", "pieddroit", "jambegauche", "jambedroite", "maingauche", "maindroite", "brasgauche", "brasdroit", "tete", "corps"], initial: "corps" });
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, blank: true });
|
||||
|
||||
return schema;
|
||||
}
|
||||
}
|
@@ -14,35 +14,68 @@ export class TeDeumEducationSchema extends foundry.abstract.TypeDataModel {
|
||||
return obj;
|
||||
}, {})
|
||||
);
|
||||
|
||||
schema.genre = new fields.StringField({required: true, initial: "Homme", choices: ["masculin", "mixte", "Homme", "Femme", "Mixte"]});
|
||||
|
||||
schema.nbChoixCarac = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 });
|
||||
schema.caracteristiques = new fields.SchemaField(Array.fromRange(3, 1).reduce((caracs, i) => {
|
||||
caracs[`carac${i}`] = new fields.SchemaField({
|
||||
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(16, 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;
|
||||
}
|
||||
|
@@ -13,4 +13,10 @@ export class TeDeumEquipementSchema extends foundry.abstract.TypeDataModel {
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
get monnaieLabel() {
|
||||
console.log("monnaieLabel", this.monnaie,game.system.tedeum.config.monnaieUnit)
|
||||
return game.system.tedeum.config.monnaieUnit[String(this.monnaie)]?.label;
|
||||
}
|
||||
|
||||
}
|
||||
|
19
modules/data/tedeum-schema-maladie.js
Normal file
@@ -0,0 +1,19 @@
|
||||
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.complications = 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;
|
||||
}
|
||||
}
|
@@ -23,29 +23,37 @@ 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({
|
||||
blessures: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0, max: 20 })
|
||||
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;
|
||||
}, {})
|
||||
);
|
||||
|
||||
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 })
|
||||
"deniers": new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
});
|
||||
|
||||
schema.description = new fields.HTMLField({required: true, blank: true});
|
||||
schema.notes = new fields.HTMLField({required: true, blank: true});
|
||||
schema.connaissances = new fields.HTMLField({required: true, blank: true});
|
||||
schema.histoire = new fields.HTMLField({required: true, blank: true});
|
||||
schema.vetements = new fields.HTMLField({required: true, blank: true});
|
||||
//schema.descriptiongraces = new fields.HTMLField({required: true, blank: true});
|
||||
schema.genre = new fields.StringField({required: true, choices: ["Homme", "Femme"], 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.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: "" });
|
||||
schema.datenaissance = new fields.StringField({ required: false, blank: true, initial: "" });
|
||||
schema.statutocial = new fields.StringField({ required: false, blank: true, initial: "" });
|
||||
schema.chargestitre = new fields.StringField({ required: false, blank: true, initial: "" });
|
||||
schema.charges = new fields.StringField({ required: false, blank: true, initial: "" });
|
||||
schema.religion = new fields.StringField({ required: false, blank: true, initial: "" });
|
||||
schema.lieunaissance = new fields.StringField({ required: false, blank: true, initial: "" });
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
20
modules/data/tedeum-schema-simple.js
Normal 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;
|
||||
}
|
||||
}
|
@@ -60,16 +60,43 @@ export class TeDeumRollDialog extends Dialog {
|
||||
html.find('#bonusMalusPerso').change((event) => {
|
||||
this.rollData.bonusMalusPerso = Number(event.currentTarget.value)
|
||||
})
|
||||
html.find('#roll-allonge').change((event) => {
|
||||
this.rollData.allongeId = event.currentTarget.value
|
||||
})
|
||||
html.find('#roll-main-gauche').change((event) => {
|
||||
this.rollData.isMainGauche = event.currentTarget.checked
|
||||
})
|
||||
html.find('#roll-difficulty').change((event) => {
|
||||
this.rollData.difficulty = String(event.currentTarget.value) || "pardefaut"
|
||||
})
|
||||
html.find('#roll-attaque-ciblee').change((event) => {
|
||||
this.rollData.attaqueCiblee = event.currentTarget.value || "0"
|
||||
})
|
||||
html.find('#roll-bonus-malus').change((event) => {
|
||||
this.rollData.bonusMalus = event.currentTarget.value || "0"
|
||||
})
|
||||
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
|
||||
})
|
||||
html.find('#roll-charge-a-pied').change((event) => {
|
||||
this.rollData.isChargeAPied = event.currentTarget.checked
|
||||
})
|
||||
html.find('#roll-charge-a-cheval').change((event) => {
|
||||
this.rollData.isChargeACheval = event.currentTarget.checked
|
||||
})
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@@ -4,11 +4,11 @@ import { TeDeumUtility } from "../common/tedeum-utility.js";
|
||||
* Extend the basic ItemSheet with some very simple modifications
|
||||
* @extends {ItemSheet}
|
||||
*/
|
||||
export class TeDeumItemSheet extends ItemSheet {
|
||||
export class TeDeumItemSheet extends foundry.appv1.sheets.ItemSheet {
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
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,23 +43,22 @@ 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,
|
||||
owner: this.document.isOwner,
|
||||
description: await TextEditor.enrichHTML(this.object.system.description, { async: true }),
|
||||
notes: await TextEditor.enrichHTML(this.object.system.notes, { async: true }),
|
||||
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.description, { async: true }),
|
||||
notes: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.notes, { async: true }),
|
||||
isGM: game.user.isGM
|
||||
}
|
||||
|
||||
|
||||
if (this.object.type == "education") {
|
||||
TeDeumUtility.prepareEducationContent(formData);
|
||||
}
|
||||
|
||||
this.options.editable = !(this.object.origin == "embeddedItem");
|
||||
console.log("ITEM DATA", formData, this);
|
||||
return formData;
|
||||
}
|
||||
|
||||
@@ -103,7 +102,7 @@ export class TeDeumItemSheet extends ItemSheet {
|
||||
let levelIndex = Number($(ev.currentTarget).parents(".item").data("level-index"))
|
||||
let choiceIndex = Number($(ev.currentTarget).parents(".item").data("choice-index"))
|
||||
let featureId = $(ev.currentTarget).parents(".item").data("feature-id")
|
||||
|
||||
|
||||
let itemData = this.object.system.levels[levelIndex].choices[choiceIndex].features[featureId]
|
||||
|
||||
if (itemData.name != 'None') {
|
||||
@@ -157,7 +156,7 @@ export class TeDeumItemSheet extends ItemSheet {
|
||||
let itemType = li.data("item-type");
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
get template() {
|
||||
|
@@ -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",
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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`);
|
||||
@@ -47,7 +51,7 @@ Hooks.once("init", async function () {
|
||||
// preload handlebars templates
|
||||
TeDeumUtility.preloadHandlebarsTemplates();
|
||||
|
||||
// Set an initiative formula for the system
|
||||
// Set an initiative formula for the system
|
||||
CONFIG.Combat.initiative = {
|
||||
formula: "1d6",
|
||||
decimals: 1
|
||||
@@ -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,37 +75,32 @@ Hooks.once("init", async function () {
|
||||
armure: TeDeumArmureSchema,
|
||||
origine: TeDeumOrigineSchema,
|
||||
education: TeDeumEducationSchema,
|
||||
grace: TeDeumGraceSchema
|
||||
grace: TeDeumGraceSchema,
|
||||
blessure: TeDeumBlessureSchema,
|
||||
maladie: TeDeumMaladieSchema,
|
||||
};
|
||||
|
||||
|
||||
console.log("TeDeum RPG | Ready");
|
||||
|
||||
Actors.unregisterSheet("core", ActorSheet);
|
||||
Actors.registerSheet("fvtt-te-deum", TeDeumActorPJSheet, { types: ["pj"], makeDefault: true });
|
||||
Actors.registerSheet("fvtt-te-deum", TeDeumActorPJSheet, { types: ["pnj"], makeDefault: true });
|
||||
|
||||
Items.unregisterSheet("core", ItemSheet);
|
||||
Items.registerSheet("fvtt-te-deum", TeDeumItemSheet, { makeDefault: true });
|
||||
foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet);
|
||||
foundry.documents.collections.Actors.registerSheet("fvtt-te-deum", TeDeumActorPJSheet, { types: ["pj"], makeDefault: true });
|
||||
foundry.documents.collections.Actors.registerSheet("fvtt-te-deum", TeDeumActorPJSheet, { types: ["pnj"], makeDefault: true });
|
||||
|
||||
TeDeumUtility.init()
|
||||
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet);
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-te-deum", TeDeumItemSheet, { makeDefault: true });
|
||||
|
||||
TeDeumUtility.init()
|
||||
|
||||
TeDeumUtility.installHooks()
|
||||
});
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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 */
|
||||
/* -------------------------------------------- */
|
||||
Hooks.once("ready", function () {
|
||||
|
||||
|
||||
// User warning
|
||||
if (!game.user.isGM && game.user.character == undefined) {
|
||||
ui.notifications.info("Attention ! Aucun personnage relié au joueur !");
|
||||
@@ -110,16 +109,17 @@ Hooks.once("ready", function () {
|
||||
user: game.user._id
|
||||
});
|
||||
}
|
||||
|
||||
import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter=>{
|
||||
|
||||
import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => {
|
||||
console.log("ClassCounter loaded", moduleCounter)
|
||||
moduleCounter.ClassCounter.registerUsageCount()
|
||||
}).catch(err=>
|
||||
}).catch(err =>
|
||||
console.log("No stats available, giving up.")
|
||||
)
|
||||
TeDeumUtility.ready();
|
||||
|
||||
welcomeMessage();
|
||||
TeDeumUtility.importDefaultScene()
|
||||
TeDeumUtility.welcomeMessage();
|
||||
|
||||
})
|
||||
|
||||
@@ -137,4 +137,3 @@ Hooks.on("chatMessage", (html, content, msg) => {
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
BIN
packs/aides/000136.ldb
Normal file
1
packs/aides/CURRENT
Normal file
@@ -0,0 +1 @@
|
||||
MANIFEST-000157
|
7
packs/aides/LOG
Normal file
@@ -0,0 +1,7 @@
|
||||
2025/09/24-15:09:29.187023 7f7d00dfa6c0 Recovering log #155
|
||||
2025/09/24-15:09:29.197297 7f7d00dfa6c0 Delete type=3 #153
|
||||
2025/09/24-15:09:29.197358 7f7d00dfa6c0 Delete type=0 #155
|
||||
2025/09/24-15:11:47.439451 7f7cf9fff6c0 Level-0 table #160: started
|
||||
2025/09/24-15:11:47.439482 7f7cf9fff6c0 Level-0 table #160: 0 bytes OK
|
||||
2025/09/24-15:11:47.446526 7f7cf9fff6c0 Delete type=0 #158
|
||||
2025/09/24-15:11:47.446682 7f7cf9fff6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)
|
7
packs/aides/LOG.old
Normal file
@@ -0,0 +1,7 @@
|
||||
2025/09/24-14:48:23.305998 7f7cfb7fe6c0 Recovering log #151
|
||||
2025/09/24-14:48:23.315978 7f7cfb7fe6c0 Delete type=3 #149
|
||||
2025/09/24-14:48:23.316051 7f7cfb7fe6c0 Delete type=0 #151
|
||||
2025/09/24-15:08:26.608194 7f7cf9fff6c0 Level-0 table #156: started
|
||||
2025/09/24-15:08:26.608240 7f7cf9fff6c0 Level-0 table #156: 0 bytes OK
|
||||
2025/09/24-15:08:26.663875 7f7cf9fff6c0 Delete type=0 #154
|
||||
2025/09/24-15:08:26.664085 7f7cf9fff6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)
|
BIN
packs/aides/MANIFEST-000157
Normal file
0
packs/aides/lost/000049.log
Normal file
0
packs/aides/lost/000056.log
Normal file
0
packs/aides/lost/000063.log
Normal file
0
packs/aides/lost/000130.log
Normal file
BIN
packs/aides/lost/MANIFEST-000047
Normal file
BIN
packs/aides/lost/MANIFEST-000054
Normal file
BIN
packs/aides/lost/MANIFEST-000061
Normal file
BIN
packs/armes/000239.ldb
Normal file
0
packs/armes/000262.log
Normal file
1
packs/armes/CURRENT
Normal file
@@ -0,0 +1 @@
|
||||
MANIFEST-000260
|
0
packs/armes/LOCK
Normal file
7
packs/armes/LOG
Normal file
@@ -0,0 +1,7 @@
|
||||
2025/09/24-15:09:29.097777 7f7cfbfff6c0 Recovering log #258
|
||||
2025/09/24-15:09:29.108008 7f7cfbfff6c0 Delete type=3 #256
|
||||
2025/09/24-15:09:29.108079 7f7cfbfff6c0 Delete type=0 #258
|
||||
2025/09/24-15:11:47.381009 7f7cf9fff6c0 Level-0 table #263: started
|
||||
2025/09/24-15:11:47.381035 7f7cf9fff6c0 Level-0 table #263: 0 bytes OK
|
||||
2025/09/24-15:11:47.387083 7f7cf9fff6c0 Delete type=0 #261
|
||||
2025/09/24-15:11:47.393292 7f7cf9fff6c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)
|
7
packs/armes/LOG.old
Normal file
@@ -0,0 +1,7 @@
|
||||
2025/09/24-14:48:23.211234 7f7cfaffd6c0 Recovering log #254
|
||||
2025/09/24-14:48:23.220782 7f7cfaffd6c0 Delete type=3 #252
|
||||
2025/09/24-14:48:23.220848 7f7cfaffd6c0 Delete type=0 #254
|
||||
2025/09/24-15:08:26.052999 7f7cf9fff6c0 Level-0 table #259: started
|
||||
2025/09/24-15:08:26.053039 7f7cf9fff6c0 Level-0 table #259: 0 bytes OK
|
||||
2025/09/24-15:08:26.114659 7f7cf9fff6c0 Delete type=0 #257
|
||||
2025/09/24-15:08:26.173656 7f7cf9fff6c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)
|
BIN
packs/armes/MANIFEST-000260
Normal file
0
packs/armes/lost/000147.log
Normal file
0
packs/armes/lost/000151.log
Normal file
0
packs/armes/lost/000158.log
Normal file
0
packs/armes/lost/000165.log
Normal file
0
packs/armes/lost/000233.log
Normal file
BIN
packs/armes/lost/MANIFEST-000149
Normal file
BIN
packs/armes/lost/MANIFEST-000156
Normal file
BIN
packs/armes/lost/MANIFEST-000163
Normal file
BIN
packs/armures/000238.ldb
Normal file
0
packs/armures/000261.log
Normal file
1
packs/armures/CURRENT
Normal file
@@ -0,0 +1 @@
|
||||
MANIFEST-000259
|
0
packs/armures/LOCK
Normal file
7
packs/armures/LOG
Normal file
@@ -0,0 +1,7 @@
|
||||
2025/09/24-15:09:29.111050 7f7cfaffd6c0 Recovering log #257
|
||||
2025/09/24-15:09:29.121636 7f7cfaffd6c0 Delete type=3 #255
|
||||
2025/09/24-15:09:29.121696 7f7cfaffd6c0 Delete type=0 #257
|
||||
2025/09/24-15:11:47.374855 7f7cf9fff6c0 Level-0 table #262: started
|
||||
2025/09/24-15:11:47.374881 7f7cf9fff6c0 Level-0 table #262: 0 bytes OK
|
||||
2025/09/24-15:11:47.380908 7f7cf9fff6c0 Delete type=0 #260
|
||||
2025/09/24-15:11:47.393280 7f7cf9fff6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)
|
7
packs/armures/LOG.old
Normal file
@@ -0,0 +1,7 @@
|
||||
2025/09/24-14:48:23.223575 7f7d00dfa6c0 Recovering log #253
|
||||
2025/09/24-14:48:23.234727 7f7d00dfa6c0 Delete type=3 #251
|
||||
2025/09/24-14:48:23.234789 7f7d00dfa6c0 Delete type=0 #253
|
||||
2025/09/24-15:08:26.173817 7f7cf9fff6c0 Level-0 table #258: started
|
||||
2025/09/24-15:08:26.173861 7f7cf9fff6c0 Level-0 table #258: 0 bytes OK
|
||||
2025/09/24-15:08:26.233062 7f7cf9fff6c0 Delete type=0 #256
|
||||
2025/09/24-15:08:26.424194 7f7cf9fff6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)
|
BIN
packs/armures/MANIFEST-000259
Normal file
0
packs/armures/lost/000147.log
Normal file
0
packs/armures/lost/000151.log
Normal file
0
packs/armures/lost/000158.log
Normal file
0
packs/armures/lost/000165.log
Normal file
0
packs/armures/lost/000232.log
Normal file
BIN
packs/armures/lost/MANIFEST-000149
Normal file
BIN
packs/armures/lost/MANIFEST-000156
Normal file
BIN
packs/armures/lost/MANIFEST-000163
Normal file
BIN
packs/competences/000237.ldb
Normal file
0
packs/competences/000260.log
Normal file
@@ -1 +1 @@
|
||||
MANIFEST-000097
|
||||
MANIFEST-000258
|
||||
|