Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 636632063c | |||
| c54a625a42 | |||
| 1f917bfdfd | |||
| ed4aa5aa16 | |||
| 38d88c2f19 |
@@ -0,0 +1,55 @@
|
||||
# AGENTS.md — foundryvtt-wh4-lang-fr-fr
|
||||
|
||||
FoundryVTT WFRP4e French translation module (wh4-fr-translation).
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
npm run build # packs scripts/*.js → modules/loadScripts.js (do NOT edit loadScripts.js manually)
|
||||
python3 -mjson.tool fr.json > /dev/null # validate JSON (CI check)
|
||||
python3 -mjson.tool module.json > /dev/null
|
||||
```
|
||||
|
||||
No test framework exists. Only automated check is JSON validity (`.gitea/workflows/validate.yaml` on every push).
|
||||
|
||||
## Architecture
|
||||
|
||||
- **`fr.json`** (2715 keys) — UI/system flat key→val translations (`WFRP4E.*` namespace)
|
||||
- **`compendium/*.json`** — compendium translations named `{source-module}.{pack-type}.json`; entries keyed by English `id`
|
||||
- **`scripts/*.js`** — ActiveEffect scripts named by Foundry item IDs (GUID-like `a7v422EZcOUUC20X.js`)
|
||||
- **`modules/loadScripts.js`** — **generated** by `npm run build`; never edit directly
|
||||
- **`modules/babele-register.js`** — registers all compendium JSONs with Babele at `init` hook; contains all converter logic
|
||||
- **`modules/addon-register.js`** — patches `game.wfrp4e.config.*` with French strings at `init`/`ready`
|
||||
- **`modules/config-patch.js`** — `WH4FRPatchConfig` class (skill list translation, talent list, NPC details)
|
||||
- **`modules/import-stat-2.js`** — French stat block parser (replaces WFRP4e default)
|
||||
- **`wh4_fr.js`** — entry point, inits `travelv2` and `inn` submodules from `modules/`
|
||||
- **`packs/`** — custom French compendium packs (LevelDB format)
|
||||
- **`patch-styles.css`** — CSS patches
|
||||
|
||||
## Critical conventions
|
||||
|
||||
- **Never use French words as JS variable names** in `scripts/`. `Blessures` and `Tests` shadow WFRP4e internals (the system uses `game.wfrp4e.config.*` lookup based on English names, and `Blessures`/`Tests` as variable names break this). Scan with:
|
||||
```bash
|
||||
node find-blessures-variables.cjs
|
||||
node find-tests-variables.cjs
|
||||
```
|
||||
- Conflicts in the release workflow: `compatibility-verified: '13'` in `.gitea/workflows/release.yaml` but `"verified": "14"` in `module.json`. The CI step overwrites the release yaml's value — but if adding module.json updates, match both.
|
||||
|
||||
## Upstream sync workflow
|
||||
|
||||
When updating to a new WFRP4e release:
|
||||
|
||||
```bash
|
||||
node tools/copy-new-scripts.js --list # count new scripts
|
||||
node tools/copy-new-scripts.js --dry-run # preview
|
||||
node tools/copy-new-scripts.js --copy # copy new scripts
|
||||
node tools/sync-scripts.js # compare scripts with upstream
|
||||
node tools/translate-scripts.js # apply auto-translation passes
|
||||
node tools/check-tests.js # scan for "Tests" in scripts/ content
|
||||
```
|
||||
|
||||
## Release
|
||||
|
||||
Published via Gitea release. The zip includes: `module.json`, `fr.json`, `wh4_fr.js`, `patch-styles.css`, `README.md`, `LICENSE`, `compendium/`, `modules/`, `packs/`, `icons/`, `images/`, `trade/`.
|
||||
|
||||
Detailed architecture reference in `.github/copilot-instructions.md`.
|
||||
@@ -1175,6 +1175,12 @@
|
||||
"CHAT.Dispel": "Dissiper {spell}",
|
||||
"CHAT.DissolutionTable": "Lancer sur la Table de Dissolution du Corps et de l'Esprit pour votre Espèce:<br>@Table[corruption]",
|
||||
"CHAT.InvokePrayer": "Invoquer {prayer}",
|
||||
"CHAT.TestModifiers.MovedThisRound":"Tir lors d'un tour où vous utilisez également votre mouvement",
|
||||
|
||||
"CHAT.ApplyHealing":"Appliquer les soins",
|
||||
"Healing":"Soins",
|
||||
"RestRecoverHealed":"<strong>{actor}</strong> a soigné {amount} Blessures .",
|
||||
|
||||
"Error.SpeciesSkills": "Impossible d'ajouter des compétences pour les races",
|
||||
"Error.SpeciesTalents": "Impossible d'ajouter des talents pour les races",
|
||||
"Error.CriticalWound": "Erreur lors de l'application des blessures",
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
}
|
||||
],
|
||||
"url": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr",
|
||||
"version": "9.4.3",
|
||||
"version": "9.6.0",
|
||||
"esmodules": [
|
||||
"wh4_fr.js",
|
||||
"modules/babele-register.js",
|
||||
|
||||
@@ -274,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.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>",
|
||||
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.6.0 : <ul><li>Très grosse mise à jour des scripts d'Effets et de leur traduction</li></ul></div>",
|
||||
user: game.user.id,
|
||||
whisper: ChatMessage.getWhisperRecipients("GM")
|
||||
});
|
||||
@@ -478,6 +478,79 @@ Hooks.on('ready', () => {
|
||||
"doom": "Maudit (-40)"
|
||||
}
|
||||
|
||||
// Patch handleCorruptionResult to use hardcoded English severity comparisons.
|
||||
// The system compares this.options.corruption against game.i18n.localize() values,
|
||||
// which works in English by coincidence ("minor" === "minor") but breaks in French
|
||||
// ("minor" !== "mineur"). Since corruption severity strings ("minor"/"moderate"/"major")
|
||||
// are internal API constants, not user-facing text, we use hardcoded comparisons.
|
||||
const TestWFRP = game.wfrp4e.rolls.TestWFRP;
|
||||
if (TestWFRP?.prototype?.handleCorruptionResult) {
|
||||
TestWFRP.prototype.handleCorruptionResult = async function () {
|
||||
const strength = this.options.corruption;
|
||||
const failed = this.failed;
|
||||
let corruption = 0;
|
||||
switch (strength) {
|
||||
case "minor":
|
||||
if (failed) corruption++;
|
||||
break;
|
||||
case "moderate":
|
||||
if (failed) corruption += 2;
|
||||
else if (this.result.SL < 2) corruption += 1;
|
||||
break;
|
||||
case "major":
|
||||
if (failed) corruption += 3;
|
||||
else if (this.result.SL < 2) corruption += 2;
|
||||
else if (this.result.SL < 4) corruption += 1;
|
||||
break;
|
||||
}
|
||||
if (this.context.reroll || this.context.fortuneUsedAddSL) {
|
||||
const prevFailed = this.context.previousResult.outcome === "failure";
|
||||
switch (strength) {
|
||||
case "minor":
|
||||
if (prevFailed) corruption--;
|
||||
break;
|
||||
case "moderate":
|
||||
if (prevFailed) corruption -= 2;
|
||||
else if (this.context.previousResult.SL < 2) corruption -= 1;
|
||||
break;
|
||||
case "major":
|
||||
if (prevFailed) corruption -= 3;
|
||||
else if (this.context.previousResult.SL < 2) corruption -= 2;
|
||||
else if (this.context.previousResult.SL < 4) corruption -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let newCorruption = Number(this.actor.system.status.corruption.value) + corruption;
|
||||
if (newCorruption < 0) newCorruption = 0;
|
||||
if (!this.context.reroll && !this.context.fortuneUsedAddSL)
|
||||
ChatMessage.create(game.wfrp4e.utility.chatDataSetup(game.i18n.format("CHAT.CorruptionFail", { name: this.actor.name, number: corruption }), "gmroll", false));
|
||||
else
|
||||
ChatMessage.create(game.wfrp4e.utility.chatDataSetup(game.i18n.format("CHAT.CorruptionReroll", { name: this.actor.name, number: corruption }), "gmroll", false));
|
||||
await this.actor.update({ "system.status.corruption.value": newCorruption });
|
||||
};
|
||||
}
|
||||
|
||||
// Patch _onResist to accept both raw English and localized French corruption severity.
|
||||
// The original validation compares `this.strength` against localized CORRUPTION.* keys,
|
||||
// which fails when the stored strength is an English API value like "minor" vs French "Mineur".
|
||||
const CorruptionMsgModel = CONFIG.ChatMessage.dataModels?.["corruption"];
|
||||
if (CorruptionMsgModel?._onResist) {
|
||||
CorruptionMsgModel._onResist = async function (ev, target) {
|
||||
const strength = this.strength.toLowerCase();
|
||||
const sMap = {
|
||||
"minor": "minor", "moderate": "moderate", "major": "major",
|
||||
[game.i18n.localize("CORRUPTION.Minor").toLowerCase()]: "minor",
|
||||
[game.i18n.localize("CORRUPTION.Moderate").toLowerCase()]: "moderate",
|
||||
[game.i18n.localize("CORRUPTION.Major").toLowerCase()]: "major",
|
||||
};
|
||||
const normalized = sMap[strength];
|
||||
if (!normalized) return ui.notifications.error("ErrorCorruption", { localize: true });
|
||||
const actors = warhammer.utility.targetedOrAssignedActors();
|
||||
if (!actors.length) return ui.notifications.error("ErrorCharAssigned", { localize: true });
|
||||
actors.forEach(a => a.corruptionDialog(normalized, this.skill));
|
||||
};
|
||||
}
|
||||
|
||||
if (game.user.isGM) {
|
||||
game.wfrp4e.warnDialog.render(true, { focus: true, left: 20, top: 20 });
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
MANIFEST-001339
|
||||
MANIFEST-001372
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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)
|
||||
2026/07/23-21:32:46.337262 7fb396ffd6c0 Recovering log #1370
|
||||
2026/07/23-21:32:46.347360 7fb396ffd6c0 Delete type=3 #1368
|
||||
2026/07/23-21:32:46.347448 7fb396ffd6c0 Delete type=0 #1370
|
||||
2026/07/23-21:38:47.750711 7fb394b4f6c0 Level-0 table #1375: started
|
||||
2026/07/23-21:38:47.750736 7fb394b4f6c0 Level-0 table #1375: 0 bytes OK
|
||||
2026/07/23-21:38:47.784333 7fb394b4f6c0 Delete type=0 #1373
|
||||
2026/07/23-21:38:47.834602 7fb394b4f6c0 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/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)
|
||||
2026/07/23-21:30:54.821703 7fb3977fe6c0 Recovering log #1366
|
||||
2026/07/23-21:30:54.880645 7fb3977fe6c0 Delete type=3 #1364
|
||||
2026/07/23-21:30:54.880743 7fb3977fe6c0 Delete type=0 #1366
|
||||
2026/07/23-21:32:07.239111 7fb394b4f6c0 Level-0 table #1371: started
|
||||
2026/07/23-21:32:07.239141 7fb394b4f6c0 Level-0 table #1371: 0 bytes OK
|
||||
2026/07/23-21:32:07.245796 7fb394b4f6c0 Delete type=0 #1369
|
||||
2026/07/23-21:32:07.253300 7fb394b4f6c0 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-001341
|
||||
MANIFEST-001374
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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)
|
||||
2026/07/23-21:32:46.352107 7fb3e4fff6c0 Recovering log #1372
|
||||
2026/07/23-21:32:46.362976 7fb3e4fff6c0 Delete type=3 #1370
|
||||
2026/07/23-21:32:46.363061 7fb3e4fff6c0 Delete type=0 #1372
|
||||
2026/07/23-21:38:47.805575 7fb394b4f6c0 Level-0 table #1377: started
|
||||
2026/07/23-21:38:47.805603 7fb394b4f6c0 Level-0 table #1377: 0 bytes OK
|
||||
2026/07/23-21:38:47.834447 7fb394b4f6c0 Delete type=0 #1375
|
||||
2026/07/23-21:38:47.865254 7fb394b4f6c0 Manual compaction at level-0 from '!folders!3uquYH73ttCdoH0I' @ 72057594037927935 : 1 .. '!items!ylFhk7mGZOnAJTUT' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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)
|
||||
2026/07/23-21:30:54.895642 7fb397fff6c0 Recovering log #1368
|
||||
2026/07/23-21:30:54.946258 7fb397fff6c0 Delete type=3 #1366
|
||||
2026/07/23-21:30:54.946385 7fb397fff6c0 Delete type=0 #1368
|
||||
2026/07/23-21:32:07.253662 7fb394b4f6c0 Level-0 table #1373: started
|
||||
2026/07/23-21:32:07.253706 7fb394b4f6c0 Level-0 table #1373: 0 bytes OK
|
||||
2026/07/23-21:32:07.260031 7fb394b4f6c0 Delete type=0 #1371
|
||||
2026/07/23-21:32:07.292474 7fb394b4f6c0 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-001339
|
||||
MANIFEST-001372
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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)
|
||||
2026/07/23-21:32:46.383400 7fb396ffd6c0 Recovering log #1370
|
||||
2026/07/23-21:32:46.393737 7fb396ffd6c0 Delete type=3 #1368
|
||||
2026/07/23-21:32:46.393827 7fb396ffd6c0 Delete type=0 #1370
|
||||
2026/07/23-21:38:47.834624 7fb394b4f6c0 Level-0 table #1375: started
|
||||
2026/07/23-21:38:47.834644 7fb394b4f6c0 Level-0 table #1375: 0 bytes OK
|
||||
2026/07/23-21:38:47.865104 7fb394b4f6c0 Delete type=0 #1373
|
||||
2026/07/23-21:38:47.935946 7fb394b4f6c0 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/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)
|
||||
2026/07/23-21:30:55.024458 7fb3977fe6c0 Recovering log #1366
|
||||
2026/07/23-21:30:55.079364 7fb3977fe6c0 Delete type=3 #1364
|
||||
2026/07/23-21:30:55.079438 7fb3977fe6c0 Delete type=0 #1366
|
||||
2026/07/23-21:32:07.260189 7fb394b4f6c0 Level-0 table #1371: started
|
||||
2026/07/23-21:32:07.260219 7fb394b4f6c0 Level-0 table #1371: 0 bytes OK
|
||||
2026/07/23-21:32:07.267866 7fb394b4f6c0 Delete type=0 #1369
|
||||
2026/07/23-21:32:07.292502 7fb394b4f6c0 Manual compaction at level-0 from '!journal!cZtNgayIw2QFhC9u' @ 72057594037927935 : 1 .. '!journal.pages!cZtNgayIw2QFhC9u.ts265H1XkisLgdow' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-001339
|
||||
MANIFEST-001372
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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)
|
||||
2026/07/23-21:32:46.321063 7fb3977fe6c0 Recovering log #1370
|
||||
2026/07/23-21:32:46.332477 7fb3977fe6c0 Delete type=3 #1368
|
||||
2026/07/23-21:32:46.332563 7fb3977fe6c0 Delete type=0 #1370
|
||||
2026/07/23-21:38:47.731514 7fb394b4f6c0 Level-0 table #1375: started
|
||||
2026/07/23-21:38:47.731544 7fb394b4f6c0 Level-0 table #1375: 0 bytes OK
|
||||
2026/07/23-21:38:47.750533 7fb394b4f6c0 Delete type=0 #1373
|
||||
2026/07/23-21:38:47.805560 7fb394b4f6c0 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/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)
|
||||
2026/07/23-21:30:54.763392 7fb3e4fff6c0 Recovering log #1366
|
||||
2026/07/23-21:30:54.817497 7fb3e4fff6c0 Delete type=3 #1364
|
||||
2026/07/23-21:30:54.817575 7fb3e4fff6c0 Delete type=0 #1366
|
||||
2026/07/23-21:32:07.232391 7fb394b4f6c0 Level-0 table #1371: started
|
||||
2026/07/23-21:32:07.232438 7fb394b4f6c0 Level-0 table #1371: 0 bytes OK
|
||||
2026/07/23-21:32:07.238943 7fb394b4f6c0 Delete type=0 #1369
|
||||
2026/07/23-21:32:07.253287 7fb394b4f6c0 Manual compaction at level-0 from '!journal!50u8VAjdmovyr0hx' @ 72057594037927935 : 1 .. '!journal.pages!yzw9I0r3hCK7PJnz.sPNCYj2nR3Cp3jHd' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-001339
|
||||
MANIFEST-001372
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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)
|
||||
2026/07/23-21:32:46.304963 7fb3e4fff6c0 Recovering log #1370
|
||||
2026/07/23-21:32:46.316282 7fb3e4fff6c0 Delete type=3 #1368
|
||||
2026/07/23-21:32:46.316381 7fb3e4fff6c0 Delete type=0 #1370
|
||||
2026/07/23-21:38:47.694700 7fb394b4f6c0 Level-0 table #1375: started
|
||||
2026/07/23-21:38:47.694730 7fb394b4f6c0 Level-0 table #1375: 0 bytes OK
|
||||
2026/07/23-21:38:47.731162 7fb394b4f6c0 Delete type=0 #1373
|
||||
2026/07/23-21:38:47.731496 7fb394b4f6c0 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/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)
|
||||
2026/07/23-21:30:54.705033 7fb397fff6c0 Recovering log #1366
|
||||
2026/07/23-21:30:54.759053 7fb397fff6c0 Delete type=3 #1364
|
||||
2026/07/23-21:30:54.759134 7fb397fff6c0 Delete type=0 #1366
|
||||
2026/07/23-21:32:07.212952 7fb394b4f6c0 Level-0 table #1371: started
|
||||
2026/07/23-21:32:07.213006 7fb394b4f6c0 Level-0 table #1371: 0 bytes OK
|
||||
2026/07/23-21:32:07.219722 7fb394b4f6c0 Delete type=0 #1369
|
||||
2026/07/23-21:32:07.220049 7fb394b4f6c0 Manual compaction at level-0 from '!tables!4l60Lxv8cpsyy2Cg' @ 72057594037927935 : 1 .. '!tables.results!tfaYKDZqu7kgZvRG.yvbwKursaixh2dby' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000982
|
||||
MANIFEST-001015
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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)
|
||||
2026/07/23-21:32:46.368053 7fb397fff6c0 Recovering log #1013
|
||||
2026/07/23-21:32:46.379073 7fb397fff6c0 Delete type=3 #1011
|
||||
2026/07/23-21:32:46.379161 7fb397fff6c0 Delete type=0 #1013
|
||||
2026/07/23-21:38:47.784533 7fb394b4f6c0 Level-0 table #1018: started
|
||||
2026/07/23-21:38:47.784566 7fb394b4f6c0 Level-0 table #1018: 0 bytes OK
|
||||
2026/07/23-21:38:47.805371 7fb394b4f6c0 Delete type=0 #1016
|
||||
2026/07/23-21:38:47.834614 7fb394b4f6c0 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/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)
|
||||
2026/07/23-21:30:54.950889 7fb3e4fff6c0 Recovering log #1009
|
||||
2026/07/23-21:30:55.020209 7fb3e4fff6c0 Delete type=3 #1007
|
||||
2026/07/23-21:30:55.020289 7fb3e4fff6c0 Delete type=0 #1009
|
||||
2026/07/23-21:32:07.245955 7fb394b4f6c0 Level-0 table #1014: started
|
||||
2026/07/23-21:32:07.245987 7fb394b4f6c0 Level-0 table #1014: 0 bytes OK
|
||||
2026/07/23-21:32:07.253115 7fb394b4f6c0 Delete type=0 #1012
|
||||
2026/07/23-21:32:07.253437 7fb394b4f6c0 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 +1 @@
|
||||
return args.item?.system?.isProjectiles && args.data.targets[0]?.actor?.sizeNum < 3
|
||||
return args.item?.system?.isRanged && args.data.targets[0]?.actor?.sizeNum < 3
|
||||
@@ -0,0 +1 @@
|
||||
this.item.system.encumbrance.value = Math.max(0, this.item.system.encumbrance.value - 1)
|
||||
@@ -0,0 +1,18 @@
|
||||
let melee = ["Compendium.wfrp4e-core.items.Item.4MJJCiOKPkBByYwW", "Compendium.wfrp4e-core.items.Item.RWJrupj9seau0w31", "Compendium.wfrp4e-core.items.Item.jt0DmVK9IiF6Sd2h"];
|
||||
let ranged = ["Compendium.wfrp4e-core.items.Item.5eDd6iFeR9G6cCfz", "Compendium.wfrp4e-core.items.Item.jrYW2OyDHd1Md2my", "Compendium.wfrp4e-core.items.Item.cygaI9gq4BQJvbB5"];
|
||||
|
||||
if (args.equipped)
|
||||
{
|
||||
if (this.item.system.isMelee)
|
||||
{
|
||||
this.actor.addEffectItems(melee, this.effect);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.actor.addEffectItems(ranged, this.effect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.effect.deleteCreatedItems();
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
let property = this.effect.getFlag("wfrp4e", "property");
|
||||
if (property && !this.item.system.flaws.value.find(i => i.name == property));
|
||||
{
|
||||
this.item.system.flaws.value.push({name : property});
|
||||
}
|
||||
+27
-24
@@ -1,28 +1,31 @@
|
||||
if (!this.item.name.includes("(") || this.item.system.tests.value.includes("Terrain") || this.item.system.tests.value.toLowerCase().includes("(any)")) {
|
||||
let tests = this.item.system.tests.value
|
||||
let name = this.item.name
|
||||
if (!this.item.name.includes("(") || this.item.system.tests.value.includes("Terrain") || this.item.system.tests.value.toLowerCase().includes("(any)"))
|
||||
{
|
||||
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("(") && !name.toLowerCase().includes("(any)")) {
|
||||
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: "Littoral",
|
||||
deserts: "Déserts",
|
||||
marshes: "Marécages",
|
||||
rocky: "Rocailleux",
|
||||
tundra: "Toundra",
|
||||
woodlands: "Régions boisées"
|
||||
}, this.item.img), 1, "Choisissez un Terrain");
|
||||
if (choice[0]) {
|
||||
name = `${name.split("(")[0].trim()} (${choice[0].name})`
|
||||
tests = tests.replace("Terrain", choice[0].name + " Terrain")
|
||||
// Si le nom précise déjà un terrain, on met à jour la valeur de tests
|
||||
if (name.includes("(") && !name.toLowerCase().includes("(any)"))
|
||||
{
|
||||
let terrain = name.split("(")[1].split(")")[0]
|
||||
tests = tests.replace("the Terrain", terrain)
|
||||
}
|
||||
else // Sinon, on propose un choix par dialogue
|
||||
{
|
||||
let choice = await ItemDialog.create(ItemDialog.objectToArray({
|
||||
coastal : "Littoral",
|
||||
deserts : "Déserts",
|
||||
marshes : "Marécages",
|
||||
rocky : "Rocailleux",
|
||||
tundra : "Toundra",
|
||||
woodlands : "Régions boisées"
|
||||
}, this.item.img), 1, "Choisissez un 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 })
|
||||
this.effect.updateSource({name})
|
||||
this.item.updateSource({name, "system.tests.value" : tests})
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
let damage = await new Roll("1d10").roll();
|
||||
damage.toMessage(this.script.getChatData());
|
||||
this.actor.applyDamage(damage.total, {
|
||||
damageType: game.wfrp4e.config.DAMAGE_TYPE.IGNORE_ALL,
|
||||
createMessage: this.script.getChatData()
|
||||
});
|
||||
|
||||
const test = await this.actor.setupSkill(
|
||||
game.i18n.localize("NAME.Endurance"),
|
||||
{
|
||||
fields: {difficulty: "average"},
|
||||
skipTargets: true,
|
||||
appendTitle: ` — ${this.effect.name}`,
|
||||
},
|
||||
);
|
||||
|
||||
await test.roll();
|
||||
if (test.failed)
|
||||
{
|
||||
this.actor.addCondition("stunned");
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
if (args.opposedTest.result.hitloc.value == this.item.system.location.key && args.totalWoundLoss > 0)
|
||||
if (args.loc == this.item.system.location.key && args.totalWoundLoss > 0)
|
||||
{
|
||||
args.actor.addCondition("bleeding", 2);
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
if (!this.item.system.properties.qualities.pummel) this.item.system.qualities.value.push({name : 'pummel'});if (!this.item.system.properties.qualities.hack) this.item.system.qualities.value.push({name : 'hack'})
|
||||
@@ -0,0 +1 @@
|
||||
return game.messages.get(args.context.dispel)?.system.test.spell.system.magicMissile.value;
|
||||
@@ -1 +1 @@
|
||||
args.prefillModifiers.difficulty = "hard"
|
||||
args.fields.difficulty = "hard"
|
||||
@@ -0,0 +1,6 @@
|
||||
let damage = await new Roll("1d10 + 1").roll();
|
||||
damage.toMessage(this.script.getChatData());
|
||||
this.actor.applyDamage(damage.total, {
|
||||
damageType: game.wfrp4e.config.DAMAGE_TYPE.IGNORE_AP,
|
||||
createMessage: this.script.getChatData()
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
if (args.type == "effect" && args.options.action == "delete" && ["prone"].some(i => args.document.statuses.has(i)))
|
||||
{
|
||||
this.script.notification("Impossible de retirer " + args.document.name);
|
||||
let resist = await this.effect.resistEffect();
|
||||
if (resist)
|
||||
{
|
||||
this.effect.delete();
|
||||
}
|
||||
return resist;
|
||||
}
|
||||
@@ -5,5 +5,5 @@ let SL = Math.floor(args.test.target / 10) - Math.floor(args.test.result.roll /
|
||||
let ones = Number(args.test.result.roll.toString().split("").pop())
|
||||
|
||||
if (ones > SL)
|
||||
args.Test.result.other.push(`<span class="hide-option"><b>${this.effect.name}</b>: ${ones + args.test.successBonus + args.test.slBonus} DR</span>`)
|
||||
args.test.result.other.push(`<span class="hide-option"><b>${this.effect.name}</b>: ${ones + args.test.successBonus + args.test.slBonus} DR</span>`)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Pray"), {appendTitle: ` - ${this.effect.name}`});
|
||||
await test.roll();
|
||||
|
||||
if (test.succeeded)
|
||||
{
|
||||
this.actor.removeCondition("blinded", 1 + parseInt(test.result.SL));
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
args.options.terror
|
||||
@@ -0,0 +1,6 @@
|
||||
let roll = await new Roll("2d10 + @sin", {sin: this.actor.system.status.sin.value || 0}).roll();
|
||||
roll.toMessage(this.script.getChatData());
|
||||
this.effect.updateSource({duration: {
|
||||
value: roll.total,
|
||||
units: "days"
|
||||
}});
|
||||
@@ -0,0 +1,6 @@
|
||||
let roll = await new Roll("2d10 + @sin", {sin: this.actor.system.status.sin.value || 0}).roll();
|
||||
roll.toMessage(this.script.getChatData());
|
||||
this.effect.updateSource({duration: {
|
||||
value: roll.total,
|
||||
units: "rounds"
|
||||
}});
|
||||
@@ -0,0 +1 @@
|
||||
this.actor.modifyWounds(-1);
|
||||
@@ -0,0 +1,21 @@
|
||||
let damage = await new Roll("1d10 + @sin", {sin: this.actor.system.status.sin.value || 0}).roll();
|
||||
damage.toMessage(this.script.getChatData());
|
||||
this.actor.applyDamage(damage.total, {
|
||||
damageType: game.wfrp4e.config.DAMAGE_TYPE.IGNORE_ALL,
|
||||
createMessage: this.script.getChatData()
|
||||
});
|
||||
|
||||
const test = await this.actor.setupSkill(
|
||||
game.i18n.localize("NAME.Endurance"),
|
||||
{
|
||||
fields: {difficulty: "difficult"},
|
||||
skipTargets: true,
|
||||
appendTitle: ` — ${this.effect.name}`,
|
||||
},
|
||||
);
|
||||
|
||||
await test.roll();
|
||||
if (test.failed)
|
||||
{
|
||||
this.actor.addCondition("stunned");
|
||||
}
|
||||
@@ -5,5 +5,5 @@ let SL = Math.floor(args.test.target / 10) - Math.floor(args.test.result.roll /
|
||||
let ones = Number(args.test.result.roll.toString().split("").pop())
|
||||
|
||||
if (ones > SL)
|
||||
args.Test.result.other.push(`<span class="hide-option"><b>${this.effect.name}</b>: ${ones + args.test.successBonus + args.test.slBonus} DR</span>`)
|
||||
args.test.result.other.push(`<span class="hide-option"><b>${this.effect.name}</b>: ${ones + args.test.successBonus + args.test.slBonus} DR</span>`)
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
if (args.equipped) {
|
||||
this.actor.createEmbeddedDocuments("ActiveEffect", [this.item.effects.contents[1]?.convertToApplied()])
|
||||
this.script.message(`${this.actor.name} porte le <strong>${this.item.name}</strong>. <br>
|
||||
Ils gagnent +1 point de Corruption si un Test d'exposition échoue, ce qui devra être appliqué manuellement.<br> S'ils portent le masque pendant plus d'une heure ou bénéficient de l'un de ses effets, ils sont exposés à @Corruption[modérée]{Corruption Modérée}
|
||||
Ils gagnent +1 point de Corruption si un Test d'exposition échoue, ce qui devra être appliqué manuellement.<br> S'ils portent le masque pendant plus d'une heure ou bénéficient de l'un de ses effets, ils sont exposés à @Corruption[moderate]{Corruption Modérée}
|
||||
`,
|
||||
{whisper: ChatMessage.getWhisperRecipients("GM")})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
let roll = await new Roll("1d10").roll();
|
||||
|
||||
roll.toMessage(this.script.getChatData());
|
||||
|
||||
if (roll.total == 1)
|
||||
{
|
||||
this.item.updateSource({"system.description.value" : this.item.system.description.value += `<p><strong>${this.effect.name}</strong>: The weapon counts as a @Corruption[minor]{minor source of Corruption}.</p>`});
|
||||
}
|
||||
else if (roll.total <= 5)
|
||||
{
|
||||
let quirks = await fromUuid("Compendium.wfrp4e-archives2.tables.RollTable.LbNZOF6Ov7xKHS5Z");
|
||||
if (quirks)
|
||||
{
|
||||
let quirkRoll = await new Roll("1d100 + 40").roll();
|
||||
quirkRoll.toMessage(this.script.getChatData());
|
||||
let quirkResult = (await quirks.roll({roll: quirkRoll})).results[0].text;
|
||||
this.item.updateSource({"system.description.value" : this.item.system.description.value += `<p><strong>${this.effect.name}</strong>: ${quirkResult.replace("<p>", "")}</p>`});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.item.updateSource({"system.description.value" : this.item.system.description.value += `<p><strong>${this.effect.name}</strong>: Generate an additional Quirk or Curse by rolling on the @UUID[Compendium.wfrp4e-archives2.tables.RollTable.LbNZOF6Ov7xKHS5Z]{Quirks and Curses} Table and adding +40 to the result.</p>`});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.item.updateSource({"system.description.value" : this.item.system.description.value += `<p><strong>${this.effect.name}</strong>: People who recognise the weapon are subject to @UUID[Compendium.wfrp4e-core.items.Item.0VpT5yubw4UL7j6f]{Animosity} towards the bearer.</p>`});
|
||||
}
|
||||
@@ -11,8 +11,8 @@ if (args.test.result.castOutcome == "failure")
|
||||
this.script.notification(`Lost ${value} Wounds`)
|
||||
this.actor.modifyWounds(-1 * value)
|
||||
await this.item.system.toggleEquip();
|
||||
args.Test.addSL(value);
|
||||
args.Test.preData.other.push(`<strong>${this.effect.name}</strong>: +${value} SL`)
|
||||
args.test.addSL(value);
|
||||
args.test.preData.other.push(`<strong>${this.effect.name}</strong>: +${value} SL`)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Cool"), {skipTargets: true, appendTitle : ` - ${this.effect.name}`})
|
||||
await test.roll();
|
||||
if (test.failed && this.actor.type == "character")
|
||||
{
|
||||
this.actor.update({"system.status.corruption.value" : parseInt(this.actor.status.corruption.value) + 1})
|
||||
this.script.message("Gagné un point de Corruption", {whisper : ChatMessage.getWhisperRecipients("GM")})
|
||||
}
|
||||
@@ -13,7 +13,7 @@ const test = await this.actor.setupSkill(game.i18n.localize("NAME.Résistance"),
|
||||
await test.roll();
|
||||
|
||||
if (test.failed) {
|
||||
await this.actor.addEffectItems(bloodyFluxUUID, this.effet);
|
||||
await this.actor.addEffectItems(bloodyFluxUUID, this.effect);
|
||||
} else {
|
||||
const SL = test.result.SL;
|
||||
const heal = 1 + SL;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
this.actor.addCondition("blinded");
|
||||
let roll = await new Roll("1d10").roll();
|
||||
roll.toMessage(this.script.getChatData());
|
||||
this.effect.updateSource({duration: {value: roll.total, units: "hours"}});
|
||||
@@ -0,0 +1,5 @@
|
||||
if (args.sourceTest.options.doubleDamage)
|
||||
{
|
||||
args.modifiers.other.push({label: this.effect.name, value: args.totalWoundLoss});
|
||||
args.totalWoundLoss *= 2;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
let test = args.test
|
||||
if (test && test.spell?.system.magicMissile.value)
|
||||
{
|
||||
let roll = await new Roll("1d100").roll();
|
||||
roll.toMessage(this.script.getChatData());
|
||||
if (roll.total <= 30)
|
||||
{
|
||||
this.script.message(`<strong>${this.item.name}</strong> : Le sort échoue !`)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
if (args.test.skill?.name == game.i18n.localize("NAME.Pray") || args.test.prayer)
|
||||
{
|
||||
if (parseInt(args.test.result.SL) > 0)
|
||||
{
|
||||
args.test.result.SL = "+0";
|
||||
args.test.result.description = game.i18n.localize("ROLL.MarginalSuccess");
|
||||
args.test.result.other.push(`<strong>${this.effect.name}</strong>: Maximum +0 SL`)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
let halve;
|
||||
if (args.opposedTest.attackerTest.item?.type != "spell")
|
||||
if (args.sourceItem?.type != "spell")
|
||||
{
|
||||
halve = await foundry.applications.api.DialogV2.confirm({window : {title : this.effect.name}, content : "Diviser les dégâts par deux ? (Divise tous les dégâts sauf le feu, le froid et la magie)"})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
let properties = {
|
||||
fine : "Fine",
|
||||
durable : "Durable",
|
||||
lightweight : "Lightweight",
|
||||
practical : "Practical"
|
||||
};
|
||||
|
||||
|
||||
let choice = await ItemDialog.create(ItemDialog.objectToArray(properties), 1, {title: this.effect.name, text: "Select Property"});
|
||||
|
||||
if (choice[0])
|
||||
{
|
||||
this.effect.updateSource({"flags.wfrp4e.property" : choice[0].id, name : this.effect.setSpecifier(choice[0].name)});
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
let colors = {
|
||||
fire : "#b22222",
|
||||
heavens : "#87ceeb",
|
||||
metal : "#ee9b3a",
|
||||
shadow : "#808080",
|
||||
life : "#008000",
|
||||
beasts : "#a52a2a",
|
||||
light : "#f0ffff",
|
||||
death : "#800080",
|
||||
necromancy : "#800080",
|
||||
daemonology : "#8b0000"
|
||||
};
|
||||
|
||||
let spell = this.actor.itemTypes.spell.find(i => Object.keys(colors).includes(i.system.lore.value[0]));
|
||||
|
||||
let color;
|
||||
if (spell)
|
||||
{
|
||||
color = colors[spell.system.lore.value[0]];
|
||||
}
|
||||
else
|
||||
{
|
||||
color = Object.values(colors)[Math.ceil(CONFIG.Dice.randomUniform() * 10)];
|
||||
}
|
||||
|
||||
this.effect.updateSource({changes: this.effect.changes.concat({key: "token.light.color", type: "override", value: color})});
|
||||
@@ -0,0 +1,15 @@
|
||||
let qualities = {
|
||||
fast : "Rapide",
|
||||
hack : "Tranchant",
|
||||
impale : "Empalant",
|
||||
penetrating : "Pénétrant",
|
||||
precise : "Précis"
|
||||
}
|
||||
|
||||
let choice = await ItemDialog.create(ItemDialog.objectToArray(qualities, this.item.img), 1, {text: "Choisissez une qualité", title: this.effect.name});
|
||||
|
||||
if (choice[0])
|
||||
{
|
||||
this.script.message(choice[0].name);
|
||||
this.effect.setFlag("wfrp4e", "quality", choice[0].id);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
if (args.totalWoundLoss > 0) args.actor.addCondition('ablaze')
|
||||
@@ -2,7 +2,7 @@ let lore = this.effect.name.split("(")[1].split(")")[0].toLowerCase();
|
||||
|
||||
// If channelling corresponding lore
|
||||
if (args.type == "channelling" && args.spell.system.lore.value == lore)
|
||||
args.prefillModifiers.slBonus += 2
|
||||
args.fields.slBonus += 2
|
||||
// If channelling or casting different lore
|
||||
else if (args.spell.system.lore.value != lore && args.spell.system.lore.value != "petty")
|
||||
args.prefillModifiers.slBonus -= 1
|
||||
args.fields.slBonus -= 1
|
||||
@@ -0,0 +1,6 @@
|
||||
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Cool"), {skipTargets: true, appendTitle : ` - ${this.effect.name}`, fields : {difficulty : "hard"}, context : {failure: "Gain Broken"}});
|
||||
await test.roll();
|
||||
if (test.failed)
|
||||
{
|
||||
this.actor.addCondition("broken");
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
if (args.opposedTest.attackerTest.weapon?.system.properties?.qualities.hack && !args.hackReminder)
|
||||
if (args.sourceItem?.system.properties?.qualities.hack && !args.hackReminder)
|
||||
{
|
||||
args.hackReminder = true;
|
||||
args.opposedTest.result.other.push(`<strong>${this.effect.name}</strong>: Hack causes ${this.item.Advances} extra damage`)
|
||||
}
|
||||
if (args.opposedTest)
|
||||
{
|
||||
args.opposedTest.result.other.push(`<strong>${this.effect.name}</strong> : Tranchant inflige ${this.item.Advances} dégâts supplémentaires`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
if (args.totalWoundLoss > 0) {
|
||||
args.opposedTest.result.other.push(
|
||||
`@Corruption[minor]{Moderate Exposure to Corruption}`
|
||||
)
|
||||
if (args.opposedTest)
|
||||
{
|
||||
args.opposedTest.result.other.push(
|
||||
`@Corruption[minor]{Exposition modérée à la Corruption}`
|
||||
)
|
||||
}
|
||||
this.script.message(`<strong>${this.effect.name}</strong>:
|
||||
@Corruption[moderate]{Moderate Exposure to Corruption} <br/>
|
||||
<strong>${args.actor.prototypeToken.name}</strong> must take an
|
||||
<strong>Corruption (Moderate) Test</strong>`,
|
||||
@Corruption[moderate]{Exposition modérée à la Corruption} <br/>
|
||||
<strong>${args.actor.prototypeToken.name}</strong> doit effectuer un
|
||||
<strong>Test de Corruption (Modéré)</strong>`,
|
||||
{whisper: ChatMessage.getWhisperRecipients("GM")}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
if ((args.opposedTest.attackerTest.item && args.opposedTest.attackerTest.item.isMelee) || (args.opposedTest.attackerTest.item && !args.opposedTest.attackerTest.item.name.includes("Projectiles")))
|
||||
if ((args.sourceItem && args.sourceItem.isMelee) || (args.sourceItem && !args.sourceItem.name.includes("Projectiles")))
|
||||
{
|
||||
let choice = await foundry.applications.api.DialogV2.confirm({window : {title : this.effect.name}, content : `<p>Apply damage with <strong>${this.effect.name}</strong> to attacker?`})
|
||||
let choice = await foundry.applications.api.DialogV2.confirm({window : {title : this.effect.name}, content : `<p>Appliquer les dégâts avec <strong>${this.effect.name}</strong> à l'attaquant ?`})
|
||||
|
||||
if (choice)
|
||||
{
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
args.prefillModifiers.modifier += 10
|
||||
args.fields.modifier += 10
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
let properties = {
|
||||
ugly : "Ugly",
|
||||
shoddy : "Shoddy",
|
||||
unreliable : "Unreliable"
|
||||
};
|
||||
|
||||
let choice = await ItemDialog.create(ItemDialog.objectToArray(properties), 1, {title: this.effect.name, text: "Select Property"});
|
||||
|
||||
if (choice[0])
|
||||
{
|
||||
this.effect.updateSource({"flags.wfrp4e.property" : choice[0].id, name : this.effect.setSpecifier(choice[0].name)});
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
let skills = this.actor.itemTypes.skill.filter(s => (this.effect.getFlag("wfrp4e", "skills") || []).includes(s.name));
|
||||
skills.forEach(s => {
|
||||
s.system.modifier.value -= 10;
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
if (args.opposedTest.result.hitloc.value == this.item.system.location.key && args.totalWoundLoss > 0)
|
||||
if (args.loc == this.item.system.location.key && args.totalWoundLoss > 0)
|
||||
{
|
||||
args.actor.addCondition("bleeding", 2);
|
||||
this.script.notification("Etat Hémorragique ajouté")
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
if (args.opposedTest.result.hitloc.value == "body")
|
||||
if (args.loc == "body")
|
||||
{
|
||||
if ((await new Roll("1d2").roll()).total == 1)
|
||||
{
|
||||
args.opposedTest.result.hitloc.value = "head"
|
||||
this.script.message(`Localisation du coup changé pour la tête`)
|
||||
args.loc = "head"
|
||||
args.AP = foundry.utils.deepClone(args.actor.status.armour[args.loc]);
|
||||
this.script.message(`Localisation du coup changée pour la tête`)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
let locs = Object.keys(this.actor.system.status.armour);
|
||||
|
||||
let location = locs[Math.floor(CONFIG.Dice.randomUniform() * (locs.length))];
|
||||
|
||||
game.wfrp4e.tables.formatChatRoll(`crit${location}`, {criticalLocation: location, showRoll: true});
|
||||
@@ -0,0 +1,3 @@
|
||||
let roll = await new Roll("1d10").roll();
|
||||
roll.toMessage(this.script.getChatData());
|
||||
this.effect.updateSource({duration: {value: roll.total, units: "hours"}});
|
||||
@@ -0,0 +1,2 @@
|
||||
let skill = this.actor.itemTypes.skill.find(s => s.name === game.i18n.localize("NAME.Pray"));
|
||||
skill.system.modifier.value -= 10;
|
||||
@@ -0,0 +1,27 @@
|
||||
this.actor.addCondition("ablaze");
|
||||
let colors = {
|
||||
fire : "#b22222",
|
||||
heavens : "#87ceeb",
|
||||
metal : "#ee9b3a",
|
||||
shadow : "#808080",
|
||||
life : "#008000",
|
||||
beasts : "#a52a2a",
|
||||
light : "#f0ffff",
|
||||
death : "#800080",
|
||||
necromancy : "#800080",
|
||||
daemonology : "#8b0000"
|
||||
};
|
||||
|
||||
let spell = this.actor.itemTypes.spell.find(i => Object.keys(colors).includes(i.system.lore.value[0]));
|
||||
|
||||
let color;
|
||||
if (spell)
|
||||
{
|
||||
color = colors[spell.system.lore.value[0]];
|
||||
}
|
||||
else
|
||||
{
|
||||
color = Object.values(colors)[Math.ceil(CONFIG.Dice.randomUniform() * 10)];
|
||||
}
|
||||
|
||||
this.effect.updateSource({changes: this.effect.changes.concat({key: "token.light.color", type: "override", value: color})});
|
||||
@@ -1,4 +1,4 @@
|
||||
if (args.opposedTest.result.hitloc.value == "body" && args.totalWoundLoss > 0)
|
||||
if (args.loc == "body" && args.totalWoundLoss > 0)
|
||||
{
|
||||
args.actor.addCondition("bleeding", 2)
|
||||
this.script.notification("Etat Hémmoragique appliqué : 2 niveaux de saignement")
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
if (args.type == "effect" && args.options.action == "delete" && ["blinded"].some(i => args.document.statuses.has(i)))
|
||||
{
|
||||
this.script.notification("Impossible de retirer " + args.document.name);
|
||||
return false;
|
||||
}
|
||||
@@ -25,7 +25,7 @@ if (god)
|
||||
if (blessings.length)
|
||||
{
|
||||
this.script.scriptNotification("Ajout de " + blessings.map(i => i.name).join(", "))
|
||||
await this.actor.addEffectItems(blessings.map(i => i.uuid), this.effet)
|
||||
await this.actor.addEffectItems(blessings.map(i => i.uuid), this.effect)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
this.actor.addCondition("deafened");
|
||||
@@ -0,0 +1 @@
|
||||
game.wfrp4e.tables.formatChatRoll(`mutatephys`, {showRoll: true});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user