Compare commits
21 Commits
foundryvtt
...
9.5.1
| Author | SHA1 | Date | |
|---|---|---|---|
| df1e0b9952 | |||
| b1e96af421 | |||
| 17d865b60b | |||
| 5f4e0c7ce5 | |||
| 8862698262 | |||
| 047933a610 | |||
| b489f65618 | |||
| 406a535c76 | |||
| 5bc6d0d2f5 | |||
| d557fac83f | |||
| f07ef0b01d | |||
| 301cc830bc | |||
| 786afeab74 | |||
| e0383def30 | |||
| 7dc51444f0 | |||
| 752a6701c0 | |||
| 0e8237c233 | |||
| df26a699a0 | |||
| 0a1fa37e49 | |||
| 5b7fba4c87 | |||
| d710061eeb |
89
.gitea/workflows/release.yaml
Normal file
89
.gitea/workflows/release.yaml
Normal file
@@ -0,0 +1,89 @@
|
||||
name: Release Creation
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo "💡 The ${{ gitea.repository }} repository will be cloned to the runner."
|
||||
|
||||
- uses: RouxAntoine/checkout@v3.5.4
|
||||
|
||||
# Valider les JSON avant de packager
|
||||
- name: Valider fr.json et module.json
|
||||
run: |
|
||||
python3 -mjson.tool fr.json > /dev/null
|
||||
python3 -mjson.tool module.json > /dev/null
|
||||
|
||||
# Générer modules/loadScripts.js depuis scripts/
|
||||
- name: Build (génération de loadScripts.js)
|
||||
run: node scriptPacker.js
|
||||
|
||||
# Extraire le numéro de version depuis le tag (sans le 'v' initial)
|
||||
- name: Extraire la version depuis le tag
|
||||
id: get_version
|
||||
uses: battila7/get-version-action@v2
|
||||
|
||||
# Mettre à jour version, url, manifest et download dans module.json
|
||||
- name: Substituer les URLs de Manifest et Download
|
||||
id: sub_manifest_link_version
|
||||
uses: microsoft/variable-substitution@v1
|
||||
with:
|
||||
files: 'module.json'
|
||||
env:
|
||||
version: ${{ steps.get_version.outputs.version-without-v }}
|
||||
url: https://www.uberwald.me/gitea/${{ gitea.repository }}
|
||||
manifest: https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr/releases/download/latest/module.json
|
||||
download: https://www.uberwald.me/gitea/${{ gitea.repository }}/releases/download/${{ github.event.release.tag_name }}/foundryvtt-wh4-lang-fr-fr.zip
|
||||
|
||||
# Créer le zip avec uniquement les fichiers nécessaires au module Foundry
|
||||
- name: Installer zip
|
||||
run: |
|
||||
apt update -y
|
||||
apt install -y zip
|
||||
|
||||
- name: Créer l'archive foundryvtt-wh4-lang-fr-fr.zip
|
||||
run: >
|
||||
zip -r ./foundryvtt-wh4-lang-fr-fr.zip
|
||||
module.json
|
||||
fr.json
|
||||
wh4_fr.js
|
||||
patch-styles.css
|
||||
README.md
|
||||
LICENSE
|
||||
compendium/
|
||||
modules/
|
||||
packs/
|
||||
icons/
|
||||
images/
|
||||
trade/
|
||||
|
||||
# Publier le zip et le module.json sur la release Gitea
|
||||
- name: setup go
|
||||
uses: https://github.com/actions/setup-go@v4
|
||||
with:
|
||||
go-version: '>=1.20.1'
|
||||
|
||||
- name: Publier les assets sur la release Gitea
|
||||
id: use-go-action
|
||||
uses: https://gitea.com/actions/release-action@main
|
||||
with:
|
||||
files: |-
|
||||
./foundryvtt-wh4-lang-fr-fr.zip
|
||||
module.json
|
||||
api_key: '${{ secrets.ALLOW_PUSH_RELEASE }}'
|
||||
|
||||
# Déclarer la release sur le portail FoundryVTT
|
||||
- name: Publier sur FoundryVTT
|
||||
uses: https://github.com/djlechuck/foundryvtt-publish-package-action@v1
|
||||
with:
|
||||
token: ${{ secrets.FOUNDRYVTT_RELEASE_TOKEN }}
|
||||
id: 'wh4-fr-translation'
|
||||
version: ${{ github.event.release.tag_name }}
|
||||
manifest: 'https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr/releases/download/latest/module.json'
|
||||
notes: 'https://www.uberwald.me/gitea/${{ gitea.repository }}/releases/tag/${{ github.event.release.tag_name }}'
|
||||
compatibility-minimum: '13'
|
||||
compatibility-verified: '13'
|
||||
19
.gitea/workflows/validate.yaml
Normal file
19
.gitea/workflows/validate.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Validation JSON
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: RouxAntoine/checkout@v3.5.4
|
||||
|
||||
- name: Valider fr.json
|
||||
run: python3 -mjson.tool fr.json > /dev/null
|
||||
|
||||
- name: Valider module.json
|
||||
run: python3 -mjson.tool module.json > /dev/null
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
.history/
|
||||
.idea/
|
||||
.github/
|
||||
@@ -1,29 +0,0 @@
|
||||
image: python:3-alpine
|
||||
|
||||
before_script:
|
||||
- apk update
|
||||
- apk add zip
|
||||
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
|
||||
test:
|
||||
stage: test
|
||||
script:
|
||||
- python -mjson.tool 'fr.json' > /dev/null
|
||||
- python -mjson.tool 'module.json' > /dev/null
|
||||
|
||||
build:
|
||||
stage: build
|
||||
script:
|
||||
- zip wh4-fr-FR.zip -r *.js *.json *.md compendium lang tables -x ".*"
|
||||
artifacts:
|
||||
name: wh4-fr-FR
|
||||
when: on_success
|
||||
paths:
|
||||
- wh4-fr-FR.zip
|
||||
when: on_success
|
||||
only:
|
||||
- tags
|
||||
- master
|
||||
File diff suppressed because one or more lines are too long
@@ -1354,7 +1354,7 @@
|
||||
"name": "Coude fracassé"
|
||||
},
|
||||
{
|
||||
"description": "<p style=\"text-align: justify:\"Un coup violent sur le haut de la cuisse. Gagnez 1 État @Condition[Hémorragique] et réussissez un Test de <strong>Résistance Accessible (+20)</strong> sous peine de trébucher et de gagner l’État @Condition[A Terre]{À Terre}.</p>",
|
||||
"description": "<p style=\"text-align: justify:\"Un coup violent sur le haut de la cuisse. <p>Gagnez 1 État @Condition[Hémorragique] et réussissez un Test de <strong>Résistance Accessible (+20)</strong> sous peine de trébucher et de gagner l’État @Condition[A Terre]{À Terre}.</p>",
|
||||
"id": "Thigh Strike",
|
||||
"name": "Coup à la cuisse"
|
||||
},
|
||||
@@ -1631,10 +1631,10 @@
|
||||
{
|
||||
"contraction": "Sur un échec d'un Test de Résistance Facile (+40) après un combat vous ayant opposé à une créature avec le Trait Infecté. Vous pouvez également développer une infection à partir d'une Infection Mineure. L'incubation est instantanée si développée à partir d'autres symptômes",
|
||||
"description": "<p style=\"text-align: justify:\">Les coupures infectées et les égratignures sont monnaie courante, ce qui explique qu’il existe de nombreuses superstitions quant à la meilleure façon de les traiter. Les cataplasmes confectionnés à partir de fumier enveloppé dans des feuilles, la peau de crapaud, ou encore les plumes de colombe sont très répandus, tout comme le fait de frotter la blessure avec de la bonne terre de Sigmar. La plupart des physiciens considèrent ces pratiques comme de pures âneries et vont préférer des remèdes plus scientifiques, comme le mélange de la bile d’un boeuf noir avec trois cuillères de l’urine du patient et une demi-cuillère de sel de mer, mixture ensuite appliquée sur la blessure purulente. Les hurlements qui suivent généralement cette application sont bien la preuve de son efficacité.</p>",
|
||||
"durationUnit": "Jours",
|
||||
"durationUnit": "days",
|
||||
"durationValue": "1d10",
|
||||
"id": "Festering Wound",
|
||||
"incubationUnit": "Jours",
|
||||
"incubationUnit": "days",
|
||||
"incubationValue": "1d10, ou instantanée si développée à partir d’autres symptômes",
|
||||
"name": "Blessure Purulente",
|
||||
"permanent": "",
|
||||
@@ -1643,10 +1643,10 @@
|
||||
{
|
||||
"contraction": "Sur un échec d'un Test d'Endurance Facile (+40) après avoir ingurgité de la matière infectée.",
|
||||
"description": "<p style=\"text-align: justify:\">On raconte que la nourriture des halflings ne peut pas donner de <em>Courante Galopante</em>, une maladie peu râgoutante et malheureusement trop répandue au sein de l'Empire à cause du manque de soins apportés à la préparation de la nourriture. Même si ceux souffrant de « Vengeance des Rumsters » après avoir ingurgité des tourtes bon marché des halflings vendues à Altdorf vous diront le contraire, s'ils peuvent quitter les toilettes assez longtemps...</p>",
|
||||
"durationUnit": "Jours",
|
||||
"durationUnit": "days",
|
||||
"durationValue": "1d10",
|
||||
"id": "Galloping Trots",
|
||||
"incubationUnit": "Heures",
|
||||
"incubationUnit": "hours",
|
||||
"incubationValue": "1d10",
|
||||
"name": "Courante Galopante",
|
||||
"permanent": "",
|
||||
@@ -1655,10 +1655,10 @@
|
||||
{
|
||||
"contraction": "Sur un échec d'un Test de Résistance Accessible (+20) après un combat où vous avez été blessé par des rongeurs (dont les skavens) possédant le Trait Infecté, ou sur un échec d'un Test de Résistance Facile (+40) après qu'une source infectée est entrée en contact avec votre bouche.",
|
||||
"description": "<p style=\"text-align: justify:\">La très redoutée <em>Fièvre du rongeur</em> est transmise, comme son nom l’indique, par des rongeurs infectés et cause des irritations douloureuses et des ulcérations avant que la fièvre ne monte et que le corps ne soit secoué de spasmes. Même si cette maladie est rarement fatale, elle est débilitante et il faut patienter longtemps avant de s’en remettre totalement. C’est pourquoi chacun cherchera à en atténuer les symptômes. Parmi les remèdes les plus connus, il y a, à Altdorf, l’auto-flagellation, réputée soulager toutes les infections cutanées. À Talabheim, on préconise de se recouvrir d’une mixture composée d’un mélange de fromage de chèvre relevé de poivre glacé importé de Kislev. Dans les villes et les cités les plus importantes, la <em>Fièvre du rongeur</em> est également connue sous le nom de <em>Fièvre de la tourte</em>, car il est notoire que, bien souvent, on remplace la viande la plus chère par du rat infecté dans ce genre de mets.</p>",
|
||||
"durationUnit": "Jours",
|
||||
"durationUnit": "days",
|
||||
"durationValue": "3d10+10",
|
||||
"id": "Ratte Fever",
|
||||
"incubationUnit": "Jours",
|
||||
"incubationUnit": "days",
|
||||
"incubationValue": "3d10+5",
|
||||
"name": "Fièvre du rongeur",
|
||||
"permanent": "",
|
||||
@@ -1667,10 +1667,10 @@
|
||||
{
|
||||
"contraction": "Sur un échec d'un Test d'Endurance Facile (+40) après avoir ingéré de la matière infectée.",
|
||||
"description": "<p style=\"text-align: justify:\">Le <em>Flux sanglant</em> est un problème récurrent au sein de l'Empire et d'une manière générale, est considéré comme une malédiction infligée par les dieux aux impies. Cette maladie infâme oblige la pauvre victime à se vider sans cesse. Le <em>Flux sanglant</em> est endémique au sein des Armées de l'État, où il tue bien plus de soldats que les forces ennemies. Parmi les remèdes les plus fréquents, il y a l'ingurgitation de boudin pour remplacer les humeurs perdues, le « bouchonnage », et le massage des parties avec des substances grasses afin d'atténuer la douleur aigüe.</p>",
|
||||
"durationUnit": "Jours",
|
||||
"durationUnit": "days",
|
||||
"durationValue": "1d10",
|
||||
"id": "The Bloody Flux",
|
||||
"incubationUnit": "Jours",
|
||||
"incubationUnit": "days",
|
||||
"incubationValue": "2d10",
|
||||
"name": "Flux Sanglant",
|
||||
"permanent": "",
|
||||
@@ -1679,10 +1679,10 @@
|
||||
{
|
||||
"contraction": "C'est le développement d'une autre maladie, ou cela intervient après une Blessure critique.",
|
||||
"description": "<p style=\"text-align: justify:\">Votre sang est infecté et votre coeur répand la maladie dans votre corps. Il est possible de vous soigner par l'intermédiaire de saignées, mais certains doktors préfèrent effectuer des incisions à un endroit très précis au niveau du cou pour expulser le sang contaminé et demandent au patient d'ingérer d'énormes quantité de sang sain pour remplacer celui qui a été perdu. Que le patient accepte ou non ce remède, si aucun traitement n'est appliqué l'<em>Infection du sang</em> est mortelle et se concluera par une visite à la Guilde de Thanatopracteurs et du Culte de Morr.</p>",
|
||||
"durationUnit": "Jours",
|
||||
"durationUnit": "days",
|
||||
"durationValue": "1d10",
|
||||
"id": "Blood Rot",
|
||||
"incubationUnit": "Jours",
|
||||
"incubationUnit": "days",
|
||||
"incubationValue": "0",
|
||||
"name": "Infection du Sang",
|
||||
"permanent": "",
|
||||
@@ -1691,10 +1691,10 @@
|
||||
{
|
||||
"contraction": "Sur un échec d'un Test de Résistance Très Facile (+60) après un combat où vous subi une Blessure critique.",
|
||||
"description": "<p style=\"text-align: justify:\">Les <em>Infections mineures</em> - des blessures guérissant lentement, qui n'enflent quasiment pas et ne provoquent pas de fièvre - sont trés répandues. La plupart guérissent d'elles-mêmes, donc peu de personnes s'en soucient réellement avant qu'il ne soit trop tard et que les Portes de Morr ne s'ouvrent.</p>",
|
||||
"durationUnit": "Jours",
|
||||
"durationUnit": "days",
|
||||
"durationValue": "1d10",
|
||||
"id": "Minor Infection",
|
||||
"incubationUnit": "Jours",
|
||||
"incubationUnit": "days",
|
||||
"incubationValue": "1d10",
|
||||
"name": "Infection Mineure",
|
||||
"permanent": "",
|
||||
@@ -1703,10 +1703,10 @@
|
||||
{
|
||||
"contraction": "Effectuer un Test de Résistance Accessible (+20) pour chaque heure entamée passée dans la zone infectée, ou lorsque vous vous retrouvez en présence de fluides infectés.",
|
||||
"description": "<p style=\"text-align: justify:\">Les historiens affirment qu'il y a des siècles de cela, les rats ont déferlé sur l'Empire et que la <em>Peste Noire</em> s'ensuivit, décimant neuf âmes sur dix. Des recrudescences inexpliquées de cette horrible maladie apparaissent encore de nos jours et sont systématiquement accompagnées de la présence des pragmatiques nonnes blanches. Le Culte de Shallya a juré de faire tout ce qui était en son pouvoir pour éradiquer cette terrible maladie, et, en application de droits ancestraux qui lui sont conférés, des cordons sanitaires, délimités par des cordes blanches, sont déployées partout ou l'épidémie surgit, afin d'être certain que personne ne puisse entrer ou sortir de la zone de quarantaine. Et ce, jusqu'à ce que la recrudescence soit maîtrisée et que les corps aient été correctement traités.</p>",
|
||||
"durationUnit": "Jours",
|
||||
"durationUnit": "days",
|
||||
"durationValue": "3d10",
|
||||
"id": "The Black Plague",
|
||||
"incubationUnit": "Minutes",
|
||||
"incubationUnit": "minutes",
|
||||
"incubationValue": "1d10",
|
||||
"name": "Peste Noire",
|
||||
"permanent": "",
|
||||
@@ -1715,10 +1715,10 @@
|
||||
{
|
||||
"contraction": "Sur un échec d'un Test de Résistance Facile (+40) après être entré en contact avec un animal, de la peau, ou des cadavres infectés.",
|
||||
"description": "<p style=\"text-align: justify:\">C'est une maladie très répandue parmi les chasseurs, les fourreurs et les marchands, transmises par les moutons et le bétail, respectivement par la laine et la peau, et par les cadavres de ceux qui sont morts de cette maladie. Elle se manifeste au départ par de légères démangeaisons, trés vite remplacées par des boursufflures roses qui vont se progager sur tout le corps, et particulièrement sur le torse et les bras. Ce n'est pas la forme de vérole la plus grave de l'Empire, mais elle persiste assez longtemps et peut quelquefois s'avérer mortelle.</p>",
|
||||
"durationUnit": "Jours",
|
||||
"durationUnit": "days",
|
||||
"durationValue": "5d10",
|
||||
"id": "Packer's Pox",
|
||||
"incubationUnit": "Jours",
|
||||
"incubationUnit": "days",
|
||||
"incubationValue": "1d10",
|
||||
"name": "Vérole du Tanneur",
|
||||
"permanent": "",
|
||||
@@ -1727,10 +1727,10 @@
|
||||
{
|
||||
"contraction": "Sur un échec d'un Test de Résistance Accessible (+20) lorsque vous touchez une personne infectée ou que vous échouez à ce même Test après qu'un patient contagieux a toussé ou éternué juste à côté de vous (effectue un Test par heure)",
|
||||
"description": "<p style=\"text-align: justify:\">Tous les ans, la plupart des villes et des cités de l'Empire subissent une épidémie de <em>Vérole urticante</em>. La maladie, qui fait apparaître des boursuflures qui démangent sur la quasi-totalité du corps, reste relativement bénigne et ne provoque que très rarement des complications, et n'est donc un réel souci que pour certains patients qui vont s’inquiéter et les nobliaux oisifs. La maladie est tellement répandue qu'on trouve dans la plupart des temples de Shallya des ampoules remplies de pâte blanche qui permettent de soulager les démangeaisons des malades.</p>",
|
||||
"durationUnit": "Jours",
|
||||
"durationUnit": "days",
|
||||
"durationValue": "1d10+7",
|
||||
"id": "Itching Pox",
|
||||
"incubationUnit": "Jours",
|
||||
"incubationUnit": "days",
|
||||
"incubationValue": "1d10",
|
||||
"name": "Vérole Urticante",
|
||||
"permanent": "Vous ne pouvez pas l'attraper une seconde fois, si vous l'avez déjà contractée dans le passé.",
|
||||
|
||||
@@ -69,16 +69,10 @@
|
||||
"converter": "generic_localization"
|
||||
},
|
||||
"durationValue": "system.duration.value",
|
||||
"durationUnit": {
|
||||
"path": "system.duration.unit",
|
||||
"converter": "disease_duration_unit"
|
||||
},
|
||||
"durationUnit": "system.duration.unit",
|
||||
"contraction": "system.contraction.value",
|
||||
"incubationValue": "system.incubation.value",
|
||||
"incubationUnit": {
|
||||
"path": "system.incubation.unit",
|
||||
"converter": "disease_duration_unit"
|
||||
},
|
||||
"incubationUnit": "system.incubation.unit",
|
||||
"symptoms": "system.symptoms.value",
|
||||
"permanent": "system.permanent.value",
|
||||
"special": "system.special.value",
|
||||
|
||||
@@ -78,16 +78,10 @@
|
||||
"converter": "generic_localization"
|
||||
},
|
||||
"durationValue": "system.duration.value",
|
||||
"durationUnit": {
|
||||
"path": "system.duration.unit",
|
||||
"converter": "disease_duration_unit"
|
||||
},
|
||||
"durationUnit": "system.duration.unit",
|
||||
"contraction": "system.contraction.value",
|
||||
"incubationValue": "system.incubation.value",
|
||||
"incubationUnit": {
|
||||
"path": "system.incubation.unit",
|
||||
"converter": "disease_duration_unit"
|
||||
},
|
||||
"incubationUnit": "system.incubation.unit",
|
||||
"symptoms": "system.symptoms.value",
|
||||
"permanent": "system.permanent.value",
|
||||
"special": "system.special.value",
|
||||
|
||||
@@ -70,16 +70,10 @@
|
||||
"converter": "generic_localization"
|
||||
},
|
||||
"durationValue": "system.duration.value",
|
||||
"durationUnit": {
|
||||
"path": "system.duration.unit",
|
||||
"converter": "disease_duration_unit"
|
||||
},
|
||||
"durationUnit": "system.duration.unit",
|
||||
"contraction": "system.contraction.value",
|
||||
"incubationValue": "system.incubation.value",
|
||||
"incubationUnit": {
|
||||
"path": "system.incubation.unit",
|
||||
"converter": "disease_duration_unit"
|
||||
},
|
||||
"incubationUnit": "system.incubation.unit",
|
||||
"symptoms": "system.symptoms.value",
|
||||
"permanent": "system.permanent.value",
|
||||
"special": "system.special.value",
|
||||
|
||||
92
find-blessures-variables.cjs
Normal file
92
find-blessures-variables.cjs
Normal file
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Patterns pour détecter les variables JavaScript nommées "Blessures"
|
||||
const patterns = [
|
||||
// Déclarations de variables
|
||||
/\b(let|const|var)\s+Blessures\b/g,
|
||||
// Paramètres de fonction
|
||||
/function\s+\w*\s*\([^)]*\bBlessures\b[^)]*\)/g,
|
||||
// Arrow functions avec paramètres
|
||||
/\(\s*[^)]*\bBlessures\b[^)]*\)\s*=>/g,
|
||||
// Arrow function avec un seul paramètre sans parenthèses
|
||||
/\bBlessures\s*=>/g,
|
||||
// Destructuration d'objets
|
||||
/\{\s*[^}]*\bBlessures\b[^}]*\}\s*=/g,
|
||||
// Destructuration de tableaux
|
||||
/\[\s*[^\]]*\bBlessures\b[^\]]*\]\s*=/g,
|
||||
// Catch clause
|
||||
/catch\s*\(\s*Blessures\s*\)/g,
|
||||
// For...of/in loops
|
||||
/for\s*\(\s*(let|const|var)?\s*Blessures\s+(of|in)\b/g,
|
||||
];
|
||||
|
||||
function findBlessuresInFile(filePath) {
|
||||
const content = fs.readFileSync(filePath, 'utf-8');
|
||||
const lines = content.split('\n');
|
||||
const results = [];
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
patterns.forEach(pattern => {
|
||||
pattern.lastIndex = 0; // Reset regex
|
||||
if (pattern.test(line)) {
|
||||
results.push({
|
||||
line: index + 1,
|
||||
content: line.trim()
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function walkDirectory(dir) {
|
||||
const files = fs.readdirSync(dir);
|
||||
const allResults = {};
|
||||
|
||||
files.forEach(file => {
|
||||
const filePath = path.join(dir, file);
|
||||
const stat = fs.statSync(filePath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
Object.assign(allResults, walkDirectory(filePath));
|
||||
} else if (file.endsWith('.js')) {
|
||||
const results = findBlessuresInFile(filePath);
|
||||
if (results.length > 0) {
|
||||
allResults[filePath] = results;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return allResults;
|
||||
}
|
||||
|
||||
// Main
|
||||
const scriptsDir = path.join(__dirname, 'scripts');
|
||||
|
||||
console.log('🔍 Recherche des variables JavaScript nommées "Blessures" dans le répertoire scripts/...\n');
|
||||
|
||||
if (!fs.existsSync(scriptsDir)) {
|
||||
console.error('❌ Le répertoire scripts/ n\'existe pas');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const results = walkDirectory(scriptsDir);
|
||||
|
||||
if (Object.keys(results).length === 0) {
|
||||
console.log('✅ Aucune variable JavaScript nommée "Blessures" trouvée.');
|
||||
} else {
|
||||
console.log(`⚠️ ${Object.keys(results).length} fichier(s) contenant des variables "Blessures" :\n`);
|
||||
|
||||
Object.entries(results).forEach(([filePath, occurrences]) => {
|
||||
const relativePath = path.relative(__dirname, filePath);
|
||||
console.log(`📄 ${relativePath}`);
|
||||
occurrences.forEach(({ line, content }) => {
|
||||
console.log(` Ligne ${line}: ${content}`);
|
||||
});
|
||||
console.log('');
|
||||
});
|
||||
}
|
||||
92
find-tests-variables.cjs
Normal file
92
find-tests-variables.cjs
Normal file
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Patterns pour détecter les variables JavaScript nommées "Tests"
|
||||
const patterns = [
|
||||
// Déclarations de variables
|
||||
/\b(let|const|var)\s+Tests\b/g,
|
||||
// Paramètres de fonction
|
||||
/function\s+\w*\s*\([^)]*\bTests\b[^)]*\)/g,
|
||||
// Arrow functions avec paramètres
|
||||
/\(\s*[^)]*\bTests\b[^)]*\)\s*=>/g,
|
||||
// Arrow function avec un seul paramètre sans parenthèses
|
||||
/\bTests\s*=>/g,
|
||||
// Destructuration d'objets
|
||||
/\{\s*[^}]*\bTests\b[^}]*\}\s*=/g,
|
||||
// Destructuration de tableaux
|
||||
/\[\s*[^\]]*\bTests\b[^\]]*\]\s*=/g,
|
||||
// Catch clause
|
||||
/catch\s*\(\s*Tests\s*\)/g,
|
||||
// For...of/in loops
|
||||
/for\s*\(\s*(let|const|var)?\s*Tests\s+(of|in)\b/g,
|
||||
];
|
||||
|
||||
function findTestsInFile(filePath) {
|
||||
const content = fs.readFileSync(filePath, 'utf-8');
|
||||
const lines = content.split('\n');
|
||||
const results = [];
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
patterns.forEach(pattern => {
|
||||
pattern.lastIndex = 0; // Reset regex
|
||||
if (pattern.test(line)) {
|
||||
results.push({
|
||||
line: index + 1,
|
||||
content: line.trim()
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function walkDirectory(dir) {
|
||||
const files = fs.readdirSync(dir);
|
||||
const allResults = {};
|
||||
|
||||
files.forEach(file => {
|
||||
const filePath = path.join(dir, file);
|
||||
const stat = fs.statSync(filePath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
Object.assign(allResults, walkDirectory(filePath));
|
||||
} else if (file.endsWith('.js')) {
|
||||
const results = findTestsInFile(filePath);
|
||||
if (results.length > 0) {
|
||||
allResults[filePath] = results;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return allResults;
|
||||
}
|
||||
|
||||
// Main
|
||||
const scriptsDir = path.join(__dirname, 'scripts');
|
||||
|
||||
console.log('🔍 Recherche des variables JavaScript nommées "Tests" dans le répertoire scripts/...\n');
|
||||
|
||||
if (!fs.existsSync(scriptsDir)) {
|
||||
console.error('❌ Le répertoire scripts/ n\'existe pas');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const results = walkDirectory(scriptsDir);
|
||||
|
||||
if (Object.keys(results).length === 0) {
|
||||
console.log('✅ Aucune variable JavaScript nommée "Tests" trouvée.');
|
||||
} else {
|
||||
console.log(`⚠️ ${Object.keys(results).length} fichier(s) contenant des variables "Tests" :\n`);
|
||||
|
||||
Object.entries(results).forEach(([filePath, occurrences]) => {
|
||||
const relativePath = path.relative(__dirname, filePath);
|
||||
console.log(`📄 ${relativePath}`);
|
||||
occurrences.forEach(({ line, content }) => {
|
||||
console.log(` Ligne ${line}: ${content}`);
|
||||
});
|
||||
console.log('');
|
||||
});
|
||||
}
|
||||
11
foundryvtt-wh4-lang-fr-fr.code-workspace
Normal file
11
foundryvtt-wh4-lang-fr-fr.code-workspace
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"path": "../WFRP4e-FoundryVTT"
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
}
|
||||
],
|
||||
"url": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr",
|
||||
"version": "9.3.4",
|
||||
"version": "9.4.3",
|
||||
"esmodules": [
|
||||
"wh4_fr.js",
|
||||
"modules/babele-register.js",
|
||||
@@ -119,12 +119,12 @@
|
||||
"folders": []
|
||||
}
|
||||
],
|
||||
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr/raw/v10/module.json",
|
||||
"download": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr/archive/foundryvtt-wh4-lang-fr-9-3-4.zip",
|
||||
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr/releases/download/latest/module.json",
|
||||
"download": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr/releases/download/latest/foundryvtt-wh4-lang-fr-fr.zip",
|
||||
"id": "wh4-fr-translation",
|
||||
"compatibility": {
|
||||
"minimum": "13",
|
||||
"verified": "13"
|
||||
"verified": "14"
|
||||
},
|
||||
"relationships": {
|
||||
"systems": [
|
||||
|
||||
@@ -16,30 +16,27 @@ const _patch_eis = () => {
|
||||
game.wfrp4e.config.symptomTreatment["swelling"] = "La plupart des traitements consistent à plonger la partie affectée, ou parfois tout le corps, dans un bain d'eau glacée pour réduire la chaleur qui accompagne les gonflements. Un <b> Test de Guérison Difficile (-20) étendu </b> nécessitant +3 DR réduit le renflement de <b> <a class ='chat-roll'> 2d10 </a> </b> heures. Chaque test dure une heure. Le patient se retrouve avec l'Etat Exténué +1 pour chaque test effectué au cours du processus. <br> <br> A la place, certains médecins saignent le patient avec une lame ou des sangsues. Un <b>Test de Guérison étendu </b> réussi nécessitant +4 SL et des Outils (médecin) réduit le renflement de (<a class ='chat-roll'> 1d10 </a> + Bonus d'Endurance du patient) heures. Chaque test a une difficulté de base <b> impossible (-50) </b> et dure une demi-heure.";
|
||||
|
||||
game.wfrp4e.config.loreEffects["tzeentch"] = {
|
||||
label: "Domaine de Tzeentch",
|
||||
icon: "modules/wfrp4e-core/icons/spells/tzeentch.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"effectApplication": "apply",
|
||||
"effectTrigger": "oneTime",
|
||||
"lore": true,
|
||||
"script": `
|
||||
if (this.actor.isOwner)
|
||||
args.actor.setupSkill("Résistance", {context : {failure: "1 Point de Corruption reçu", success : "1 Point de Chance gagné"}}).then(setupData => {
|
||||
args.actor.basicTest(setupData).then(test =>
|
||||
{
|
||||
if (test.result.result == "success" && args.actor.type == "character")
|
||||
{
|
||||
args.actor.update({"system.status.fortune.value" : args.actor.system.status.fortune.value + 1})
|
||||
}
|
||||
else if (test.result.result == "failure" && args.actor.type == "character")
|
||||
{
|
||||
args.actor.update({"system.status.corruption.value" : args.actor.system.status.corruption.value + 1})
|
||||
name: "Domaine de Tzeentch",
|
||||
img: "modules/wfrp4e-core/icons/spells/tzeentch.png",
|
||||
system: {
|
||||
transferData: {
|
||||
type: "target"
|
||||
},
|
||||
scriptData: [{
|
||||
trigger: "immediate",
|
||||
label: "Test d'Endurance",
|
||||
script: `
|
||||
this.actor.setupSkill(game.i18n.localize("NAME.Endurance"), {appendTitle : " - " + this.effect.name, context : {failure: "1 Point de Corruption reçu", success : "1 Point de Chance gagné"}}).then(setupData => {
|
||||
this.actor.basicTest(setupData).then(test => {
|
||||
if (test.succeeded && this.actor.type == "character") {
|
||||
this.actor.update({"system.status.fortune.value" : this.actor.system.status.fortune.value + 1})
|
||||
} else if (test.failed && this.actor.type == "character") {
|
||||
this.actor.update({"system.status.corruption.value" : this.actor.system.status.corruption.value + 1})
|
||||
}
|
||||
})
|
||||
})`
|
||||
}
|
||||
})
|
||||
return false;`
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,10 +130,10 @@ const __auto_patch_translation_journal_compendium = async (compmod) => {
|
||||
if (game.user.isGM) {
|
||||
let compData = game.packs.get("WH4-fr-translation.tables-des-traductions");
|
||||
compData.locked = false;
|
||||
let translEntries = await compData.getContent();
|
||||
let translEntries = await compData.getDocuments();
|
||||
for (let entryData of translEntries) {
|
||||
let mydata = foundry.utils.duplicate(entryData.data);
|
||||
mydata.content = mydata.content.replace(/wfrp4e-content/g, compmod);
|
||||
let mydata = entryData.toObject();
|
||||
mydata.text.content = mydata.text.content.replace(/wfrp4e-content/g, compmod);
|
||||
entryData.update(mydata);
|
||||
}
|
||||
compData.locked = true;
|
||||
@@ -175,9 +172,55 @@ const patch_core_tables = (tableList) => {
|
||||
|
||||
/************************************************************************************/
|
||||
const patch_trade_gazeteer = () => {
|
||||
if (game.wfrp4e.config.trade?.gazetteer) {
|
||||
// Translate river cargoTypes to French (DotR module registers English values)
|
||||
if (game.wfrp4e.trade?.tradeData?.river?.cargoTypes) {
|
||||
Object.assign(game.wfrp4e.trade.tradeData.river.cargoTypes, {
|
||||
"grain": game.i18n.localize("TRADE.Grain"),
|
||||
"armaments": game.i18n.localize("TRADE.Armaments"),
|
||||
"luxuries": game.i18n.localize("TRADE.Luxuries"),
|
||||
"metal": game.i18n.localize("TRADE.Metal"),
|
||||
"timber": game.i18n.localize("TRADE.Timber"),
|
||||
"wine": game.i18n.localize("TRADE.Wine"),
|
||||
"brandy": game.i18n.localize("TRADE.Brandy"),
|
||||
"wool": game.i18n.localize("TRADE.Wool"),
|
||||
});
|
||||
}
|
||||
// Translate maritime cargoTypes to French (SOC module)
|
||||
if (game.wfrp4e.trade?.tradeData?.maritime?.cargoTypes) {
|
||||
const maritimeKeys = {
|
||||
"citrusfruit": "TRADE.Citrusfruit",
|
||||
"olives": "TRADE.Olives",
|
||||
"saltfish": "TRADE.Saltfish",
|
||||
"stone": "TRADE.Stone",
|
||||
};
|
||||
for (let [key, locKey] of Object.entries(maritimeKeys)) {
|
||||
if (game.wfrp4e.trade.tradeData.maritime.cargoTypes[key]) {
|
||||
game.wfrp4e.trade.tradeData.maritime.cargoTypes[key] = game.i18n.localize(locKey);
|
||||
}
|
||||
}
|
||||
// Translate shared keys that may also appear in maritime
|
||||
Object.assign(game.wfrp4e.trade.tradeData.maritime.cargoTypes,
|
||||
Object.fromEntries(
|
||||
Object.entries(game.wfrp4e.trade.tradeData.maritime.cargoTypes)
|
||||
.filter(([k]) => game.wfrp4e.trade.tradeData.river?.cargoTypes?.[k])
|
||||
.map(([k]) => [k, game.wfrp4e.trade.tradeData.river.cargoTypes[k]])
|
||||
)
|
||||
);
|
||||
}
|
||||
// Translate season names shown in the trade dialog
|
||||
if (game.wfrp4e.trade?.seasons) {
|
||||
Object.assign(game.wfrp4e.trade.seasons, {
|
||||
"spring": game.i18n.localize("TRADE.Spring"),
|
||||
"summer": game.i18n.localize("TRADE.Summer"),
|
||||
"autumn": game.i18n.localize("TRADE.Autumn"),
|
||||
"winter": game.i18n.localize("TRADE.Winter"),
|
||||
});
|
||||
}
|
||||
// Replace the English DotR gazetteer with the French-translated one
|
||||
// New API: game.wfrp4e.trade.gazetteers.river (replaces old game.wfrp4e.config.trade.gazetteer)
|
||||
if (game.wfrp4e.trade?.gazetteers?.river?.length) {
|
||||
fetch("modules/wh4-fr-translation/trade/gazetteer_dotr.json").then(r => r.json()).then(records => {
|
||||
game.wfrp4e.config.trade.gazetteer = records;
|
||||
game.wfrp4e.trade.gazetteers.river = records;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -231,7 +274,7 @@ const __check_fix_wrong_modules = (chatFlag, patchFinished) => {
|
||||
}
|
||||
} else if (game.user.isGM && patchFinished) {
|
||||
ChatMessage.create({
|
||||
content: "<div>Les modules WFRP4E ont été <strong>patchés avec succés</strong>. Vous pouvez y aller et que <strong>Shallya vous garde !</strong><div><div>Changements v9.3.4 : <ul><li>Ajout de la commande /voyage !</li><li>Améliorations de la commande /auberge</li><li>Très grosses mise à jour des scripts d'Effets et de leur traduction</li></ul></div>",
|
||||
content: "<div>Les modules WFRP4E ont été <strong>patchés avec succés</strong>. Vous pouvez y aller et que <strong>Shallya vous garde !</strong><div><div>Changements v9.3.5 : <ul><li>Ajout de la commande /voyage !</li><li>Améliorations de la commande /auberge</li><li>Les joueurs doivent désormais pouvoir créer leur persos</li><li>Très grosses mise à jour des scripts d'Effets et de leur traduction</li></ul></div>",
|
||||
user: game.user.id,
|
||||
whisper: ChatMessage.getWhisperRecipients("GM")
|
||||
});
|
||||
@@ -358,6 +401,56 @@ Hooks.on('ready', () => {
|
||||
// Patch function for effects
|
||||
game.wfrp4e.utility.findKey = warhammer.utility.findKey
|
||||
|
||||
// Patch SpellModel.computeSpellDamage to handle English characteristic bonus names.
|
||||
// Babele instantiates actors TWICE: first with untranslated data (English formulas like
|
||||
// "Willpower Bonus+4"), then with translated data. The first pass fails because
|
||||
// characteristicsBonus values are already French ("Bonus de Force Mentale").
|
||||
// This patch pre-replaces English bonus names with numeric values before the original
|
||||
// formula evaluation runs, preventing SyntaxErrors and notification spam.
|
||||
const __EN_BONUS_TO_CHAR = {
|
||||
"weapon skill bonus": "ws", "ballistic skill bonus": "bs",
|
||||
"strength bonus": "s", "toughness bonus": "t",
|
||||
"initiative bonus": "i", "agility bonus": "ag",
|
||||
"dexterity bonus": "dex", "intelligence bonus": "int",
|
||||
"willpower bonus": "wp", "fellowship bonus": "fel"
|
||||
};
|
||||
const SpellModel = CONFIG.Item.dataModels?.["spell"];
|
||||
if (SpellModel?.prototype?.computeSpellDamage) {
|
||||
const _origComputeSpellDamage = SpellModel.prototype.computeSpellDamage;
|
||||
SpellModel.prototype.computeSpellDamage = function(formula, options) {
|
||||
if (typeof formula === "string") {
|
||||
const actor = options?.actor || this.parent?.actor;
|
||||
if (actor?.system?.characteristics) {
|
||||
let f = formula.toLowerCase();
|
||||
for (const [enName, ch] of Object.entries(__EN_BONUS_TO_CHAR)) {
|
||||
if (f.includes(enName)) {
|
||||
const bonus = actor.system.characteristics[ch]?.bonus ?? 0;
|
||||
f = f.replace(enName, bonus);
|
||||
}
|
||||
}
|
||||
formula = f;
|
||||
}
|
||||
}
|
||||
return _origComputeSpellDamage.call(this, formula, options);
|
||||
};
|
||||
}
|
||||
|
||||
// Patch postSymptom to handle English symptom names in @Symptom[...] links.
|
||||
// After i18nInit, config.symptoms values are French strings (e.g. "Fièvre"), so
|
||||
// findKey("Fever", config.symptoms) fails. We normalize via game.i18n.localize first.
|
||||
const _origPostSymptom = game.wfrp4e.utility.postSymptom.bind(game.wfrp4e.utility);
|
||||
game.wfrp4e.utility.postSymptom = async function(symptom) {
|
||||
const baseName = symptom.split("(")[0].trim();
|
||||
const symkey = warhammer.utility.findKey(baseName, game.wfrp4e.config.symptoms);
|
||||
if (!symkey) {
|
||||
const localizedBase = game.i18n.localize(baseName);
|
||||
if (localizedBase !== baseName) {
|
||||
symptom = symptom.replace(baseName, localizedBase);
|
||||
}
|
||||
}
|
||||
return _origPostSymptom(symptom);
|
||||
};
|
||||
|
||||
/** New modifiers */
|
||||
game.wfrp4e.config.difficultyModifiers = {
|
||||
"veasy": 60,
|
||||
@@ -385,7 +478,9 @@ Hooks.on('ready', () => {
|
||||
"doom": "Maudit (-40)"
|
||||
}
|
||||
|
||||
if (game.user.isGM) {
|
||||
game.wfrp4e.warnDialog.render(true, { focus: true, left: 20, top: 20 });
|
||||
}
|
||||
//setTimeout( __check_fix_wrong_modules, 2000, true, false);
|
||||
setTimeout(__check_fix_wrong_modules, 20000, true, true);
|
||||
setTimeout(__add_actors_translation, 21000, false, true);
|
||||
|
||||
@@ -30,6 +30,20 @@ const __SELECT_BONUS_PREFIX_D = {
|
||||
"agilité": 1
|
||||
}
|
||||
|
||||
// Map English characteristic names (as they appear in spell formulas) to WFRP4e abbreviations
|
||||
const __CHAR_EN_TO_ABBR = {
|
||||
"weapon skill": "ws",
|
||||
"ballistic skill": "bs",
|
||||
"strength": "s",
|
||||
"toughness": "t",
|
||||
"initiative": "i",
|
||||
"agility": "ag",
|
||||
"dexterity": "dex",
|
||||
"intelligence": "int",
|
||||
"willpower": "wp",
|
||||
"fellowship": "fel"
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
export class WFRP4FrTranslation {
|
||||
|
||||
@@ -57,16 +71,23 @@ export class WFRP4FrTranslation {
|
||||
if (value == "You") return "Vous"; // Hop !
|
||||
if (value == "Instant") return "Instantané"; // Hop !
|
||||
let translw = value;
|
||||
let re = /(.*)\s+[Bb]onus\s*(\w*)/i;
|
||||
let re = /(.*)\s+[Bb]onus\s*(.*)/i; // (.*) at end captures modifiers like "+4"
|
||||
let res = re.exec(value);
|
||||
let unit = "";
|
||||
if (res) { // Test "<charac> Bonus <unit>" pattern
|
||||
if (res) { // Test "<charac> Bonus <modifier>" pattern
|
||||
if (res[1]) { // We have char name, then convert it
|
||||
const charEN = res[1].trim().toLowerCase();
|
||||
const abbr = __CHAR_EN_TO_ABBR[charEN];
|
||||
if (abbr && game.wfrp4e?.config?.characteristicsBonus?.[abbr]) {
|
||||
// Use the localized French bonus name from config (already resolved by localizeConfig at i18nInit)
|
||||
translw = game.wfrp4e.config.characteristicsBonus[abbr];
|
||||
} else {
|
||||
translw = game.i18n.localize(res[1].trim());
|
||||
let bonusPrefix = (translw.toLowerCase() in __SELECT_BONUS_PREFIX_D) ? "Bonus d'" : "Bonus de ";
|
||||
translw = bonusPrefix + translw
|
||||
translw = bonusPrefix + translw;
|
||||
}
|
||||
unit = res[2];
|
||||
}
|
||||
unit = res[2]; // may be "+4", "-2", "2", "yards", etc.
|
||||
} else {
|
||||
re = /(\d+) (\w+)/i;
|
||||
res = re.exec(value);
|
||||
@@ -90,6 +111,8 @@ export class WFRP4FrTranslation {
|
||||
if (unit == "Bonus") { // Another weird management
|
||||
console.log("Translating bonus", unit);
|
||||
translw = "Bonus de " + translw;
|
||||
} else if (unit && /^[+\-*\/]/.test(unit)) {
|
||||
translw += unit; // No space before operators like "+4"
|
||||
} else {
|
||||
translw += " " + unit;
|
||||
}
|
||||
@@ -248,16 +271,16 @@ Hooks.once('init', () => {
|
||||
let translw = translItem?.name || undefined
|
||||
if (translw && translw != s1) {
|
||||
let res2 = re.exec(translw);
|
||||
transl = res2[1] + "(" + subword + ")";
|
||||
transl = res2[1].trim() + " (" + subword + ")";
|
||||
} else {
|
||||
s1 = res[1].trim() + " ( )";
|
||||
translItem = game.babele.translate(compData.metadata.id, { name: s1, type: "skill" }, true)
|
||||
translw = translItem?.name || undefined
|
||||
if(translw) {
|
||||
let res2 = re.exec(translw);
|
||||
transl = res2[1] + "(" + subword + ")";
|
||||
transl = res2[1].trim() + " (" + subword + ")";
|
||||
} else {
|
||||
transl = res[1] + " (" + subword + ")";
|
||||
transl = res[1].trim() + " (" + subword + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,8 +301,25 @@ Hooks.once('init', () => {
|
||||
"process_effects": (effectsData, translations, data, tc, tc_translations) => {
|
||||
//console.log("Effects :", effectsData, translations, data, tc, tc_translations)
|
||||
for (let e of effectsData) {
|
||||
// Foundry v13 requires name; migrate legacy data where only label was stored
|
||||
if (e.name == null) e.name = e.label || "";
|
||||
let origName = e.name
|
||||
e.name = tc_translations.name || game.i18n.localize(e.name)
|
||||
// Symptom effects have their own name (Fever, Malaise, etc.) — don't overwrite with the parent item name
|
||||
if (e.flags?.wfrp4e?.symptom) {
|
||||
let symName = e.name;
|
||||
let gravity = "";
|
||||
if (symName.includes("(") && symName.includes(")")) {
|
||||
let re = /(.*) +\((.*)\)/i;
|
||||
let res = re.exec(symName);
|
||||
if (res) {
|
||||
symName = res[1].trim();
|
||||
gravity = " (" + game.i18n.localize(res[2].trim()) + ")";
|
||||
}
|
||||
}
|
||||
e.name = game.i18n.localize(symName) + gravity;
|
||||
} else {
|
||||
e.name = tc_translations.name || game.i18n.localize(e.name) || e.label || ""
|
||||
}
|
||||
if ( e.flags?.wfrp4e?.scriptData) {
|
||||
for (let script of e.flags.wfrp4e.scriptData) {
|
||||
if (script?.label) {
|
||||
@@ -366,7 +406,7 @@ Hooks.once('init', () => {
|
||||
translItem = game.babele.translate(compData.metadata.id, { name: s1 }, true)
|
||||
let translw = translItem?.name || undefined
|
||||
if (translw && translw != s1) {
|
||||
transl = translw + " (" + subword + ")";
|
||||
transl = translw.trim() + " (" + subword + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,10 +436,18 @@ Hooks.once('init', () => {
|
||||
return beast_traits
|
||||
}
|
||||
//console.log("TRANS:", beast_traits)
|
||||
// Normalize: Foundry v13 requires ActiveEffect.name; migrate legacy v12 data
|
||||
for (let trait_en of beast_traits) {
|
||||
if (trait_en.effects) {
|
||||
for (let eff of trait_en.effects) {
|
||||
if (eff.name == null) eff.name = eff.label || "";
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let trait_en of beast_traits) {
|
||||
let special = "";
|
||||
let nbt = "";
|
||||
let name_en = trait_en.name.trim(); // strip \r in some traits name
|
||||
let name_en = trait_en.name.replace(/\r/g, '').trim(); // strip \r (including internal) in some traits name
|
||||
if (!trait_en.name || trait_en.name.length == 0) {
|
||||
console.log("Wrong item name found!!!!")
|
||||
continue
|
||||
@@ -415,17 +463,22 @@ Hooks.once('init', () => {
|
||||
} else if (name_en.includes("(") && name_en.includes(")")) { // Then process specific traits name with (xxxx) inside
|
||||
let re = /(.*) \((.*)\)/i;
|
||||
let res = re.exec(name_en);
|
||||
if (!res) { console.warn("WFRP4E-FR | bestiary_traits: regex failed for trait:", name_en); }
|
||||
else {
|
||||
name_en = res[1]; // Get the root traits name
|
||||
special = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
|
||||
}
|
||||
}
|
||||
let validCompendiums = game.wfrp4e.tags.getPacksWithTag("trait")
|
||||
for (let compData of validCompendiums) {
|
||||
let trait_fr = game.babele.translate(compData.metadata.id, { name: name_en, system:{description:{value: trait_en.system.description.value}} }, true)
|
||||
if (trait_fr?.name && trait_fr?.name != name_en) {
|
||||
trait_fr.name = trait_fr.name || trait_en.name
|
||||
trait_en.name = nbt + trait_fr.name + special;
|
||||
if ( trait_en.system?.description?.value && trait_fr.system?.description?.value) {
|
||||
trait_en.system.description.value = trait_fr.system.description.value;
|
||||
if (trait_en.system?.specification && isNaN(trait_en.system.specification.value)) { // This is a string, so translate it
|
||||
}
|
||||
if (trait_en?.system?.specification && isNaN(trait_en.system.specification?.value)) { // This is a string, so translate it
|
||||
//console.log("Translating : ", trait_en.system.specification.value);
|
||||
trait_en.system.specification.value = game.i18n.localize(trait_en.system.specification.value.trim());
|
||||
}
|
||||
@@ -436,9 +489,12 @@ Hooks.once('init', () => {
|
||||
if (name_en.includes("(") && name_en.includes(")")) { // Then process specific skills name with (xxxx) inside
|
||||
let re = /(.*) +\((.*)\)/i;
|
||||
let res = re.exec(name_en);
|
||||
if (!res) { console.warn("WFRP4E-FR | bestiary_traits: regex failed for skill:", name_en); }
|
||||
else {
|
||||
name_en = res[1].trim(); // Get the root skill name
|
||||
special = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
|
||||
}
|
||||
}
|
||||
let validCompendiums = game.wfrp4e.tags.getPacksWithTag("skill")
|
||||
for (let compData of validCompendiums) {
|
||||
let trait_fr = game.babele.translate(compData.metadata.id, { name: name_en, system:{description:{value: trait_en.system.description.value}} }, true)
|
||||
@@ -482,9 +538,12 @@ Hooks.once('init', () => {
|
||||
if (name_en.includes("(") && name_en.includes(")")) { // Then process specific skills name with (xxxx) inside
|
||||
let re = /(.*) +\((.*)\)/i;
|
||||
let res = re.exec(name_en);
|
||||
if (!res) { console.warn("WFRP4E-FR | bestiary_traits: regex failed for talent:", name_en); }
|
||||
else {
|
||||
name_en = res[1].trim(); // Get the root talent name, no parenthesis this time...
|
||||
special = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
|
||||
}
|
||||
}
|
||||
let validCompendiums = game.wfrp4e.tags.getPacksWithTag("talent")
|
||||
for (let compData of validCompendiums) {
|
||||
if (name_en === "Trapper") {
|
||||
@@ -648,15 +707,15 @@ Hooks.once('init', () => {
|
||||
if (!effects) return;
|
||||
for (const element of effects) {
|
||||
let effect = element;
|
||||
let label = effect.label;
|
||||
let name = effect.name || effect.label;
|
||||
let gravity = "";
|
||||
if (label.includes("(") && label.includes(")")) { // Then process specific skills name with (xxxx) inside
|
||||
if (name.includes("(") && name.includes(")")) {
|
||||
let re = /(.*) +\((.*)\)/i;
|
||||
let res = re.exec(label);
|
||||
label = res[1].trim(); // Get the gravity
|
||||
gravity = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
|
||||
let res = re.exec(name);
|
||||
name = res[1].trim();
|
||||
gravity = " (" + game.i18n.localize(res[2].trim()) + ")";
|
||||
}
|
||||
effect.label = game.i18n.localize(label) + gravity;
|
||||
effect.name = game.i18n.localize(name) + gravity;
|
||||
}
|
||||
},
|
||||
// Auto-translate duration
|
||||
|
||||
@@ -145,6 +145,39 @@ export class WH4FRPatchConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
static patch_symptom_severity() {
|
||||
// The core module's symptomEffects scripts check for English severity terms
|
||||
// ("Moderate", "Severe") in this.effect.name. French disease compendiums use
|
||||
// translated severity ("Modéré(e)", "Grave"), so the checks would fail.
|
||||
// We patch the relevant scriptData to also check for French severity terms.
|
||||
const effects = game.wfrp4e.config.symptomEffects;
|
||||
if (!effects) return;
|
||||
|
||||
// Patch blight: checks Moderate → easy, Severe → average, else → veasy
|
||||
for (const key of ["blight", "gangrene"]) {
|
||||
const effect = effects[key];
|
||||
if (!effect?.system?.scriptData) continue;
|
||||
for (const sd of effect.system.scriptData) {
|
||||
if (sd.script && sd.script.includes('.includes("Moderate")')) {
|
||||
sd.script = sd.script
|
||||
.replace('includes("Moderate")', 'includes("Moderate") || this.effect.name.includes("Modéré")')
|
||||
.replace('includes("Severe")', 'includes("Severe") || this.effect.name.includes("Grave")');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Patch convulsions: checks Moderate → -20, else → -10
|
||||
if (effects.convulsions?.system?.scriptData) {
|
||||
for (const sd of effects.convulsions.system.scriptData) {
|
||||
if (sd.script && sd.script.includes('.includes("Moderate")')) {
|
||||
sd.script = sd.script
|
||||
.replace('includes("Moderate")', 'includes("Moderate") || this.effect.name.includes("Modéré")');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
static fixSpeciesTable() {
|
||||
|
||||
@@ -192,16 +225,15 @@ export class WH4FRPatchConfig {
|
||||
}
|
||||
|
||||
if (game.wfrp4e.config.loreEffects) {
|
||||
game.wfrp4e.config.loreEffects["beasts"].label = "Domaine des Bêtes"
|
||||
game.wfrp4e.config.loreEffects["death"].label = "Domaine de la Mort"
|
||||
game.wfrp4e.config.loreEffects["fire"].label = "Domaine du Feu"
|
||||
game.wfrp4e.config.loreEffects["metal"].label = "Domaine du Métal"
|
||||
game.wfrp4e.config.loreEffects["heavens"].label = "Domaine des Cieux"
|
||||
game.wfrp4e.config.loreEffects["life"].label = "Domaine de la Vie"
|
||||
game.wfrp4e.config.loreEffects["light"].label = "Domaine de la Lumière"
|
||||
game.wfrp4e.config.loreEffects["shadow"].label = "Domaine des Ombres"
|
||||
game.wfrp4e.config.loreEffects["hedgecraft"].label = "Domaine de la Magie de Village"
|
||||
game.wfrp4e.config.loreEffects["hedgecraft"].label = "Domaine de la Sorcellerie"
|
||||
game.wfrp4e.config.loreEffects["beasts"].name = "Domaine des Bêtes"
|
||||
game.wfrp4e.config.loreEffects["death"].name = "Domaine de la Mort"
|
||||
game.wfrp4e.config.loreEffects["fire"].name = "Domaine du Feu"
|
||||
game.wfrp4e.config.loreEffects["metal"].name = "Domaine du Métal"
|
||||
game.wfrp4e.config.loreEffects["heavens"].name = "Domaine des Cieux"
|
||||
game.wfrp4e.config.loreEffects["life"].name = "Domaine de la Vie"
|
||||
game.wfrp4e.config.loreEffects["light"].name = "Domaine de la Lumière"
|
||||
game.wfrp4e.config.loreEffects["shadow"].name = "Domaine des Ombres"
|
||||
game.wfrp4e.config.loreEffects["hedgecraft"].name = "Domaine de la Sorcellerie"
|
||||
}
|
||||
|
||||
if (game.wfrp4e.config.species) {
|
||||
@@ -240,276 +272,10 @@ export class WH4FRPatchConfig {
|
||||
this.patch_career();
|
||||
|
||||
|
||||
game.wfrp4e.config.symptomEffects = {
|
||||
"blight": {
|
||||
label: "Toxine",
|
||||
icon: "modules/wfrp4e-core/icons/diseases/disease.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"effectApplication": "actor",
|
||||
"effectTrigger": "invoke",
|
||||
"symptom": true,
|
||||
"script": `
|
||||
let difficulty = ""
|
||||
if (this.effect.label.includes("Modéré"))
|
||||
difficulty = "easy"
|
||||
else if (this.effect.label.includes("Sévère"))
|
||||
difficulty = "average"
|
||||
else
|
||||
difficulty = "veasy"
|
||||
|
||||
if (args.actor.isOwner)
|
||||
{
|
||||
args.actor.setupSkill("Résistance", {absolute: {difficulty}}).then(setupData => {
|
||||
args.actor.basicTest(setupData).then(test =>
|
||||
{
|
||||
if (test.result.outcome == "failure")
|
||||
args.actor.addCondition("dead")
|
||||
})
|
||||
})
|
||||
}`
|
||||
}
|
||||
}
|
||||
},
|
||||
"buboes": {
|
||||
label: "Bubons",
|
||||
icon: "modules/wfrp4e-core/icons/diseases/disease.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"effectApplication": "actor",
|
||||
"effectTrigger": "prefillDialog",
|
||||
"symptom": true,
|
||||
"script": `
|
||||
let applicableCharacteristics = ["ws", "bs", "s", "fel", "ag", "t", "dex"]
|
||||
if (args.type == "weapon")
|
||||
args.prefillModifiers.modifier -= 10
|
||||
else if (args.type == "characteristic")
|
||||
{
|
||||
if (applicableCharacteristics.includes(args.item))
|
||||
args.prefillModifiers.modifier -= 10
|
||||
}
|
||||
else if (args.type == "skill")
|
||||
{
|
||||
if (applicableCharacteristics.includes(args.item.characteristic.value))
|
||||
args.prefillModifiers.modifier -= 10
|
||||
}
|
||||
`}
|
||||
}
|
||||
},
|
||||
"convulsions": {
|
||||
label: "Convulsions",
|
||||
icon: "modules/wfrp4e-core/icons/diseases/disease.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"effectApplication": "actor",
|
||||
"effectTrigger": "prefillDialog",
|
||||
"symptom": true,
|
||||
"script": `
|
||||
let modifier = 0
|
||||
if (this.effect.label.includes("Modéré"))
|
||||
modifier = -20
|
||||
else
|
||||
modifier = -10
|
||||
|
||||
let applicableCharacteristics = ["ws", "bs", "s", "ag", "t", "dex"]
|
||||
if (args.type == "weapon")
|
||||
args.prefillModifiers.modifier += modifier
|
||||
else if (args.type == "characteristic")
|
||||
{
|
||||
if (applicableCharacteristics.includes(args.item))
|
||||
args.prefillModifiers.modifier += modifier
|
||||
}
|
||||
else if (args.type == "skill")
|
||||
{
|
||||
if (applicableCharacteristics.includes(args.item.characteristic.value))
|
||||
args.prefillModifiers.modifier += modifier
|
||||
}
|
||||
}`
|
||||
}
|
||||
}
|
||||
},
|
||||
"fever": {
|
||||
label: "Fièvre",
|
||||
icon: "modules/wfrp4e-core/icons/diseases/disease.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"effectApplication": "actor",
|
||||
"effectTrigger": "prefillDialog",
|
||||
"symptom": true,
|
||||
"script": `
|
||||
|
||||
let applicableCharacteristics = ["ws", "bs", "s", "fel", "ag", "t", "dex"]
|
||||
|
||||
if (args.type == "weapon")
|
||||
args.prefillModifiers.modifier -= 10
|
||||
else if (args.type == "characteristic")
|
||||
{
|
||||
if (applicableCharacteristics.includes(args.item))
|
||||
args.prefillModifiers.modifier -= 10
|
||||
}
|
||||
else if (args.type == "skill")
|
||||
{
|
||||
if (applicableCharacteristics.includes(args.item.characteristic.value))
|
||||
args.prefillModifiers.modifier -= 10
|
||||
}`,
|
||||
"otherEffects": ["blight", "wounded"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"flux": {
|
||||
label: "Intoxication Alimentaire",
|
||||
icon: "modules/wfrp4e-core/icons/diseases/disease.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"symptom": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"lingering": {
|
||||
label: "Persistant",
|
||||
icon: "modules/wfrp4e-core/icons/diseases/disease.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"symptom": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"coughsAndSneezes": {
|
||||
label: "Toux et éternuements",
|
||||
icon: "modules/wfrp4e-core/icons/diseases/disease.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"symptom": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"gangrene": {
|
||||
label: "Gangrène",
|
||||
icon: "modules/wfrp4e-core/icons/diseases/disease.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"effectApplication": "actor",
|
||||
"effectTrigger": "prefillDialog",
|
||||
"symptom": true,
|
||||
"script": `
|
||||
if (args.type == "characteristic" && args.item == "fel")
|
||||
{
|
||||
if (args.item == "fel")
|
||||
args.prefillModifiers.modifier -= 10
|
||||
}
|
||||
else if (args.type == "skill")
|
||||
{
|
||||
if (args.item.characteristic.value == "fel")
|
||||
args.prefillModifiers.modifier -= 10
|
||||
}
|
||||
}`
|
||||
}
|
||||
}
|
||||
},
|
||||
"malaise": {
|
||||
label: "Malaise",
|
||||
icon: "modules/wfrp4e-core/icons/diseases/disease.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"effectApplication": "actor",
|
||||
"effectTrigger": "prepareData",
|
||||
"symptom": true,
|
||||
"script": `
|
||||
if (game.user.isUniqueGM)
|
||||
{
|
||||
let fatigued = args.actor.hasCondition("fatigued")
|
||||
if (!fatigued)
|
||||
{
|
||||
args.actor.addCondition("fatigued")
|
||||
ui.notifications.notify("Etat Extenué ajouté à " + args.actor.name + ", qui ne peut pas être enlevé tant que le symptôme Malaise est présent.")
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
||||
},
|
||||
"nausea": {
|
||||
label: "Nausée",
|
||||
icon: "modules/wfrp4e-core/icons/diseases/disease.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"effectApplication": "actor",
|
||||
"effectTrigger": "rollTest",
|
||||
"symptom": true,
|
||||
"script": `
|
||||
if (this.actor.isOwner && args.test.result.outcome == "failure")
|
||||
{
|
||||
let applicableCharacteristics = ["ws", "bs", "s", "fel", "ag", "t", "dex"]
|
||||
if (applicableCharacteristics.includes(args.test.result.characteristic))
|
||||
this.actor.addCondition("stunned")
|
||||
else if (args.test.result.skill && applicableCharacteristics.includes(args.test.result.skill.system.characteristic.value))
|
||||
this.actor.addCondition("stunned")
|
||||
else if (args.test.result.weapon)
|
||||
this.actor.addCondition("stunned")
|
||||
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
||||
},
|
||||
"pox": {
|
||||
label: "Démangeaisons",
|
||||
icon: "modules/wfrp4e-core/icons/diseases/disease.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"effectApplication": "actor",
|
||||
"effectTrigger": "prefillDialog",
|
||||
"symptom": true,
|
||||
"script": `
|
||||
|
||||
if (args.type == "characteristic" && args.item == "fel")
|
||||
args.prefillModifiers.modifier -= 10
|
||||
else if (args.type == "skill")
|
||||
{
|
||||
if (args.item.characteristic.value == "fel")
|
||||
args.prefillModifiers.modifier -= 10
|
||||
}
|
||||
}`
|
||||
}
|
||||
}
|
||||
},
|
||||
"wounded": {
|
||||
label: "Blessé",
|
||||
icon: "modules/wfrp4e-core/icons/diseases/disease.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"effectApplication": "actor",
|
||||
"effectTrigger": "invoke",
|
||||
"symptom": true,
|
||||
"script": `
|
||||
if (args.actor.isOwner)
|
||||
{
|
||||
args.actor.setupSkill("Résistance", {absolute: {difficulty : "average"}}).then(setupData => {
|
||||
args.actor.basicTest(setupData).then(test =>
|
||||
{
|
||||
if (test.result.outcome == "failure")
|
||||
fromUuid("Compendium.wfrp4e-core.diseases.kKccDTGzWzSXCBOb").then(disease => {
|
||||
args.actor.createEmbeddedDocuments("Item", [disease.toObject()])
|
||||
})
|
||||
})
|
||||
})
|
||||
}`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Patch symptom severity scripts to support French severity terms
|
||||
// The core module scripts check for "Moderate"/"Severe" in effect.name,
|
||||
// but French disease compendiums use "Modéré(e)"/"Grave" instead.
|
||||
this.patch_symptom_severity();
|
||||
|
||||
game.wfrp4e.config.effectApplication = {
|
||||
"actor": "Acteur",
|
||||
|
||||
@@ -155,7 +155,7 @@ export default class InnRoller {
|
||||
}
|
||||
|
||||
// Extraire les informations du résultat
|
||||
const resultText = rollResult.results[0]?.text || "Résultat inconnu";
|
||||
const resultText = rollResult.results[0]?.name || rollResult.results[0]?.description || "Résultat inconnu";
|
||||
const rollFormula = rollResult.roll?.formula || "1d100";
|
||||
const rollTotal = rollResult.roll?.total || 0;
|
||||
|
||||
@@ -349,7 +349,7 @@ export default class InnRoller {
|
||||
if (rollTable) {
|
||||
try {
|
||||
const roll = await rollTable.draw({ displayChat: false });
|
||||
const resultText = roll.results[0]?.text || "Résultat inconnu";
|
||||
const resultText = roll.results[0]?.name || roll.results[0]?.description || "Résultat inconnu";
|
||||
results.push({
|
||||
category: this.getCategoryName(tableName),
|
||||
name: resultText,
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
MANIFEST-001251
|
||||
MANIFEST-001339
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/01/07-15:05:51.801144 7f93ebfff6c0 Recovering log #1249
|
||||
2026/01/07-15:05:51.812047 7f93ebfff6c0 Delete type=3 #1247
|
||||
2026/01/07-15:05:51.812099 7f93ebfff6c0 Delete type=0 #1249
|
||||
2026/01/07-15:06:45.486999 7f93e9ffb6c0 Level-0 table #1254: started
|
||||
2026/01/07-15:06:45.487020 7f93e9ffb6c0 Level-0 table #1254: 0 bytes OK
|
||||
2026/01/07-15:06:45.493208 7f93e9ffb6c0 Delete type=0 #1252
|
||||
2026/01/07-15:06:45.493509 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!3IgmiprzLB6Lwenc' @ 72057594037927935 : 1 .. '!journal.pages!suuYN87Al1ZZWtQQ.jhgNnhWhrkOpKs1B' @ 0 : 0; will stop at (end)
|
||||
2026/04/13-23:10:07.603169 7fddd97be6c0 Recovering log #1337
|
||||
2026/04/13-23:10:07.613544 7fddd97be6c0 Delete type=3 #1335
|
||||
2026/04/13-23:10:07.613619 7fddd97be6c0 Delete type=0 #1337
|
||||
2026/04/13-23:14:52.439353 7fddca1c26c0 Level-0 table #1342: started
|
||||
2026/04/13-23:14:52.439375 7fddca1c26c0 Level-0 table #1342: 0 bytes OK
|
||||
2026/04/13-23:14:52.447401 7fddca1c26c0 Delete type=0 #1340
|
||||
2026/04/13-23:14:52.447538 7fddca1c26c0 Manual compaction at level-0 from '!journal!3IgmiprzLB6Lwenc' @ 72057594037927935 : 1 .. '!journal.pages!suuYN87Al1ZZWtQQ.jhgNnhWhrkOpKs1B' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/01/07-14:19:22.396531 7f93ebfff6c0 Recovering log #1245
|
||||
2026/01/07-14:19:22.406238 7f93ebfff6c0 Delete type=3 #1243
|
||||
2026/01/07-14:19:22.406300 7f93ebfff6c0 Delete type=0 #1245
|
||||
2026/01/07-15:04:29.638874 7f93e9ffb6c0 Level-0 table #1250: started
|
||||
2026/01/07-15:04:29.638900 7f93e9ffb6c0 Level-0 table #1250: 0 bytes OK
|
||||
2026/01/07-15:04:29.650961 7f93e9ffb6c0 Delete type=0 #1248
|
||||
2026/01/07-15:04:29.667055 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!3IgmiprzLB6Lwenc' @ 72057594037927935 : 1 .. '!journal.pages!suuYN87Al1ZZWtQQ.jhgNnhWhrkOpKs1B' @ 0 : 0; will stop at (end)
|
||||
2026/04/13-23:01:32.388566 7fddd97be6c0 Recovering log #1333
|
||||
2026/04/13-23:01:32.399282 7fddd97be6c0 Delete type=3 #1331
|
||||
2026/04/13-23:01:32.399346 7fddd97be6c0 Delete type=0 #1333
|
||||
2026/04/13-23:07:12.207745 7fddca1c26c0 Level-0 table #1338: started
|
||||
2026/04/13-23:07:12.207766 7fddca1c26c0 Level-0 table #1338: 0 bytes OK
|
||||
2026/04/13-23:07:12.214487 7fddca1c26c0 Delete type=0 #1336
|
||||
2026/04/13-23:07:12.214671 7fddca1c26c0 Manual compaction at level-0 from '!journal!3IgmiprzLB6Lwenc' @ 72057594037927935 : 1 .. '!journal.pages!suuYN87Al1ZZWtQQ.jhgNnhWhrkOpKs1B' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-001253
|
||||
MANIFEST-001341
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/01/07-15:05:51.814570 7f93ea7fc6c0 Recovering log #1251
|
||||
2026/01/07-15:05:51.824155 7f93ea7fc6c0 Delete type=3 #1249
|
||||
2026/01/07-15:05:51.824233 7f93ea7fc6c0 Delete type=0 #1251
|
||||
2026/01/07-15:06:45.493731 7f93e9ffb6c0 Level-0 table #1256: started
|
||||
2026/01/07-15:06:45.493762 7f93e9ffb6c0 Level-0 table #1256: 0 bytes OK
|
||||
2026/01/07-15:06:45.500998 7f93e9ffb6c0 Delete type=0 #1254
|
||||
2026/01/07-15:06:45.529036 7f93e9ffb6c0 Manual compaction at level-0 from '!folders!3uquYH73ttCdoH0I' @ 72057594037927935 : 1 .. '!items!ylFhk7mGZOnAJTUT' @ 0 : 0; will stop at (end)
|
||||
2026/04/13-23:10:07.616013 7fddcbfff6c0 Recovering log #1339
|
||||
2026/04/13-23:10:07.625710 7fddcbfff6c0 Delete type=3 #1337
|
||||
2026/04/13-23:10:07.625777 7fddcbfff6c0 Delete type=0 #1339
|
||||
2026/04/13-23:14:52.426320 7fddca1c26c0 Level-0 table #1344: started
|
||||
2026/04/13-23:14:52.426354 7fddca1c26c0 Level-0 table #1344: 0 bytes OK
|
||||
2026/04/13-23:14:52.432796 7fddca1c26c0 Delete type=0 #1342
|
||||
2026/04/13-23:14:52.447521 7fddca1c26c0 Manual compaction at level-0 from '!folders!3uquYH73ttCdoH0I' @ 72057594037927935 : 1 .. '!items!ylFhk7mGZOnAJTUT' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/01/07-14:19:22.408420 7f93ea7fc6c0 Recovering log #1247
|
||||
2026/01/07-14:19:22.419450 7f93ea7fc6c0 Delete type=3 #1245
|
||||
2026/01/07-14:19:22.419496 7f93ea7fc6c0 Delete type=0 #1247
|
||||
2026/01/07-15:04:29.689520 7f93e9ffb6c0 Level-0 table #1252: started
|
||||
2026/01/07-15:04:29.689548 7f93e9ffb6c0 Level-0 table #1252: 0 bytes OK
|
||||
2026/01/07-15:04:29.701802 7f93e9ffb6c0 Delete type=0 #1250
|
||||
2026/01/07-15:04:29.713438 7f93e9ffb6c0 Manual compaction at level-0 from '!folders!3uquYH73ttCdoH0I' @ 72057594037927935 : 1 .. '!items!ylFhk7mGZOnAJTUT' @ 0 : 0; will stop at (end)
|
||||
2026/04/13-23:01:32.401911 7fddd8fbd6c0 Recovering log #1335
|
||||
2026/04/13-23:01:32.411157 7fddd8fbd6c0 Delete type=3 #1333
|
||||
2026/04/13-23:01:32.411219 7fddd8fbd6c0 Delete type=0 #1335
|
||||
2026/04/13-23:07:12.194188 7fddca1c26c0 Level-0 table #1340: started
|
||||
2026/04/13-23:07:12.194235 7fddca1c26c0 Level-0 table #1340: 0 bytes OK
|
||||
2026/04/13-23:07:12.201298 7fddca1c26c0 Delete type=0 #1338
|
||||
2026/04/13-23:07:12.214646 7fddca1c26c0 Manual compaction at level-0 from '!folders!3uquYH73ttCdoH0I' @ 72057594037927935 : 1 .. '!items!ylFhk7mGZOnAJTUT' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-001251
|
||||
MANIFEST-001339
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/01/07-15:05:51.839318 7f93eaffd6c0 Recovering log #1249
|
||||
2026/01/07-15:05:51.849796 7f93eaffd6c0 Delete type=3 #1247
|
||||
2026/01/07-15:05:51.849857 7f93eaffd6c0 Delete type=0 #1249
|
||||
2026/01/07-15:06:45.501213 7f93e9ffb6c0 Level-0 table #1254: started
|
||||
2026/01/07-15:06:45.501269 7f93e9ffb6c0 Level-0 table #1254: 0 bytes OK
|
||||
2026/01/07-15:06:45.508204 7f93e9ffb6c0 Delete type=0 #1252
|
||||
2026/01/07-15:06:45.529072 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!cZtNgayIw2QFhC9u' @ 72057594037927935 : 1 .. '!journal.pages!cZtNgayIw2QFhC9u.ts265H1XkisLgdow' @ 0 : 0; will stop at (end)
|
||||
2026/04/13-23:10:07.641322 7fddd9fbf6c0 Recovering log #1337
|
||||
2026/04/13-23:10:07.651537 7fddd9fbf6c0 Delete type=3 #1335
|
||||
2026/04/13-23:10:07.651623 7fddd9fbf6c0 Delete type=0 #1337
|
||||
2026/04/13-23:14:52.478583 7fddca1c26c0 Level-0 table #1342: started
|
||||
2026/04/13-23:14:52.478613 7fddca1c26c0 Level-0 table #1342: 0 bytes OK
|
||||
2026/04/13-23:14:52.484781 7fddca1c26c0 Delete type=0 #1340
|
||||
2026/04/13-23:14:52.484989 7fddca1c26c0 Manual compaction at level-0 from '!journal!cZtNgayIw2QFhC9u' @ 72057594037927935 : 1 .. '!journal.pages!cZtNgayIw2QFhC9u.ts265H1XkisLgdow' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/01/07-14:19:22.434524 7f93ea7fc6c0 Recovering log #1245
|
||||
2026/01/07-14:19:22.444128 7f93ea7fc6c0 Delete type=3 #1243
|
||||
2026/01/07-14:19:22.444200 7f93ea7fc6c0 Delete type=0 #1245
|
||||
2026/01/07-15:04:29.701936 7f93e9ffb6c0 Level-0 table #1250: started
|
||||
2026/01/07-15:04:29.701958 7f93e9ffb6c0 Level-0 table #1250: 0 bytes OK
|
||||
2026/01/07-15:04:29.713305 7f93e9ffb6c0 Delete type=0 #1248
|
||||
2026/01/07-15:04:29.713449 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!cZtNgayIw2QFhC9u' @ 72057594037927935 : 1 .. '!journal.pages!cZtNgayIw2QFhC9u.ts265H1XkisLgdow' @ 0 : 0; will stop at (end)
|
||||
2026/04/13-23:01:32.426243 7fddcbfff6c0 Recovering log #1333
|
||||
2026/04/13-23:01:32.436951 7fddcbfff6c0 Delete type=3 #1331
|
||||
2026/04/13-23:01:32.437016 7fddcbfff6c0 Delete type=0 #1333
|
||||
2026/04/13-23:07:12.201427 7fddca1c26c0 Level-0 table #1338: started
|
||||
2026/04/13-23:07:12.201453 7fddca1c26c0 Level-0 table #1338: 0 bytes OK
|
||||
2026/04/13-23:07:12.207634 7fddca1c26c0 Delete type=0 #1336
|
||||
2026/04/13-23:07:12.214659 7fddca1c26c0 Manual compaction at level-0 from '!journal!cZtNgayIw2QFhC9u' @ 72057594037927935 : 1 .. '!journal.pages!cZtNgayIw2QFhC9u.ts265H1XkisLgdow' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
0
packs/dons-de-rhya/001333.log
Normal file
0
packs/dons-de-rhya/001333.log
Normal file
0
packs/dons-de-rhya/001341.log
Normal file
0
packs/dons-de-rhya/001341.log
Normal file
@@ -1 +1 @@
|
||||
MANIFEST-001251
|
||||
MANIFEST-001339
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/01/07-15:05:51.788330 7f93eaffd6c0 Recovering log #1249
|
||||
2026/01/07-15:05:51.798442 7f93eaffd6c0 Delete type=3 #1247
|
||||
2026/01/07-15:05:51.798508 7f93eaffd6c0 Delete type=0 #1249
|
||||
2026/01/07-15:06:45.480176 7f93e9ffb6c0 Level-0 table #1254: started
|
||||
2026/01/07-15:06:45.480197 7f93e9ffb6c0 Level-0 table #1254: 0 bytes OK
|
||||
2026/01/07-15:06:45.486885 7f93e9ffb6c0 Delete type=0 #1252
|
||||
2026/01/07-15:06:45.493497 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!50u8VAjdmovyr0hx' @ 72057594037927935 : 1 .. '!journal.pages!yzw9I0r3hCK7PJnz.sPNCYj2nR3Cp3jHd' @ 0 : 0; will stop at (end)
|
||||
2026/04/13-23:10:07.590923 7fddd8fbd6c0 Recovering log #1337
|
||||
2026/04/13-23:10:07.600770 7fddd8fbd6c0 Delete type=3 #1335
|
||||
2026/04/13-23:10:07.600832 7fddd8fbd6c0 Delete type=0 #1337
|
||||
2026/04/13-23:14:52.419409 7fddca1c26c0 Level-0 table #1342: started
|
||||
2026/04/13-23:14:52.419440 7fddca1c26c0 Level-0 table #1342: 0 bytes OK
|
||||
2026/04/13-23:14:52.426167 7fddca1c26c0 Delete type=0 #1340
|
||||
2026/04/13-23:14:52.447511 7fddca1c26c0 Manual compaction at level-0 from '!journal!50u8VAjdmovyr0hx' @ 72057594037927935 : 1 .. '!journal.pages!yzw9I0r3hCK7PJnz.sPNCYj2nR3Cp3jHd' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/01/07-14:19:22.383713 7f93eb7fe6c0 Recovering log #1245
|
||||
2026/01/07-14:19:22.394171 7f93eb7fe6c0 Delete type=3 #1243
|
||||
2026/01/07-14:19:22.394305 7f93eb7fe6c0 Delete type=0 #1245
|
||||
2026/01/07-15:04:29.651336 7f93e9ffb6c0 Level-0 table #1250: started
|
||||
2026/01/07-15:04:29.651360 7f93e9ffb6c0 Level-0 table #1250: 0 bytes OK
|
||||
2026/01/07-15:04:29.666893 7f93e9ffb6c0 Delete type=0 #1248
|
||||
2026/01/07-15:04:29.667066 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!50u8VAjdmovyr0hx' @ 72057594037927935 : 1 .. '!journal.pages!yzw9I0r3hCK7PJnz.sPNCYj2nR3Cp3jHd' @ 0 : 0; will stop at (end)
|
||||
2026/04/13-23:01:32.376215 7fddcbfff6c0 Recovering log #1333
|
||||
2026/04/13-23:01:32.386265 7fddcbfff6c0 Delete type=3 #1331
|
||||
2026/04/13-23:01:32.386335 7fddcbfff6c0 Delete type=0 #1333
|
||||
2026/04/13-23:07:12.172988 7fddca1c26c0 Level-0 table #1338: started
|
||||
2026/04/13-23:07:12.173015 7fddca1c26c0 Level-0 table #1338: 0 bytes OK
|
||||
2026/04/13-23:07:12.180381 7fddca1c26c0 Delete type=0 #1336
|
||||
2026/04/13-23:07:12.187032 7fddca1c26c0 Manual compaction at level-0 from '!journal!50u8VAjdmovyr0hx' @ 72057594037927935 : 1 .. '!journal.pages!yzw9I0r3hCK7PJnz.sPNCYj2nR3Cp3jHd' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
0
packs/plats-dauberges/001333.log
Normal file
0
packs/plats-dauberges/001333.log
Normal file
0
packs/plats-dauberges/001341.log
Normal file
0
packs/plats-dauberges/001341.log
Normal file
@@ -1 +1 @@
|
||||
MANIFEST-001251
|
||||
MANIFEST-001339
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/01/07-15:05:51.775857 7f93ea7fc6c0 Recovering log #1249
|
||||
2026/01/07-15:05:51.785876 7f93ea7fc6c0 Delete type=3 #1247
|
||||
2026/01/07-15:05:51.785947 7f93ea7fc6c0 Delete type=0 #1249
|
||||
2026/01/07-15:06:45.473201 7f93e9ffb6c0 Level-0 table #1254: started
|
||||
2026/01/07-15:06:45.473242 7f93e9ffb6c0 Level-0 table #1254: 0 bytes OK
|
||||
2026/01/07-15:06:45.480074 7f93e9ffb6c0 Delete type=0 #1252
|
||||
2026/01/07-15:06:45.493481 7f93e9ffb6c0 Manual compaction at level-0 from '!tables!4l60Lxv8cpsyy2Cg' @ 72057594037927935 : 1 .. '!tables.results!tfaYKDZqu7kgZvRG.yvbwKursaixh2dby' @ 0 : 0; will stop at (end)
|
||||
2026/04/13-23:10:07.578503 7fddd9fbf6c0 Recovering log #1337
|
||||
2026/04/13-23:10:07.588788 7fddd9fbf6c0 Delete type=3 #1335
|
||||
2026/04/13-23:10:07.588855 7fddd9fbf6c0 Delete type=0 #1337
|
||||
2026/04/13-23:14:52.432890 7fddca1c26c0 Level-0 table #1342: started
|
||||
2026/04/13-23:14:52.432912 7fddca1c26c0 Level-0 table #1342: 0 bytes OK
|
||||
2026/04/13-23:14:52.439225 7fddca1c26c0 Delete type=0 #1340
|
||||
2026/04/13-23:14:52.447529 7fddca1c26c0 Manual compaction at level-0 from '!tables!4l60Lxv8cpsyy2Cg' @ 72057594037927935 : 1 .. '!tables.results!tfaYKDZqu7kgZvRG.yvbwKursaixh2dby' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/01/07-14:19:22.369653 7f93ebfff6c0 Recovering log #1245
|
||||
2026/01/07-14:19:22.381041 7f93ebfff6c0 Delete type=3 #1243
|
||||
2026/01/07-14:19:22.381133 7f93ebfff6c0 Delete type=0 #1245
|
||||
2026/01/07-15:04:29.629205 7f93e9ffb6c0 Level-0 table #1250: started
|
||||
2026/01/07-15:04:29.629243 7f93e9ffb6c0 Level-0 table #1250: 0 bytes OK
|
||||
2026/01/07-15:04:29.638743 7f93e9ffb6c0 Delete type=0 #1248
|
||||
2026/01/07-15:04:29.667035 7f93e9ffb6c0 Manual compaction at level-0 from '!tables!4l60Lxv8cpsyy2Cg' @ 72057594037927935 : 1 .. '!tables.results!tfaYKDZqu7kgZvRG.yvbwKursaixh2dby' @ 0 : 0; will stop at (end)
|
||||
2026/04/13-23:01:32.363321 7fddd9fbf6c0 Recovering log #1333
|
||||
2026/04/13-23:01:32.373224 7fddd9fbf6c0 Delete type=3 #1331
|
||||
2026/04/13-23:01:32.373285 7fddd9fbf6c0 Delete type=0 #1333
|
||||
2026/04/13-23:07:12.180494 7fddca1c26c0 Level-0 table #1338: started
|
||||
2026/04/13-23:07:12.180514 7fddca1c26c0 Level-0 table #1338: 0 bytes OK
|
||||
2026/04/13-23:07:12.186759 7fddca1c26c0 Delete type=0 #1336
|
||||
2026/04/13-23:07:12.187045 7fddca1c26c0 Manual compaction at level-0 from '!tables!4l60Lxv8cpsyy2Cg' @ 72057594037927935 : 1 .. '!tables.results!tfaYKDZqu7kgZvRG.yvbwKursaixh2dby' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
0
packs/tables-des-traductions/000976.log
Normal file
0
packs/tables-des-traductions/000976.log
Normal file
0
packs/tables-des-traductions/000984.log
Normal file
0
packs/tables-des-traductions/000984.log
Normal file
@@ -1 +1 @@
|
||||
MANIFEST-000894
|
||||
MANIFEST-000982
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/01/07-15:05:51.826614 7f93ebfff6c0 Recovering log #892
|
||||
2026/01/07-15:05:51.837158 7f93ebfff6c0 Delete type=3 #890
|
||||
2026/01/07-15:05:51.837206 7f93ebfff6c0 Delete type=0 #892
|
||||
2026/01/07-15:06:45.521984 7f93e9ffb6c0 Level-0 table #897: started
|
||||
2026/01/07-15:06:45.522031 7f93e9ffb6c0 Level-0 table #897: 0 bytes OK
|
||||
2026/01/07-15:06:45.528836 7f93e9ffb6c0 Delete type=0 #895
|
||||
2026/01/07-15:06:45.529100 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!056ILNNrLiPq3Gi3' @ 72057594037927935 : 1 .. '!journal.pages!yfZxl4I7XAuUF6r3.apXmOlZRmGT4GreB' @ 0 : 0; will stop at (end)
|
||||
2026/04/13-23:10:07.628261 7fddd97be6c0 Recovering log #980
|
||||
2026/04/13-23:10:07.638743 7fddd97be6c0 Delete type=3 #978
|
||||
2026/04/13-23:10:07.638813 7fddd97be6c0 Delete type=0 #980
|
||||
2026/04/13-23:14:52.447639 7fddca1c26c0 Level-0 table #985: started
|
||||
2026/04/13-23:14:52.447658 7fddca1c26c0 Level-0 table #985: 0 bytes OK
|
||||
2026/04/13-23:14:52.454058 7fddca1c26c0 Delete type=0 #983
|
||||
2026/04/13-23:14:52.484949 7fddca1c26c0 Manual compaction at level-0 from '!journal!056ILNNrLiPq3Gi3' @ 72057594037927935 : 1 .. '!journal.pages!yfZxl4I7XAuUF6r3.apXmOlZRmGT4GreB' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/01/07-14:19:22.421981 7f93eb7fe6c0 Recovering log #888
|
||||
2026/01/07-14:19:22.432249 7f93eb7fe6c0 Delete type=3 #886
|
||||
2026/01/07-14:19:22.432317 7f93eb7fe6c0 Delete type=0 #888
|
||||
2026/01/07-15:04:29.679197 7f93e9ffb6c0 Level-0 table #893: started
|
||||
2026/01/07-15:04:29.679221 7f93e9ffb6c0 Level-0 table #893: 0 bytes OK
|
||||
2026/01/07-15:04:29.689398 7f93e9ffb6c0 Delete type=0 #891
|
||||
2026/01/07-15:04:29.713429 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!056ILNNrLiPq3Gi3' @ 72057594037927935 : 1 .. '!journal.pages!yfZxl4I7XAuUF6r3.apXmOlZRmGT4GreB' @ 0 : 0; will stop at (end)
|
||||
2026/04/13-23:01:32.413810 7fddd97be6c0 Recovering log #976
|
||||
2026/04/13-23:01:32.423395 7fddd97be6c0 Delete type=3 #974
|
||||
2026/04/13-23:01:32.423455 7fddd97be6c0 Delete type=0 #976
|
||||
2026/04/13-23:07:12.187249 7fddca1c26c0 Level-0 table #981: started
|
||||
2026/04/13-23:07:12.187284 7fddca1c26c0 Level-0 table #981: 0 bytes OK
|
||||
2026/04/13-23:07:12.194022 7fddca1c26c0 Delete type=0 #979
|
||||
2026/04/13-23:07:12.214628 7fddca1c26c0 Manual compaction at level-0 from '!journal!056ILNNrLiPq3Gi3' @ 72057594037927935 : 1 .. '!journal.pages!yfZxl4I7XAuUF6r3.apXmOlZRmGT4GreB' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
let item = await fromUuid("Compendium.wfrp4e-core.items.weczkAMPlTjX7lqU")
|
||||
this.actor.createEmbeddedDocuments("Item", [item])
|
||||
@@ -1 +0,0 @@
|
||||
return args.item?.system?.isRanged && args.data.targets[0]?.actor?.sizeNum < 3
|
||||
@@ -1,25 +0,0 @@
|
||||
// The imbiber immediately
|
||||
// takes 3 Poisoned Conditions that cannot be resisted at first,
|
||||
await this.actor.addCondition("poisoned", 3)
|
||||
|
||||
// recovers a number of Wounds equal to their Toughness Bonus,
|
||||
await this.actor.modifyWounds(this.actor.system.characteristics.t.bonus)
|
||||
|
||||
// and acquires the Regenerate Creature Trait.
|
||||
const hasRegenerate = this.actor.has("Regenerate")
|
||||
if (hasRegenerate === undefined) {
|
||||
fromUuid("Compendium.wfrp4e-core.items.SfUUdOGjdYpr3KSR").then(trait => {
|
||||
let traitItem = trait.toObject()
|
||||
this.actor.createEmbeddedDocuments("Item", [traitItem], {fromEffect: this.effect.id})
|
||||
})
|
||||
}
|
||||
|
||||
this.script.scriptMessage(`<p><strong>${this.actor.prototypeToken.name}</strong> has
|
||||
<ul>
|
||||
<li>gained 3 Poisoned Conditions that cannot be resisted at first</li>
|
||||
<li>recovered ${this.actor.system.characteristics.t.bonus} Wounds</li>
|
||||
<li>acquired the Regenerate Creature Trait.</li>
|
||||
</ul>
|
||||
It’s up to Ranald if their regenerating can outpace their poisoning.</p>
|
||||
<p>When all Poisoned Conditions are lost, so too is Regenerate.</p>`,
|
||||
{ whisper: ChatMessage.getWhisperRecipients("GM"), blind: true })
|
||||
@@ -1 +0,0 @@
|
||||
this.actor.addCondition("blinded", 3)
|
||||
@@ -1,4 +0,0 @@
|
||||
let item = await fromUuid("Compendium.wfrp4e-core.items.8piWcBKFlQ2J1E3A")
|
||||
let data = item.toObject();
|
||||
data.system.location.key= this.item.system.location.key
|
||||
this.actor.createEmbeddedDocuments("Item", [data])
|
||||
@@ -1,5 +0,0 @@
|
||||
if (!args.flags.quietenedApplied)
|
||||
{
|
||||
args.fields.modifier += 10;
|
||||
args.flags.quietenedApplied = true
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
return !args.options.terror && !args.extendedTest?.flags.wfrp4e?.fear
|
||||
@@ -1,22 +0,0 @@
|
||||
let spells = await warhammer.utility.findAllItems("spell", "Loading Spells")
|
||||
|
||||
let text = (await game.wfrp4e.tables.rollTable("random-caster", {hideDSN: true})).result
|
||||
|
||||
lore = Array.from(text.matchAll(/{(.+?)}/gm))[0][1]
|
||||
|
||||
if (text == "GM's Choice")
|
||||
{
|
||||
return this.script.scriptNotification(text)
|
||||
}
|
||||
|
||||
if (spellsWithLore.length > 0)
|
||||
{
|
||||
let spellsWithLore = spells.filter(i => game.wfrp4e.config.magicLores[i.system.lore.value] == lore)
|
||||
let selectedSpell = spellsWithLore[Math.floor(CONFIG.Dice.randomUniform() * spellsWithLore.length)]
|
||||
this.script.scriptNotification(selectedSpell.name);
|
||||
this.actor.createEmbeddedDocuments("Item", [selectedSpell])
|
||||
}
|
||||
else
|
||||
{
|
||||
ui.notifications.notify(`Could not find ${lore} spell. Try Again`)
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
let item = await fromUuid("Compendium.wfrp4e-core.items.4CMKeDTDrRQZbPIJ")
|
||||
let fixation = (await game.wfrp4e.tables.rollTable("fixations"))
|
||||
let data = item.toObject();
|
||||
data.system.specification.value = fixation.result;
|
||||
this.item.updateSource({name : this.item.name += ` (${fixation.result})`});
|
||||
this.actor.createEmbeddedDocuments("Item", [data], {fromEffect : this.effect.id})
|
||||
@@ -1 +0,0 @@
|
||||
return !["t", "wp"].includes(args.characteristic)
|
||||
@@ -1,18 +0,0 @@
|
||||
let table = game.wfrp4e.tables.findTable("mutatephys");
|
||||
if (!table)
|
||||
{
|
||||
return ui.notifications.error("Mutation table not found, please ensure a table with the `mutatephys` key is imported in the world.")
|
||||
}
|
||||
let result = (await table.roll()).results[0];
|
||||
let uuid = `Compendium.${result.documentCollection}.${result.documentId}`
|
||||
let item = await fromUuid(uuid);
|
||||
|
||||
if (item)
|
||||
{
|
||||
this.script.scriptNotification(`${item.name} added`)
|
||||
this.actor.createEmbeddedDocuments("Item", [item])
|
||||
}
|
||||
else
|
||||
{
|
||||
ui.notifications.error("Item could not be found: " + uuid)
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
let location = this.item.system.location.key;
|
||||
|
||||
if (location)
|
||||
{
|
||||
let dropped = this.item.system.weaponsAtLocation;
|
||||
|
||||
if (dropped.length)
|
||||
{
|
||||
this.script.scriptNotification(`Dropped ${dropped.map(i => i.name).join(", ")}!`)
|
||||
for(let weapon of dropped)
|
||||
{
|
||||
await weapon.system.toggleEquip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let roll = await new Roll("max(1, 1d10 - @system.characteristics.t.bonus)", this.actor).roll()
|
||||
|
||||
roll.toMessage(this.script.getChatData({flavor : `${this.effect.name} (Duration)`}));
|
||||
|
||||
this.effect.updateSource({"duration.rounds" : roll.total})
|
||||
@@ -1,9 +0,0 @@
|
||||
if (args.skill?.name != game.i18n.localize("NAME.Gossip"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
args.data.canReverse = true; // Kind of a kludge here, the talent Tests has a specific condition, but the description simply says "any gossip test can be reversed" so check it here instead of submission
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
if (args.applyAP && args.modifiers.ap.metal)
|
||||
{
|
||||
args.modifiers.ap.ignored += args.modifiers.ap.metal
|
||||
args.modifiers.ap.details.push("<strong>" + this.effect.name + "</strong>: Ignore Metal (" + args.modifiers.ap.metal + ")");
|
||||
args.modifiers.ap.metal = 0
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
let item = await fromUuid("Compendium.wfrp4e-core.items.GbDyBCu8ZjDp6dkj")
|
||||
let data = item.toObject();
|
||||
this.actor.createEmbeddedDocuments("Item", [data], {fromEffect : this.effect.id})
|
||||
@@ -1,10 +0,0 @@
|
||||
let item1 = await fromUuid("Compendium.wfrp4e-core.items.3S4OYOZLauXctmev")
|
||||
let item2 = await fromUuid("Compendium.wfrp4e-core.items.7mCcI3q7hgWcmbBU")
|
||||
|
||||
let data1 = item1.toObject();
|
||||
data1.system.location.key = this.item.system.location.key
|
||||
|
||||
let data2 = item2.toObject();
|
||||
data2.system.location.key = this.item.system.location.key
|
||||
|
||||
this.actor.createEmbeddedDocuments("Item", [data1, data2], {fromEffect: this.effect.id})
|
||||
@@ -1 +0,0 @@
|
||||
args.fields.modifier -= 20;
|
||||
@@ -1,7 +0,0 @@
|
||||
if (!args.flags.strikeToStun)
|
||||
{
|
||||
args.flags.strikeToStun = true
|
||||
args.fields.modifier += 20;
|
||||
args.fields.hitLocation = "head";
|
||||
}
|
||||
args.fields.successBonus++;
|
||||
@@ -1 +0,0 @@
|
||||
return args.options.terror || args.extendedTest?.flags.wfrp4e?.fear
|
||||
@@ -1,6 +0,0 @@
|
||||
let type = this.item.getFlag("wfrp4e", "breath");
|
||||
|
||||
if (["fire", "electricity", "poison"].includes(type))
|
||||
{
|
||||
args.applyAP = false;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
args.fields.modifier -= 20
|
||||
@@ -1,7 +0,0 @@
|
||||
let state = !this.effect.disabled;
|
||||
this.effect.update({"disabled": state});
|
||||
|
||||
if (state)
|
||||
return ui.notifications.info("EFFECT.CreatureBackInWater", {localize: true})
|
||||
|
||||
return ui.notifications.info("EFFECT.CreatureOutOfWater", {localize: true});
|
||||
@@ -1,31 +0,0 @@
|
||||
if (!this.item.name.includes("(") || this.item.system.tests.value.includes("Terrain"))
|
||||
{
|
||||
let tests = this.item.system.tests.value
|
||||
let name = this.item.name
|
||||
|
||||
// If name already specifies, make sure tests value reflects that
|
||||
if (name.includes("("))
|
||||
{
|
||||
let terrain = name.split("(")[1].split(")")[0]
|
||||
tests = tests.replace("the Terrain", terrain)
|
||||
}
|
||||
else // If no sense specified, provide dialog choice
|
||||
{
|
||||
let choice = await ItemDialog.create(ItemDialog.objectToArray({
|
||||
coastal : "Coastal",
|
||||
deserts : "Deserts",
|
||||
marshes : "Marshes",
|
||||
rocky : "Rocky",
|
||||
tundra : "Tundra",
|
||||
woodlands : "Woodlands"
|
||||
}, this.item.img), 1, "Choose Terrain");
|
||||
if (choice[0])
|
||||
{
|
||||
name = `${name.split("(")[0].trim()} (${choice[0].name})`
|
||||
tests = tests.replace("the Terrain", choice[0].name + " Terrain")
|
||||
}
|
||||
}
|
||||
|
||||
this.effect.updateSource({name})
|
||||
this.item.updateSource({name, "system.tests.value" : tests})
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
let characteristics = {
|
||||
"ws" : 5,
|
||||
"bs" : 5,
|
||||
"s" : 5,
|
||||
"t" : 0,
|
||||
"i" : 5,
|
||||
"ag" : 5,
|
||||
"dex" : 5,
|
||||
"int" : 0,
|
||||
"wp" : 5,
|
||||
"fel" : 5
|
||||
}
|
||||
let items = []
|
||||
|
||||
let updateObj = this.actor.toObject();
|
||||
|
||||
let talents = (await Promise.all([game.wfrp4e.tables.rollTable("talents"), game.wfrp4e.tables.rollTable("talents"), game.wfrp4e.tables.rollTable("talents")])).map(i => i.text)
|
||||
|
||||
for (let ch in characteristics)
|
||||
{
|
||||
updateObj.system.characteristics[ch].modifier += characteristics[ch];
|
||||
}
|
||||
|
||||
for (let talent of talents)
|
||||
{
|
||||
let talentItem = await game.wfrp4e.utility.findTalent(talent)
|
||||
if (talentItem)
|
||||
{
|
||||
items.push(talentItem.toObject());
|
||||
}
|
||||
else
|
||||
{
|
||||
ui.notifications.warn(`Could not find ${talent}`, {permanent : true})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await this.actor.update(updateObj)
|
||||
this.actor.createEmbeddedDocuments("Item", items);
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
return args.characteristic != "t"
|
||||
@@ -1 +0,0 @@
|
||||
args.actor.details.move.run += 4
|
||||
@@ -1,2 +0,0 @@
|
||||
await this.actor.addCondition("ablaze", 2)
|
||||
await this.script.scriptMessage(await this.actor.applyBasicDamage(this.effect.sourceTest.result.damage, {suppressMsg: true}))
|
||||
@@ -1 +0,0 @@
|
||||
return args.characteristic != "wp"
|
||||
@@ -1,6 +0,0 @@
|
||||
let test = await this.actor.setupCharacteristic("wp", {skipTargets: true, appendTitle : ` ${this.effect.name}`})
|
||||
await test.roll()
|
||||
if (test.succeeded)
|
||||
{
|
||||
this.effect.delete();
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
args.options.cardsharp = true;
|
||||
@@ -1,5 +0,0 @@
|
||||
if (args.opposedTest.result.hitloc.value == this.item.system.location.key && args.totalWoundLoss > 0)
|
||||
{
|
||||
args.actor.addCondition("bleeding", 2);
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
return ["ws", "bs", "s", "ag", "t", "dex"].includes(args.characteristic)
|
||||
@@ -1,7 +0,0 @@
|
||||
let test = await args.actor.setupCharacteristic("wp", {skipTargets: true, appendTitle : " - " + this.effect.name, context : {failure: "Gained a Stunned Condition"}})
|
||||
await test.roll();
|
||||
if (test.failed)
|
||||
{
|
||||
args.actor.addCondition("stunned")
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
this.actor.status.addArmour(1, {source: this.effect, magical : true})
|
||||
@@ -1 +0,0 @@
|
||||
this.script.scriptNotification(`Cannot enter ${this.effect.name}!`);
|
||||
@@ -1,3 +0,0 @@
|
||||
let healed = parseInt(this.effect.sourceTest.result.SL)
|
||||
this.actor.modifyWounds(healed)
|
||||
this.script.scriptMessage(`Healed ${healed} Wounds`)
|
||||
@@ -1,20 +0,0 @@
|
||||
let damage = this.effect.sourceActor.hasCondition("fatigued") ? 6 : 10;
|
||||
|
||||
let loc = "body"
|
||||
|
||||
let APatLoc = this.actor.system.status.armour[loc];
|
||||
|
||||
let metalAP = APatLoc.layers.reduce((metal, layer) => metal += ((layer.metal && !layer.magical) ? layer.value : 0), 0)
|
||||
|
||||
let APused = Math.max(0, APatLoc.value - metalAP); // remove metal AP at location;
|
||||
|
||||
damage -= (APused + this.actor.system.characteristics.t.bonus)
|
||||
|
||||
let msg = await this.actor.applyBasicDamage(damage, {suppressMsg : true, damageType : game.wfrp4e.config.DAMAGE_TYPE.IGNORE_ALL});
|
||||
msg += ` (ignored ${metalAP} metal AP on ${game.wfrp4e.config.locations[loc]})`
|
||||
this.script.scriptMessage(msg)
|
||||
|
||||
let test = await this.actor.setupSkill("Endurance", {fields : {difficulty : "difficult"}, appendTitle : ` - ${this.effect.name}`});
|
||||
await test.roll();
|
||||
if (test.failed)
|
||||
this.actor.addCondition("stunned");
|
||||
@@ -1 +0,0 @@
|
||||
args.options.ballockKnife = true;
|
||||
@@ -1,2 +0,0 @@
|
||||
if (args.effect.conditionId == "bleeding")
|
||||
args.data.damage -= 1
|
||||
@@ -1,10 +0,0 @@
|
||||
let choice = await ItemDialog.create(ItemDialog.objectToArray(game.wfrp4e.config.locations), 1, "Choose Location");
|
||||
|
||||
let location = choice[0].id;
|
||||
|
||||
let itemTargeted = this.actor.items.get(this.effect.getFlag("wfrp4e", "itemTargets")[0])
|
||||
|
||||
if (itemTargeted)
|
||||
{
|
||||
itemTargeted.update({[`system.APdamage.${location}`] : itemTargeted.system.APdamage[location] + 1})
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
return args.options.reload
|
||||
@@ -1,4 +0,0 @@
|
||||
let item = await fromUuid("Compendium.wfrp4e-core.items.eWPN3CV2Eddwz8aM")
|
||||
let data = item.toObject();
|
||||
data.system.location.value = "Back"
|
||||
this.actor.createEmbeddedDocuments("Item", [data], {fromEffect: this.effect.id})
|
||||
@@ -1 +0,0 @@
|
||||
game.wfrp4e.utility.postCorruptionTest(this.item.system.specification.value, {speaker : {alias: this.actor.prototypeToken.name}})
|
||||
@@ -1 +0,0 @@
|
||||
return args.item?.system.attackType
|
||||
@@ -1 +0,0 @@
|
||||
return !["fel"].includes(args.characteristic)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user