Compare commits

...

124 Commits
v9 ... v10

Author SHA1 Message Date
3ba0449c12 Fix spells 2024-09-12 22:46:01 +02:00
819548567b Fix spells 2024-09-12 22:43:09 +02:00
133f7aa428 Gestion des hordes et divers améliorations + traduction espagnole 2024-09-05 20:23:41 +02:00
ed68c17304 Gestion des hordes et divers améliorations + traduction espagnole 2024-09-05 20:14:17 +02:00
e6bdc427f2 Various minor fixes + fix roll result 2024-09-04 08:57:26 +02:00
321052fd33 BoL : V12 support only 2024-08-13 10:37:56 +02:00
165a18e897 Prepare for module rulebook 2024-07-08 22:27:11 +02:00
7ed9265a26 Passage en v12 + preparation module officiel BoL 2024-04-26 18:00:56 +02:00
ae43c7c920 Update for module support 2024-02-22 18:29:04 +01:00
20ab9a17a4 Update metrics data 2024-02-07 22:11:32 +01:00
5de40d4998 Ajout du xplog 2024-01-12 18:42:12 +01:00
c7c26c0033 Ajout macro roll 2024-01-02 23:34:38 +01:00
5c4c6d73ee Add new translations 2023-12-05 10:23:55 +01:00
1a0049a3f5 Add new translations 2023-12-05 10:23:39 +01:00
5d30482ce3 Add new translations 2023-12-04 21:38:10 +01:00
3fb8e92428 Add new translations 2023-12-04 21:37:29 +01:00
7738746994 Add new translations 2023-12-04 21:30:12 +01:00
761179bc5a Now use v11 compendiums 2023-10-28 18:52:13 +02:00
a4d7c13383 Now use v11 compendiums 2023-10-28 18:47:52 +02:00
ee6bf1a4d4 Now use v11 compendiums 2023-10-28 18:46:51 +02:00
469948e296 Now use v11 compendiums 2023-10-28 18:46:29 +02:00
def271b8b9 Initiative 2023-10-15 17:56:01 +02:00
c9ed514ed6 Sync avec mater
Merge branch 'v10' of https://www.uberwald.me/gitea/public/bol into v10
2023-10-15 17:51:31 +02:00
2ffd3f35c8 Initiative 2023-10-15 17:51:07 +02:00
e3b281f195 Merge pull request 'fix: utilisation d’une variable non définie' (#24) from DjLeChuck/bol:fix-damage-without-armor-apply into v10
Reviewed-on: public/bol#24
2023-10-15 16:28:23 +02:00
Vivien DE BONA
29ecb04ec3
fix: utilisation d’une variable non définie 2023-10-15 16:25:00 +02:00
ca3064dc0a Merge pull request 'fix: data-attribut corrompu sur l’encaissement sans armure' (#23) from DjLeChuck/bol:fix-defense-request-card into v10
Reviewed-on: public/bol#23
2023-10-15 16:15:58 +02:00
Vivien DE BONA
9fd8751124
fix: data-attribut corrompu sur l’encaissement sans armure 2023-10-15 16:14:55 +02:00
2d63b63b86 Merge pull request 'fix-creatures-compendium' (#22) from DjLeChuck/bol:fix-creatures-compendium into v10
Reviewed-on: public/bol#22
2023-10-15 16:13:39 +02:00
Vivien DE BONA
b44250e728
fix: tailles du Phong et du Behemathon
- Phong : petité créature et non grande
- Behemathon : monstrueuse créature et non grande
2023-10-15 16:11:56 +02:00
Vivien DE BONA
63c3e24296
fix: typage des créatures
- Utilisation de "cartype" et non "type"
2023-10-15 16:08:41 +02:00
8a87f6deab Fix #21 2023-10-15 16:02:26 +02:00
759b099bdf Fix #20 2023-10-15 16:01:31 +02:00
ade88fb54b Corrections sur encaissement 2023-09-16 09:40:08 +02:00
f1a3f2df36 Rollback to previous release system 2023-08-26 21:45:33 +02:00
a357c6ddfc Add gitea CI/CD 2023-08-26 19:17:02 +02:00
26a6c7fc28 Add gitea CI/CD 2023-08-26 19:11:37 +02:00
6fcac36580 Add gitea CI/CD 2023-08-26 19:08:53 +02:00
34924b07c0 Add gitea CI/CD 2023-08-26 19:04:48 +02:00
66bf299ea4 Add gitea CI/CD 2023-08-26 19:01:51 +02:00
37ab0d01dc Add gitea CI/CD 2023-08-26 19:00:25 +02:00
2e3a97de04 Add gitea CI/CD 2023-08-26 18:11:41 +02:00
01dbe76f59 Minor fixes 2023-08-26 18:03:08 +02:00
ca33defd75 Update v11 2023-06-23 09:02:45 +02:00
2e616e3e31 Update v11 2023-06-23 08:37:56 +02:00
3be7f4bf9f Update v11 2023-06-23 08:37:50 +02:00
1b8e0840b0 Update v11 2023-06-22 23:05:50 +02:00
2cdd096c98 Update v11 2023-06-22 23:05:36 +02:00
8fcb17b566 Update v11 2023-06-22 23:05:04 +02:00
ad79dbb015 New combat options 2023-06-22 20:36:40 +02:00
73ccf44dd4 New combat options 2023-06-22 20:34:17 +02:00
ec3649799f v10/v11 compat 2023-05-25 16:29:43 +02:00
3f5f090bb9 Points de creation OK again 2023-05-24 14:00:24 +02:00
268ac0a25a Review initiative 2023-05-01 18:50:32 +02:00
59ee6684ab Fix #19 - Horoscope majeur 2023-04-29 21:48:51 +02:00
41fbc094bb Combat Tracker + power enhancements 2023-04-06 20:15:04 +02:00
5b91041a3f Fix options de combat 2023-04-04 13:41:22 +02:00
e7f3851daa Fix dice default 2023-03-29 23:04:02 +02:00
75d562f922 Nouvelle option d'ignorer les dommages 2023-03-25 08:42:14 +01:00
ba7e25e8c7 Fix and +/- 2023-03-18 13:51:46 +01:00
83d3f17dd0 Messages de recuperation 2023-03-18 10:24:30 +01:00
0c502a2188 Meilleure gestion initiative 2023-03-15 17:35:07 +01:00
5df2b7e624 Minot fixes 2023-02-19 19:35:03 +01:00
f6554f6945 New release 2023-02-03 23:55:59 +01:00
fbe232266f Spell changes to support v1.7 2023-02-01 10:16:21 +01:00
4b9c3bcd1e Spell changes to support v1.7 2023-02-01 10:15:56 +01:00
05f09aa3f5 Add dice selection 2023-01-26 20:50:56 +01:00
727db74545 Update sheet 2023-01-23 20:50:48 +01:00
ccb3a458c0 Add pages 2023-01-05 17:00:11 +01:00
1ac9605f08 Fix init creature + minor changes 2023-01-04 09:57:13 +01:00
1bbefd3499 Astrologie ! 2022-12-25 18:00:42 +01:00
bcb377db7a Gestion de l'astrologie 2022-12-23 23:24:09 +01:00
7a8cf9f8fd Welcome page and init info message 2022-12-23 16:38:41 +01:00
d74f7784bb Fix bougette sur PNJ/Creatures 2022-12-04 13:49:00 +01:00
6d6fec99b0 Fix bougette sur PNJ/Creatures 2022-12-04 13:48:37 +01:00
884823a1bc Init again !!!! 2022-12-02 13:16:42 +01:00
399c22d623 Init again !!!! 2022-12-02 13:15:48 +01:00
085265df5d initiative bugfix 2022-12-01 23:57:33 +01:00
593db9ba5b initiative bugfix 2022-12-01 23:46:27 +01:00
ac96f3ca67 Enhance initiative + fix combat 2022-11-30 20:58:27 +01:00
b2fe67ab05 Enhance tokens/actor management + auto effects 2022-11-30 12:12:44 +01:00
47178d7359 Use bougette v1.2 2022-11-29 15:23:05 +01:00
e1c7304551 Add a PC list summary 2022-11-25 20:47:28 +01:00
7b4e5bcbfa Add a PC list summary 2022-11-25 15:50:12 +01:00
31bd83b0ab Add a PC list summary 2022-11-25 15:50:07 +01:00
e35187433e Fix malus dice (again) and scroll rendering 2022-11-25 14:24:03 +01:00
5e7dc3ad9d Display effects in main sheet (left) and manage it for defense and damages 2022-11-25 08:49:37 +01:00
add6893864 Logo is rotating again 2022-11-25 07:37:44 +01:00
3a591e750a Ajout aide + effets 2022-11-23 21:37:46 +01:00
fe1cda67c4 Ajout aide + effets 2022-11-23 21:34:51 +01:00
985aba0318 Various enhancements 2022-11-23 15:30:31 +01:00
5d8cc300e9 Various enhancements 2022-11-23 15:27:08 +01:00
aa27168c2b fix flaws usage 2022-11-19 22:00:14 +01:00
1135e3aff2 fix flaws usage 2022-11-19 21:56:51 +01:00
30e316d34e Remove to chat button 2022-11-19 19:22:16 +01:00
f3bd84c5c9 Corrections sur creatures/npc et armes de vehicules 2022-10-10 14:14:32 +02:00
985d393de5 Corrections sur creatures/npc et armes de vehicules 2022-10-10 08:46:41 +02:00
815b5ff2ac Ajout distance 2022-10-08 17:43:09 +02:00
edf8325109 Inc version 2022-09-28 23:26:41 +02:00
895aa01419 Enable links in editor 2022-09-27 20:47:30 +02:00
9631e5e72a Merge conteneur 2022-09-26 08:28:47 +02:00
716cc53b29 Merge conteneur 2022-09-26 08:24:39 +02:00
44952d4410 Fix hotbar + tooltip 2022-09-25 21:14:39 +02:00
a7991bce92 Fix hotbar + tooltip 2022-09-25 21:13:15 +02:00
a1c20019e8 v10 init fix 2022-09-19 23:23:54 +02:00
af8576a4a1 Fix initfor combat 2022-09-09 23:49:01 +02:00
6c35ddfb0b rework ID 2022-09-02 17:31:12 +02:00
0cbcaee45e rework ID 2022-09-02 16:21:18 +02:00
904ff821e1 rework ID 2022-09-02 16:19:16 +02:00
5c13cde07a rework ID 2022-09-02 16:08:56 +02:00
51c1e205e9 rework ID 2022-09-01 22:40:29 +02:00
90a83f4571 rework ID 2022-09-01 22:23:58 +02:00
3311bc091a rework ID 2022-09-01 21:26:10 +02:00
fa8f9869a6 v10 sync 2022-08-31 23:00:41 +02:00
36b905134e v10 sync 2022-08-31 22:46:19 +02:00
eeb0a906e7 v10 sync 2022-08-31 22:24:56 +02:00
c552411d61 Allow configurable logo 2022-07-17 18:24:29 +02:00
89ec404ca8 v10 branch - Update manifest 2022-07-16 11:05:15 +02:00
d888c6a2eb v10 branch - Update manifest 2022-07-13 08:07:16 +02:00
165e41fef6 v10 branch - Update manifest 2022-07-13 08:07:04 +02:00
19bb0798c8 Sync 2022-07-07 13:33:31 +02:00
05f044bc7c Foundry v10 version 2022-07-01 16:30:21 +02:00
996ac1c88d Foundry v10 version 2022-07-01 16:00:49 +02:00
cc1964093d Foundry v10 version 2022-07-01 15:48:54 +02:00
285 changed files with 6041 additions and 7808 deletions

54
.gitea/workflows/main.yml Normal file
View File

@ -0,0 +1,54 @@
name: Release Creation
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner."
#- uses: actions/checkout@v3
- uses: RouxAntoine/checkout@v3.5.4
with:
ref: 'v10'
# get part of the tag after the `v`
- name: Extract tag version number
id: get_version
uses: battila7/get-version-action@v2
# Substitute the Manifest and Download URLs in the module.json
- name: Substitute Manifest and Download Links For Versioned Ones
id: sub_manifest_link_version
uses: microsoft/variable-substitution@v1
with:
files: 'system.json'
env:
version: ${{steps.get_version.outputs.version-without-v}}
url: https://www.uberwald.me/gitea/public/bol
manifest: https://www.uberwald.me/gitea/public/bol/releases/latest/system.json
download: https://www.uberwald.me/gitea/public/bol/releases/download/${{github.event.release.tag_name}}/bol.zip
# Create a zip file with all files required by the module to add to the release
- run: |
apt update -y
apt install -y zip
- run: zip -r ./bol.zip system.json template.json README.md LICENSE assets/ css/ fonts/ images/ lang/ module/ packs/ styles/ templates/ ui/
- name: setup go
uses: https://github.com/actions/setup-go@v4
with:
go-version: '>=1.20.1'
- name: Use Go Action
id: use-go-action
uses: https://gitea.com/actions/release-action@main
with:
files: |-
./bol.zip
system.json
api_key: '${{secrets.RELEASE_TOKEN_UBERWALD}}'

118
.gitignore vendored
View File

@ -1,108 +1,10 @@
# Logs .vscode/settings.json
logs .idea
*.log .history
npm-debug.log* todo.md
yarn-debug.log* /.vscode
yarn-error.log* /ignored/
lerna-debug.log* /node_modules/
package-lock.json /jsconfig.json
/package.json
# Diagnostic reports (https://nodejs.org/api/report.html) /package-lock.json
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# BOL Data
#/data/

View File

@ -24,6 +24,7 @@ Les livres du jeu sont nécessaires pour jouer, et sont disponibles ici : http:/
Barbarians of Lemuria, Mythic edition, est un jeu de Simon Washbourne Barbarians of Lemuria, Mythic edition, est un jeu de Simon Washbourne
Auteur : Simon Washbourne. Auteur : Simon Washbourne.
## Crédits de la version française ## Crédits de la version française
Barbarians of Lemuria, le jeu de rôle de Sword & Sorcery, est une publication des éditions Ludospherik, tous droits réservés. Barbarians of Lemuria, le jeu de rôle de Sword & Sorcery, est une publication des éditions Ludospherik, tous droits réservés.
@ -40,4 +41,4 @@ Maps : Emmanuel Roudier.
# Developmement # Developmement
Zigmund, LeRatierBretonnien LeRatierBretonnien, Zigmund (historical)

BIN
assets/bol_monnaies_v1_2.pdf Executable file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

58
changelog.md Normal file
View File

@ -0,0 +1,58 @@
Changes :
# v12.1.0
## French
- Correction sur les conditions des sorts
- Jet d'armures correctement affichés
- Dégat à 0 possibles sur les armes/capacités
## English
- Corrected spell conditions
- Armor rolls are now correctly displayed
- Weapon/capacity damage can now be set to 0
# v12.1.0
- Gestion des Hordes
- Ajout de la traduction Espagnole
- Nouvelles clés de traduction
- Petites amélioration diverses
# v11.1.2
- Ajout des traductions manquantes en anglais
# v11.1.1
- Re-organisation des compendiums + ajouts de nouveaux equipements
- Correction sur la langue Démonique (1 Parlé, 1 Lu/Ecrit)
# v11.1.0
- Foundry v11 seulement
- Re-organisation des compendiums
- Correction sur les créatures
- Correction sur l'encaissement sans armure
- Ajout d'une note d'explication sur l'initiative
# v11.0.8
- Correction sur les malus de bouclier (blocage)
- Corrrection sur le malus d'init des boucliers qui était mal affiché dans la fiche d'item
# v10.4.0
- Ajout de la gestion d'effets
- Aide intégré
- Intégration du PDF de la bougette
# v10.3.3
- Nouvelles clés de traduction
- Lorsqu'une arme a un dé bonus, prise en compte plus claire du dé bonus et affichage de l'information dans la fenêtre de jet
- Lorsqu'une arme relance les 1 sur ses dégats, l'information est affichée dans le tchat
- Termes corrects pour les PNJs (ie rival)
- Nouveaux équipements issus du Dieu Voilé

View File

@ -1,7 +1,6 @@
/* ----------------------------------------- */ /* ----------------------------------------- */
/* LOCAL FONTS */ /* LOCAL FONTS */
/* ----------------------------------------- */ /* ----------------------------------------- */
@import "../node_modules/rpg-awesome/css/rpg-awesome.min.css";
@font-face { @font-face {
font-family: 'Contrail One'; font-family: 'Contrail One';
font-style: normal; font-style: normal;
@ -59,8 +58,6 @@ a:hover {
top: -50px; top: -50px;
left: calc(50% - 100px); left: calc(50% - 100px);
opacity: 0.7; opacity: 0.7;
-webkit-animation: rotation 10s infinite linear;
animation: rotation 10s infinite linear;
} }
#pause h3 { #pause h3 {
font-family: "IMFellDWPicaSC-Regular", serif; font-family: "IMFellDWPicaSC-Regular", serif;
@ -389,16 +386,16 @@ ul.no-bullets {
background-color: lightgray; background-color: lightgray;
} }
.bol h1.form-header { .bol h1.form-header {
font-size: 2.5em; font-size: 2.2em;
font-weight: 700; font-weight: 700;
} }
.bol h2.form-header { .bol h2.form-header {
font-size: 2em; font-size: 1.8em;
font-weight: 500; font-weight: 500;
border-bottom: 1px groove #eeede0; border-bottom: 1px groove #eeede0;
} }
.bol h3.form-header { .bol h3.form-header {
font-size: 1.5em; font-size: 1.2em;
font-weight: 500; font-weight: 500;
border-bottom: 1px groove #eeede0; border-bottom: 1px groove #eeede0;
} }
@ -444,12 +441,16 @@ ul.no-bullets {
.bol .inc-dec-btns { .bol .inc-dec-btns {
color: #4b4a44; color: #4b4a44;
} }
.summmary-number {
padding-left: 4rem;
}
/* Items List */ /* Items List */
.items-list { .items-list {
list-style: none; list-style: none;
margin: 7px 0; margin: 7px 0;
padding: 0; padding: 0;
overflow-y: auto; overflow-y:hidden;
/*overflow-y: auto;*/
} }
.items-list .item-header { .items-list .item-header {
font-family: 'Signika', sans-serif; font-family: 'Signika', sans-serif;
@ -520,6 +521,18 @@ ul.no-bullets {
.items-list .item .item-control { .items-list .item .item-control {
color: #4b4a44; color: #4b4a44;
} }
.items-list .item-name-fixed-medium {
min-width: 8rem;
width: 8rem;
}
.items-list .item-field-fixed-short {
max-width: 3rem;
min-width: 3rem;
width: 3rem;
}
.bougette-dice-img {
color:rgba(150, 44, 44, 0.70);
}
/* ----------------------------------------- */ /* ----------------------------------------- */
/* Premade colors */ /* Premade colors */
@ -790,6 +803,18 @@ body.system-bol img#logo {
max-width: calc(250px - 10px); max-width: calc(250px - 10px);
margin-right: 10px; margin-right: 10px;
} }
.sheet-profile-img {
cursor: pointer;
border: none;
background-color: #EEE;
height: auto;
width: 96px;
height: 96px;
min-width: 96px;
min-height: 96px;
max-width: 96px;
margin-right: 10px;
}
.bol.sheet.actor .window-content form .main .sheet-body { .bol.sheet.actor .window-content form .main .sheet-body {
overflow: hidden; overflow: hidden;
} }
@ -924,6 +949,7 @@ body.system-bol img#logo {
min-height: 400px; min-height: 400px;
} }
.bol.sheet.item h1 input.itemname { .bol.sheet.item h1 input.itemname {
margin-top: 32px;
font-family: "Wolfsbane2Expanded", cursive; font-family: "Wolfsbane2Expanded", cursive;
} }
.bol.sheet.item .item-properties { .bol.sheet.item .item-properties {
@ -1024,15 +1050,25 @@ body.system-bol img#logo {
flex-direction: column; flex-direction: column;
position: absolute; position: absolute;
top: 2.75rem; top: 2.75rem;
right: 4rem; right: 16rem;
} }
.tokenhudext.right { .tokenhudext.right {
justify-content: flex-start; justify-content: flex-start;
flex-direction: column; flex-direction: column;
position: absolute; position: absolute;
top: 2.75rem; /*transform: translate(0, -30%);*/
top: -4rem;
max-width: 250px;
left: 4rem; left: 4rem;
} }
.tokenhudext.right2 {
justify-content: flex-start;
flex-direction: column;
/*transform: translate(0, -30%);*/
position: absolute;
top: -4rem;
left: 11rem;
}
.control-icon.tokenhudicon { .control-icon.tokenhudicon {
width: fit-content; width: fit-content;
height: fit-content; height: fit-content;
@ -1049,5 +1085,18 @@ body.system-bol img#logo {
z-index: 2; z-index: 2;
} }
.bol-hud-menu label { .bol-hud-menu label {
font-size: 0.75rem; font-size: 0.6rem;
} }
.bol-margin-tb-2 {
margin-top: 2px;
margin-bottom: 2px;
}
.character-summary-container {
  opacity: 0.95;
}
.character-summary-rollable {
text-decoration: underline;
}
.activated-green {
color: darkgreen;
}

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 372 KiB

View File

@ -156,6 +156,8 @@
"BOL.ui.armorAgiMalus": "Rüschtung+Schild-Malus (Geschick)", "BOL.ui.armorAgiMalus": "Rüschtung+Schild-Malus (Geschick)",
"BOL.ui.armorInitMalus": "Rüstungsmalus (Init)", "BOL.ui.armorInitMalus": "Rüstungsmalus (Init)",
"BOL.ui.attackValue": "Angriffswert", "BOL.ui.attackValue": "Angriffswert",
"BOL.ui.initMalus": "Init malus",
"BOL.ui.createEquipment": "Create Equipment",
"BOL.featureCategory.origins": "Herkünfte", "BOL.featureCategory.origins": "Herkünfte",
"BOL.featureCategory.races": "Rassen", "BOL.featureCategory.races": "Rassen",
@ -354,6 +356,16 @@
"BOL.vehicleCategory.boat" : "Schiff", "BOL.vehicleCategory.boat" : "Schiff",
"BOL.vehicleCategory.other" : "Anderes", "BOL.vehicleCategory.other" : "Anderes",
"BOL.ui.astrologerPoints": "Points d'Astrologie",
"BOL.ui.astrologerPointsLabel": "Points d'Astrologie actuels",
"BOL.ui.ishoroscopemajor": "Horoscope Majeur (ie de groupe) ?",
"BOL.ui.answer": "Réponse",
"BOL.ui.horoscopefavorable": "Favorable (1dB)",
"BOL.ui.horoscopeunfavorable": "Défavorable (1dM)",
"BOL.ui.horoscopes": "Horoscopes",
"BOL.ui.horoscopesBonus": "Horoscopes (Bonus)",
"BOL.ui.horoscopesMalus": "Horoscopes (Malus)",
"BOL.ui.groupHoroscope": "Horoscrope de Groupe de ",
"BOL.range.PointBlank": "Direkt", "BOL.range.PointBlank": "Direkt",
"BOL.range.Short": "Kurz", "BOL.range.Short": "Kurz",
@ -454,5 +466,25 @@
"BOL.chat.welcome2": "Zum Spielen werden zwingend die passenden BoL Bücher benötigt. Die französischen Originalbücher für dieses System gibt es hier: http://www.ludospherik.fr/content/14-barbarians-of-lemuria<br>Die deutsche Übersetzung gibt es bei Truant Spiele: https://truant.com/produkt/barbarians-of-lemuria-2", "BOL.chat.welcome2": "Zum Spielen werden zwingend die passenden BoL Bücher benötigt. Die französischen Originalbücher für dieses System gibt es hier: http://www.ludospherik.fr/content/14-barbarians-of-lemuria<br>Die deutsche Übersetzung gibt es bei Truant Spiele: https://truant.com/produkt/barbarians-of-lemuria-2",
"BOL.chat.welcome3": "Die enthaltenen Karten wurden von Guillaume Tavernier und Ludospherik zur Verfügung gestellt. Vielen Dank dafür!", "BOL.chat.welcome3": "Die enthaltenen Karten wurden von Guillaume Tavernier und Ludospherik zur Verfügung gestellt. Vielen Dank dafür!",
"BOL.chat.welcome4": "Im Discord findet ihr Support für die FoundryVTT-Implementierung dieses Systems: https://discord.gg/pPSDNJk", "BOL.chat.welcome4": "Im Discord findet ihr Support für die FoundryVTT-Implementierung dieses Systems: https://discord.gg/pPSDNJk",
"BOL.chat.welcome5": "Auf ein gutes Spiel in Lemuria!" "BOL.chat.welcome5": "Auf ein gutes Spiel in Lemuria!",
"BOL.chat.welcome6": "",
"BOL.settings.rollArmor": "Roll for armor",
"BOL.settings.rollArmorTooltip": "Roll for armor value, fixed value if unchecked",
"BOL.settings.useBougette": "Use Bougette (fan-made French rule)",
"BOL.settings.useBougetteTooltip": "Use the Bougette value, as described in Annales Lemurienne from LeRatierBretonnien (https://www.lahiette.com/leratierbretonnien/)",
"BOL.settings.removeDead": "Automatically remove dead NPCs by end of the round",
"BOL.settings.removeDeadTooltip": "Remove NPCs Automatically when HP are 0 or less, at the end of each round",
"BOL.settings.diceFormula": "Dice Formula",
"BOL.settings.diceFormulaTooltip": "Main dice formula (2d6 per default)",
"BOL.settings.diceSuccessValue" : "Success value",
"BOL.settings.diceSuccessValueTooltip": "Value of the success threshold (9 per default for 2d6)",
"BOL.settings.diceCriticalValue" : "Critical success value",
"BOL.settings.diceCriticalValueTooltip": "Minimum value for critical success (12 per default for 2d6)",
"BOL.settings.diceCriticalFailure" : "Critical failure value",
"BOL.settings.diceCriticalFailureTooltip": "Maximum value for critical failure (2 per default for 2d6)",
"BOL.settings.defaultLogoActorSheetPath" : "Path for Actor sheet logo",
"BOL.settings.defaultLogoPathActorSheetTooltip": "Path of the Actor sheet logo (346 x 200, default : /systems/bol/ui/logo.webp)",
"BOL.settings.defaultLogoTopLeftPath" : "Path for main top left logo",
"BOL.settings.defaultLogoTopLeftPathTooltip": "Path of the logo in the top left window (718 x 416, default : /systems/bol/ui/logo2.webp)"
} }

View File

@ -1,13 +1,22 @@
{ {
"ACTOR.TypeCharacter": "Character", "TYPES": {
"ACTOR.TypeEncounter": "Encounter", "Actor": {
"ITEM.TypeItem": "Item", "character": "PC",
"ITEM.TypeFeature": "Feature", "encounter": "NPC",
"ITEM.TypeWeapon": "Weapon", "npc": "NPC",
"ITEM.TypeArmor": "Armor", "vehicle": "Vehicle",
"horde": "Horde"
},
"Item": {
"item": "Object",
"feature": "Trait",
"weapon": "Weapon",
"armure": "Armor"
}
},
"BOL.attributes.vigor": "Vigor", "BOL.attributes.vigor": "Strength",
"BOL.attributes.halfvigor" : "Half-Vigor", "BOL.attributes.halfvigor" : "Half-Strength",
"BOL.attributes.agility": "Agility", "BOL.attributes.agility": "Agility",
"BOL.attributes.mind": "Mind", "BOL.attributes.mind": "Mind",
"BOL.attributes.appeal": "Appeal", "BOL.attributes.appeal": "Appeal",
@ -33,7 +42,22 @@
"BOL.ui.tab.description": "Description", "BOL.ui.tab.description": "Description",
"BOL.ui.tab.details": "Details", "BOL.ui.tab.details": "Details",
"BOL.ui.tab.spellalchemy": "Spells & Alchemy", "BOL.ui.tab.spellalchemy": "Spells & Alchemy",
"BOL.ui.tab.astrologer": "Astrologer",
"BOL.ui.astrologerPoints": "Points d'Astrologie",
"BOL.ui.astrologerPointsLabel": "Points d'Astrologie actuels",
"BOL.ui.ishoroscopemajor": "Horoscope Majeur (ie de groupe) ?",
"BOL.ui.answer": "Réponse",
"BOL.ui.horoscopefavorable": "Favorable (1dB)",
"BOL.ui.horoscopeunfavorable": "Défavorable (1dM)",
"BOL.ui.horoscopes": "Horoscopes",
"BOL.ui.horoscopesBonus": "Horoscopes (Bonus)",
"BOL.ui.horoscopesMalus": "Horoscopes (Malus)",
"BOL.ui.groupHoroscope": "Horoscrope de Groupe de ",
"BOL.ui.rabble": "Rabble",
"BOL.ui.tough": "Tough",
"BOL.ui.villain": "Villain",
"BOL.ui.properties": "Properties", "BOL.ui.properties": "Properties",
"BOL.ui.description": "Description", "BOL.ui.description": "Description",
"BOL.ui.actions": "Actions", "BOL.ui.actions": "Actions",
@ -115,6 +139,7 @@
"BOL.ui.isSorcerer": "Is Sorcerer ?", "BOL.ui.isSorcerer": "Is Sorcerer ?",
"BOL.ui.isAlchemist": "Is Alchemist ?", "BOL.ui.isAlchemist": "Is Alchemist ?",
"BOL.ui.isPriest": "Is Priest/Druid ?", "BOL.ui.isPriest": "Is Priest/Druid ?",
"BOL.ui.isAstrologer": "Is Astrologer?",
"BOL.ui.circle": "Circle", "BOL.ui.circle": "Circle",
"BOL.ui.spells": "Spells", "BOL.ui.spells": "Spells",
"BOL.ui.focusSpell": "Cast a spell", "BOL.ui.focusSpell": "Cast a spell",
@ -151,6 +176,57 @@
"BOL.ui.armorAgiMalus": "Armor+Shield Modifier (Agi)", "BOL.ui.armorAgiMalus": "Armor+Shield Modifier (Agi)",
"BOL.ui.armorInitMalus": "Armor Modifier (Init)", "BOL.ui.armorInitMalus": "Armor Modifier (Init)",
"BOL.ui.attackValue": "Attack Value", "BOL.ui.attackValue": "Attack Value",
"BOL.ui.attackModifier": "Attack Modifier",
"BOL.ui.weaponbonus": "Cette arme bénéficie déja d'un Dé de Bonus (Arme Favorite prise en compte, par exemple)",
"BOL.ui.initMalus": "Init malus",
"BOL.ui.creature": "Creature",
"BOL.ui.undead": "Undead",
"BOL.ui.daemon": "Daemon",
"BOL.ui.attributaptitude": "Attribut ou Aptitude",
"BOL.ui.always": "Tout les jets (ie toujours)",
"BOL.ui.effectbonusmalus": "Bonus ou Malus à appliquer",
"BOL.ui.boleffects": "Effects (automatic)",
"BOL.ui.modifier": "Modifier",
"BOL.ui.effects": "Ongoing effects",
"BOL.ui.pcname": "PCs",
"BOL.ui.npcname": "NPCs",
"BOL.ui.pclistbutton": "Compact view",
"BOL.ui.noactorfound": "Unknown NPC. The NPC must be known in the world to be displayed here.",
"BOL.ui.deletetitle": "Delete",
"BOL.ui.confirmdelete": "Are you sure to delete this item ?",
"BOL.ui.nomorealchemypoints": "No more Creation Point !",
"BOL.ui.armornoformula": "The Armor {protect.name} has no protection formula !",
"BOL.ui.selectactor": "Select the actors to apply the macro",
"BOL.ui.itemnotfound": "Impossible to find the object of this macro",
"BOL.ui.noinit": "No initiative recorded. Roll initiative from the actor's sheet.",
"BOL.ui.warninitiative": "No available initiative. Roll Initiative for this combat.",
"BOL.ui.isspecial": "Special ?",
"BOL.ui.createEquipment": "Create an equipment",
"BOL.ui.astrology": "Astrology and Horoscope",
"BOL.ui.astrologyMinor": "Build a Minor Horoscope",
"BOL.ui.astrologyMajor": "Build a Major Horoscope",
"BOL.ui.astrologyMajorGroup": "Build a Major Group Horoscope",
"BOL.ui.makeHoroscope": "Build a Horoscope",
"BOL.ui.astrologerRank": "Astrologer Rank",
"BOL.ui.horoscopeCost": "Astrology Points cost",
"BOL.ui.minor": "Minor",
"BOL.ui.major": "Major",
"BOL.ui.majorgroup": "Group Major",
"BOL.ui.horoscopeGroup": "Group Horoscope",
"BOL.ui.horoscopeDiceRemaining": "Remaining Dice",
"BOL.ui.horoscopeDiceMax": "Max Dice",
"BOL.ui.astrologyNoPoints": "You do not have enough Astrology Points!",
"BOL.ui.newEquipment": "New equipment",
"BOL.ui.newNaturalWeapon": "Natural weapon",
"BOL.ui.newNaturalProtection": "Natural protection",
"BOL.ui.createNaturalWeapon": "Create a natural weapon",
"BOL.ui.createNaturalProtection": "Create a natural protection",
"BOL.ui.hordeSize": "Horde size",
"BOL.ui.hordeAttack": "Horde attack",
"BOL.ui.hordeName": "Name of the Horde",
"BOL.ui.criticallegend": "Legendary Success",
"BOL.ui.hordeHP": "Horde Vitality (1 member)",
"BOL.ui.hordehp": "Horde Vitality (total)",
"BOL.featureCategory.origins": "Origins", "BOL.featureCategory.origins": "Origins",
"BOL.featureCategory.races": "Races", "BOL.featureCategory.races": "Races",
@ -168,6 +244,11 @@
"BOL.featureSubtypes.language": "Language", "BOL.featureSubtypes.language": "Language",
"BOL.featureSubtypes.gods": "Faith & Gods", "BOL.featureSubtypes.gods": "Faith & Gods",
"BOL.featureSubtypes.fightOption": "Combat Option", "BOL.featureSubtypes.fightOption": "Combat Option",
"BOL.featureSubtypes.effect": "Effect",
"BOL.featureSubtypes.effects": "Effects",
"BOL.featureSubtypes.boleffect": "Effect",
"BOL.featureSubtypes.horoscope": "Horoscope",
"BOL.featureSubtypes.xplog": "XP Journal",
"BOL.bougette.nomoney": "Nothing", "BOL.bougette.nomoney": "Nothing",
"BOL.bougette.tolive": "To live", "BOL.bougette.tolive": "To live",
@ -182,6 +263,7 @@
"BOL.fightOptionTypes.fulldefense": "Full Defense", "BOL.fightOptionTypes.fulldefense": "Full Defense",
"BOL.fightOptionTypes.defense": "Defensive Posture", "BOL.fightOptionTypes.defense": "Defensive Posture",
"BOL.fightOptionTypes.attack": "Offensive Posture", "BOL.fightOptionTypes.attack": "Offensive Posture",
"BOL.fightOptionTypes.other": "Other",
"BOL.itemCategory.object": "Object", "BOL.itemCategory.object": "Object",
"BOL.itemCategory.equipment": "Equipment", "BOL.itemCategory.equipment": "Equipment",
@ -191,6 +273,7 @@
"BOL.itemCategory.other": "Other", "BOL.itemCategory.other": "Other",
"BOL.itemCategory.capacity" : "Capacity", "BOL.itemCategory.capacity" : "Capacity",
"BOL.itemCategory.alchemy": "Alchemy", "BOL.itemCategory.alchemy": "Alchemy",
"BOL.itemCategory.vehicleweapon": "Vehicle weapon",
"BOL.combatCategory.protections": "Protections", "BOL.combatCategory.protections": "Protections",
"BOL.combatCategory.shields": "Shields", "BOL.combatCategory.shields": "Shields",
@ -390,11 +473,14 @@
"BOL.chat.rolldamage": "Roll for damages", "BOL.chat.rolldamage": "Roll for damages",
"BOL.chat.rolldamage6": "Roll for damages +6", "BOL.chat.rolldamage6": "Roll for damages +6",
"BOL.chat.rolldamage12": "Roll for damages +12 (1 HP)", "BOL.chat.rolldamage12": "Roll for damages +12 (1 HP)",
"BOL.chat.rolldamage12Legend": "Roll for damages +12",
"BOL.chat.damageresult": "Damages of {name} : {total}", "BOL.chat.damageresult": "Damages of {name} : {total}",
"BOL.chat.damagetarget": "Target : {target}", "BOL.chat.damagetarget": "Target : {target}",
"BOL.chat.applydamagetotarget": "Apply damages to the target", "BOL.chat.applydamagetotarget": "Apply damages to the target",
"BOL.chat.fightoption": "Combat options", "BOL.chat.fightoption": "Combat options",
"BOL.chat.reroll": "Reroll (1 HP)", "BOL.chat.reroll": "Reroll (1 HP)",
"BOL.chat.heroicreminder": "In addition of the actions below, you can : <ul><li>Carnage : Do a second free attack on the same opponent</li><li>Precise : 1 Malus Die on your opponent on a chosen location</li><li>Disarm</li><li>Rabble Massacre</li><li>Prone : Push your opponent on the ground (max +1 size)</li></ul>If you spent 1 Hero Point in addition, all these effects can be doubled.",
"BOL.chat.legendaryreminder": "In addition of the actions below, you can twice the following actions: <ul><li>Carnage : Do a second free attack on the same opponent</li><li>Precise : 1 Malus Die on your opponent on a chosen location</li><li>Disarm</li><li>Rabble Massacre</li><li>Prone : Push your opponent on the ground (max +1 size)</li></ul>",
"BOL.chat.toheroic": "Convert to Mighty success (1 HP)", "BOL.chat.toheroic": "Convert to Mighty success (1 HP)",
"BOL.chat.tolegend": "Convert to Legendary succes (1 HP)", "BOL.chat.tolegend": "Convert to Legendary succes (1 HP)",
"BOL.chat.hurttitle": "{name} is going to receive {damageTotal} damages !", "BOL.chat.hurttitle": "{name} is going to receive {damageTotal} damages !",
@ -412,6 +498,51 @@
"BOL.chat.spell": "Spell", "BOL.chat.spell": "Spell",
"BOL.chat.spellcost": "Power Points cost", "BOL.chat.spellcost": "Power Points cost",
"BOL.chat.spellremaining": "Remaining Power Points", "BOL.chat.spellremaining": "Remaining Power Points",
"BOL.chat.nodamagesummary": "No damage ....",
"BOL.chat.damageresume": "{name} as taken wounds ...",
"BOL.chat.fumblemessage": "If you accept the consequences of a fumble (GM choice), you can get 1 additionnal Hero Point.",
"BOL.chat.rangeinfo": "Range/Throw of {attackerName} to {defenderName}",
"BOL.chat.rangeweaponinfo": "Weapon : {weaponName} - Base range {weaponRange}",
"BOL.chat.rangeout": "Modifier : Out of range",
"BOL.chat.range0": "Modifier : Point blank (+1)",
"BOL.chat.range1": "Modifier : Short Range (0)",
"BOL.chat.range2": "Modifier : Middle Range (-1)",
"BOL.chat.range3": "Modifier : Long Range (-2)",
"BOL.chat.range4": "Modifier : Very Long Range (-4)",
"BOL.chat.range5": "Modifier : Extrem Range (-6)",
"BOL.chat.range6": "Modifier : Max Range (-8)",
"BOL.chat.rangeprefix": "Evaluated distance : ",
"BOL.chat.rangevisible": "Line of sight is cleared between tokens.",
"BOL.chat.rangenotvisible": "Line of sight is blocked between tokens.",
"BOL.chat.rangetitle": "GM Information",
"BOL.chat.weaponreroll1": "As a reminder, this weapon re-roll 1 whend rolling for damage.",
"BOL.chat.rollbougette": "Budget roll",
"BOL.chat.bougettesuccess": "Your budget remains unchanged !",
"BOL.chat.bougettefailure": "You spent too much money, your budget is going down by one level...",
"BOL.chat.initiative": "Initiative rank (10 to 1)",
"BOL.chat.horoscope": "Horoscope",
"BOL.chat.horoscopepoints": "Cost : {points} Astrology Points",
"BOL.chat.horoscopeminorsuccess": "Your minor horoscope is a success : change the horoscope name in your sheet. You will benefit of 1 Bonus Die for the given situation.",
"BOL.chat.horoscopeminorfailure": "Your minor horoscope mineur isa failure : change the horoscope name in your sheet. Vous will suffer 1 Malus Die for the given situation.",
"BOL.chat.horoscopemajorsuccess": "Your major horoscope is a success : {horoscopeName} gets 1 new Hero Point for this adventure. This point has been automatically added.",
"BOL.chat.horoscopemajorfailure": "Your major horoscope is a failure : {horoscopeName} looses 1 Hero Point for this adventure. This point has been automatically substracted.",
"BOL.chat.horoscopemajorgroupsuccess": "Your major group horoscope majeur is a success. Your and your party gets {careerBonus} Bonus Dice during this adventure.",
"BOL.chat.horoscopemajorgroupfailure": "Your major group horoscope is a failure. You and your party suffers {careerBonus} Malus Dice durig this adventure.",
"BOL.chat.usedhoroscope": "Horoscope has been used",
"BOL.chat.horoscopedeleted": "The Horoscopes used are deleted automatically.",
"BOL.chat.criticaloptions": "Critical success !! You can (select 1 option) :",
"BOL.chat.criticalcarnage": "Dual attack : you gain 1 free attack. This second attack can't benefit from a Hero/Villain Point.",
"BOL.chat.criticalplus6": "Devastating : damage +6 aux dommages (cf button below).",
"BOL.chat.criticalprecise": "Precise : You hit to harm your opponent. Describe what your are doing, and if the GM agree, your opponent will suffer 1 Malus Die for the relevant actions.",
"BOL.chat.criticalunarm": "Disarm : Si your opponnent has a weapon in hand, you disarm him.",
"BOL.chat.criticalrabble": "Rabble Massacre : If you fight against rabble, damages results indicate the amount of rabble you kill.",
"BOL.chat.criticalpush": "Prone : If the size allow it, you push your opponent on the ground. He suffer 1 Malus Die for all his actions during the next round.",
"BOL.chat.criticalup": "Transform to Legendary : If you spent 1 Hero Point/Villain, you can transform this Heroic success into a Legendary success.You can the choose 2 options in this list above.",
"BOL.chat.criticalinfo": "This is an Heroic success ! Choose your options and effects !",
"BOL.chat.criticallegendaryinfo": "This is a Legendary succes ! Choisissez vos options et effets !",
"BOL.chat.criticalbuttonjournal": "Legendary/Heroic Success",
"BOL.chat.nodamage": "Do not apply damages",
"BOL.chat.armorRoll": "Armor roll",
"BOL.dialog.soeasy": "So easy (+4)", "BOL.dialog.soeasy": "So easy (+4)",
"BOL.dialog.veryeasy": "Very easy (+2)", "BOL.dialog.veryeasy": "Very easy (+2)",
@ -450,6 +581,25 @@
"BOL.chat.welcome2": "Books are necessary to play, and ca be found here : http://www.ludospherik.fr/content/14-barbarians-of-lemuria", "BOL.chat.welcome2": "Books are necessary to play, and ca be found here : http://www.ludospherik.fr/content/14-barbarians-of-lemuria",
"BOL.chat.welcome3": "The integrated maps are authorized by Guillaume Tavernier and Ludospherik. Thanks to them !.", "BOL.chat.welcome3": "The integrated maps are authorized by Guillaume Tavernier and Ludospherik. Thanks to them !.",
"BOL.chat.welcome4": "All support for this system is available on this Discord server : https://discord.gg/pPSDNJk", "BOL.chat.welcome4": "All support for this system is available on this Discord server : https://discord.gg/pPSDNJk",
"BOL.chat.welcome5": "Good game in Lemuria !" "BOL.chat.welcome5": "Good game in Lemuria !",
"BOL.chat.welcome6": "",
"BOL.settings.rollArmor": "Roll for armor",
"BOL.settings.rollArmorTooltip": "Roll for armor value, fixed value if unchecked",
"BOL.settings.useBougette": "Use Bougette (fan-made French rule)",
"BOL.settings.useBougetteTooltip": "Use the Bougette value, as described in Annales Lemurienne from LeRatierBretonnien (https://www.lahiette.com/leratierbretonnien/)",
"BOL.settings.removeDead": "Automatically remove dead NPCs by end of the round",
"BOL.settings.removeDeadTooltip": "Remove NPCs Automatically when HP are 0 or less, at the end of each round",
"BOL.settings.diceFormula": "Dice Formula",
"BOL.settings.diceFormulaTooltip": "Main dice formula (2d6 per default)",
"BOL.settings.diceSuccessValue" : "Success value",
"BOL.settings.diceSuccessValueTooltip": "Value of the success threshold (9 per default for 2d6)",
"BOL.settings.diceCriticalValue" : "Critical success value",
"BOL.settings.diceCriticalValueTooltip": "Minimum value for critical success (12 per default for 2d6)",
"BOL.settings.diceCriticalFailure" : "Critical failure value",
"BOL.settings.diceCriticalFailureTooltip": "Maximum value for critical failure (2 per default for 2d6)",
"BOL.settings.defaultLogoActorSheetPath" : "Path for Actor sheet logo",
"BOL.settings.defaultLogoPathActorSheetTooltip": "Path of the Actor sheet logo (346 x 200, default : /systems/bol/ui/logo.webp)",
"BOL.settings.defaultLogoTopLeftPath" : "Path for main top left logo",
"BOL.settings.defaultLogoTopLeftPathTooltip": "Path of the logo in the top left window (718 x 416, default : /systems/bol/ui/logo2.webp)"
} }

596
lang/es.json Normal file
View File

@ -0,0 +1,596 @@
{
"TYPES": {
"Actor": {
"character": "PJ",
"encounter": "PNJ",
"npc": "PNJ",
"vehicle": "Vehículo"
},
"Item": {
"item": "Objeto",
"feature": "Rasgo",
"weapon": "Arma",
"armure": "Armadura"
}
},
"BOL.attributes.vigor": "Fuerza",
"BOL.attributes.halfvigor" : "Media-Fuerza",
"BOL.attributes.agility": "Agilidad",
"BOL.attributes.mind": "Mente",
"BOL.attributes.appeal": "Atractivo",
"BOL.aptitudes.init": "Iniciativa",
"BOL.aptitudes.melee": "Melé",
"BOL.aptitudes.ranged": "Distancia",
"BOL.aptitudes.def": "Defensa",
"BOL.aptitudes.prot": "Protección",
"BOL.resources.hp": "Vitalidad",
"BOL.resources.hero": "Héroe",
"BOL.resources.faith": "Fe",
"BOL.resources.creation": "Creación",
"BOL.resources.power": "Poder",
"BOL.resources.villainy": "Villano",
"BOL.resources.alchemypoints": "Puntos Alquimia",
"BOL.traits.xp": "Experiencia",
"BOL.ui.tab.stats": "Atributos",
"BOL.ui.tab.combat": "Combate",
"BOL.ui.tab.actions": "Acciones",
"BOL.ui.tab.features": "Rasgos",
"BOL.ui.tab.equipment": "Equipo",
"BOL.ui.tab.description": "Descripción",
"BOL.ui.tab.details": "Detalles",
"BOL.ui.tab.spellalchemy": "Alquimia",
"BOL.ui.tab.astrologer": "Astrólogo",
"BOL.ui.astrologerPoints": "Puntos Astrología",
"BOL.ui.astrologerPointsLabel": "Puntos Astrología actuales",
"BOL.ui.ishoroscopemajor": "¿Horóscopo Mayor (ej del grupo)?",
"BOL.ui.answer": "Respuesta",
"BOL.ui.horoscopefavorable": "Favorable (1dB)",
"BOL.ui.horoscopeunfavorable": "Desfavorable (1dM)",
"BOL.ui.horoscopes": "Horóscopos",
"BOL.ui.horoscopesBonus": "Horóscopos (Ventaja)",
"BOL.ui.horoscopesMalus": "Horóscopos (Desventaja)",
"BOL.ui.groupHoroscope": "Horóscropo de Grupo de ",
"BOL.ui.rabble": "Chusma",
"BOL.ui.tough": "Matones",
"BOL.ui.villain": "Villanos",
"BOL.ui.properties": "Propiedades",
"BOL.ui.description": "Descripción",
"BOL.ui.actions": "Acciones",
"BOL.ui.capacities": "Capacidad",
"BOL.ui.damages": "Daño",
"BOL.ui.details": "Detalles",
"BOL.ui.category": "Categoría",
"BOL.ui.subcategory": "Sub-Categoría",
"BOL.ui.type": "Tipo",
"BOL.ui.subtype": "Subtipo",
"BOL.ui.attribute" : "Atributo",
"BOL.ui.aptitude" : "Habilidad",
"BOL.ui.advantages" : "Ventaja/Desventaja",
"BOL.ui.modifiers": "Modificador",
"BOL.ui.item": "Objeto",
"BOL.ui.edit": "Editar",
"BOL.ui.unequip": "Quitar",
"BOL.ui.equip": "Equipar",
"BOL.ui.delete": "Borrar",
"BOL.ui.roll" : "Tirar",
"BOL.ui.equipment" : "Equipo",
"BOL.ui.equipmentProperties" : "Propiedades Equipo",
"BOL.ui.weaponAttack" : "Ataque Arma",
"BOL.ui.weaponProperties" : "Propiedades Arma",
"BOL.ui.protectionProperties" : "Propiedades Protección",
"BOL.ui.magicalProperties" : "Propiedades Mágicas",
"BOL.ui.alchemyProperties": "Propiedades Alquimia",
"BOL.ui.armor" : "Armadura",
"BOL.ui.reach" : "Alcance",
"BOL.ui.weapon" : "Arma",
"BOL.ui.melee" : "Melé",
"BOL.ui.ranged" : "Distancia",
"BOL.ui.protection" : "Protección",
"BOL.ui.shield" : "Escudo",
"BOL.ui.blocking" : "Bloqueo",
"BOL.ui.range" : "Alcance",
"BOL.ui.quantity" : "Cantidad",
"BOL.ui.qty" : "Cant.",
"BOL.ui.slot" : "Hueco",
"BOL.ui.weight" : "Peso",
"BOL.ui.price": "Precio",
"BOL.ui.cancel": "Cancelar",
"BOL.ui.submit": "OK",
"BOL.ui.attributeCheck" : "Tirada Atributo",
"BOL.ui.aptitudeCheck" : "Tirada Habilidad",
"BOL.ui.weaponCheck" : "Tirada Arma",
"BOL.ui.spellCheck" : "Tirada Conjuro",
"BOL.ui.careers" : "Oficios",
"BOL.ui.boons" : "Ventaja",
"BOL.ui.flaws" : "Desventaja",
"BOL.ui.rank" : "Rango",
"BOL.ui.success" : "Éxito",
"BOL.ui.failure" : "Fallo",
"BOL.ui.fumble" : "Pifia",
"BOL.ui.critical" : "Éxito Asombroso",
"BOL.ui.criticallegend" : "Éxito Legendario",
"BOL.ui.maneuvers" : "Maniobras",
"BOL.ui.stacksize" : "Tamaño Pila (máx)",
"BOL.ui.weapons" : "Armas",
"BOL.ui.protections" : "Protección",
"BOL.ui.ammos" : "Munición",
"BOL.ui.containers" : "Contenedor",
"BOL.ui.treasure" : "Tesoro",
"BOL.ui.vehicles" : "Vehículo/Montura",
"BOL.ui.misc" : "Varios",
"BOL.ui.vehicleProperties" : "Propiedades Vehículo",
"BOL.ui.speed" : "Velocidad",
"BOL.ui.noWeaponName" : "Nombre Arma",
"BOL.ui.targetDefence": "Defensa",
"BOL.ui.applyShieldMalus": "Aplicar Mod. Escudo",
"BOL.ui.shieldMalus": "Mod. Escudo",
"BOL.ui.defenseScore": "Valor Defensa",
"BOL.ui.defender": "Defensor",
"BOL.ui.difficulty": "Dificultad",
"BOL.ui.spellProperties": "Propiedades Conjuro",
"BOL.ui.duration": "Duración",
"BOL.ui.spellkeep": "Mantenimiento",
"BOL.ui.concentrate": "Concentración",
"BOL.ui.registerInit": "Registrar Inic.",
"BOL.ui.isSorcerer": "¿Es Hechicero?",
"BOL.ui.isAlchemist": "¿Es Alquimista?",
"BOL.ui.isPriest": "¿Es Clérigo/Druida?",
"BOL.ui.isAstrologer": "¿Es Astrólogo?",
"BOL.ui.circle": "Círculo",
"BOL.ui.spells": "Conjuros",
"BOL.ui.focusSpell": "Lanzar conjuro",
"BOL.ui.sorcererRank" : "Rango Hechicero",
"BOL.ui.alchemistRank": "Rango Alquimista",
"BOL.ui.mandatoryconditions": "Condiciones obligatorias",
"BOL.ui.optionnalconditions": "Condiciones opcionales",
"BOL.ui.ppcost": "Coste Puntos Poder",
"BOL.ui.ppAvailable": "Puntos Poder Disponibles",
"BOL.ui.pccost": "Coste Puntos Creación",
"BOL.ui.pcnow": "Puntos Creación Actuales",
"BOL.ui.alchemyType": "Tipo",
"BOL.ui.alchemy": "Alquimia",
"BOL.ui.makeAlchemy": "Realizar Alquimia",
"BOL.ui.alchemyCostTotal": "Coste Total Puntos Alquimia",
"BOL.ui.alchemyInvest": "Invertir Puntos Alquimia",
"BOL.ui.alchemyCurrent": "Puntos Alquimia actuales en Objeto",
"BOL.ui.advance": "Estado",
"BOL.ui.isadvantage": "¿Da un dado ventaja?",
"BOL.ui.bonusmalus": "Ventaja/desventaja adicional",
"BOL.ui.nbdices": "Número Dados",
"BOL.ui.totalmod": "Mod. Total",
"BOL.ui.rangeModifiers": "Mod. distancia",
"BOL.ui.money": "Dinero",
"BOL.ui.moneyTitle": "Tesoro",
"BOL.ui.fightOption": "Opciones Combate",
"BOL.ui.none": "Ninguno",
"BOL.ui.fightOptionType": "Tipo Opción Combate",
"BOL.ui.activated": "Activado",
"BOL.ui.deactivated": "Desactivado",
"BOL.ui.status": "Estado",
"BOL.ui.toactivated": "Activo",
"BOL.ui.todeactivated": "Inactivo",
"BOL.ui.armorAgiMalus": "Mod. Armadura+Escudo (Agi)",
"BOL.ui.armorInitMalus": "Mod. Armadura (Inic)",
"BOL.ui.attackValue": "Valor Ataque",
"BOL.ui.attackModifier": "Mod. Ataque",
"BOL.ui.weaponbonus": "Esta arma se beneficia de un Dado de ventaja (ej Arma Personal)",
"BOL.ui.initMalus": "Desventaja Inic.",
"BOL.ui.creature": "Criatura",
"BOL.ui.undead": "No-muerto",
"BOL.ui.daemon": "Demonio",
"BOL.ui.attributaptitude": "Atributo o Habilidad",
"BOL.ui.always": "Todos (ej siempre)",
"BOL.ui.effectbonusmalus": "Ventaja o Desventaja a aplicar",
"BOL.ui.boleffects": "Efectos (automático)",
"BOL.ui.modifier": "Modificador",
"BOL.ui.effects": "Efectos Activos",
"BOL.ui.pcname": "PCs",
"BOL.ui.npcname": "NPCs",
"BOL.ui.pclistbutton": "Vista compacta",
"BOL.ui.noactorfound": "PNJ Desconocido. El PNJ debe ser conocido en el mundo de juego para poder mostrase.",
"BOL.ui.deletetitle": "Borrar",
"BOL.ui.confirmdelete": "¿Seguro que quieres borrar este objeto?",
"BOL.ui.nomorealchemypoints": "¡Sin Puntos de Creación!",
"BOL.ui.armornoformula": "La Armadura {protect.name} no dispone de fórmula de protección!",
"BOL.ui.selectactor": "Selecciona un actora para aplicar la macro",
"BOL.ui.itemnotfound": "Imposible encontrar el objeto de esta macro",
"BOL.ui.noinit": "Sin iniciativa. Tira por iniciativa desde la hoja del actor.",
"BOL.ui.warninitiative": "Iniciativa no disponible. Tira Iniciativa para este combate.",
"BOL.ui.isspecial": "¿Especial?",
"BOL.ui.createEquipment": "Crear equipo",
"BOL.ui.astrology": "Astrología",
"BOL.ui.astrologyMinor": "Crear Horóscopo Menor",
"BOL.ui.astrologyMajor": "Crear Horóscopo Mayor",
"BOL.ui.astrologyMajorGroup": "Crear Grupo Horóscopo Mayor",
"BOL.ui.makeHoroscope": "Crear Horóscopo",
"BOL.ui.astrologerRank": "Rango Astrólogo",
"BOL.ui.horoscopeCost": "Coste Puntos Astrología",
"BOL.ui.minor": "Menor",
"BOL.ui.major": "Mayor",
"BOL.ui.majorgroup": "Grupo Mayor",
"BOL.ui.horoscopeGroup": "Grupo Horóscopo",
"BOL.ui.horoscopeDiceRemaining": "Dados Restantes",
"BOL.ui.horoscopeDiceMax": "Dado Máx",
"BOL.ui.astrologyNoPoints": "¡No dispones de suficientes Puntos Astrología!",
"BOL.ui.newEquipment": "Nuevo equipo",
"BOL.ui.newNaturalWeapon": "Arma natural",
"BOL.ui.newNaturalProtection": "Protección natural",
"BOL.ui.createNaturalWeapon": "Crear un arma natural",
"BOL.ui.createNaturalProtection": "Crear una protección natural",
"BOL.featureCategory.origins": "Origen",
"BOL.featureCategory.races": "Raza",
"BOL.featureCategory.careers": "Oficios",
"BOL.featureCategory.boons": "Ventajas",
"BOL.featureCategory.flaws": "Desventajas",
"BOL.featureCategory.languages": "Idiomas",
"BOL.featureCategory.fightoptions": "Opciones Combate",
"BOL.featureSubtypes.origin": "Origen",
"BOL.featureSubtypes.race": "Raza",
"BOL.featureSubtypes.career": "Oficio",
"BOL.featureSubtypes.boon": "Ventaja",
"BOL.featureSubtypes.flaw": "Desventaja",
"BOL.featureSubtypes.language": "Idioma",
"BOL.featureSubtypes.gods": "Dioses",
"BOL.featureSubtypes.fightOption": "Opción Combate",
"BOL.featureSubtypes.effect": "Efecto",
"BOL.featureSubtypes.effects": "Efectos",
"BOL.featureSubtypes.boleffect": "Efecto",
"BOL.featureSubtypes.horoscope": "Horóscopo",
"BOL.featureSubtypes.xplog": "Diario PX",
"BOL.bougette.nomoney": "Nada",
"BOL.bougette.tolive": "Vivir justo",
"BOL.bougette.easylife": "Vida simple",
"BOL.bougette.luxury" : "Vida lujosa",
"BOL.bougette.rich": "¡Rico!",
"BOL.fightOptionTypes.armor": "Ataque Armadura",
"BOL.fightOptionTypes.intrepid": "Ataque Total",
"BOL.fightOptionTypes.twoweaponsdef": "Dos Armas (Defensa)",
"BOL.fightOptionTypes.twoweaponsatt": "Dos Armas (Ataque)",
"BOL.fightOptionTypes.fulldefense": "Defensa Total",
"BOL.fightOptionTypes.defense": "Posición Defensiva",
"BOL.fightOptionTypes.attack": "Posición Ofensiva",
"BOL.fightOptionTypes.other": "Otro",
"BOL.itemCategory.object": "Objeto",
"BOL.itemCategory.equipment": "Equipo",
"BOL.itemCategory.consumable": "Consumible",
"BOL.itemCategory.spell": "Conjuro",
"BOL.itemCategory.vehicle": "Montura/Vehículo",
"BOL.itemCategory.other": "Otro",
"BOL.itemCategory.capacity" : "Capacidad",
"BOL.itemCategory.alchemy": "Alquimia",
"BOL.itemCategory.vehicleweapon": "Arma Vehicular",
"BOL.combatCategory.protections": "Protecciones",
"BOL.combatCategory.shields": "Escudos",
"BOL.combatCategory.melee": "Melé",
"BOL.combatCategory.ranged": "Distancia",
"BOL.combatCategory.fightOptions": "Opciones combate",
"BOL.combatCategory.natural": "Armas Naturales",
"BOL.equipmentCategory.weapon": "Arma",
"BOL.equipmentCategory.armor": "Armadura",
"BOL.equipmentCategory.protection": "Protección",
"BOL.equipmentCategory.shield": "Escudo",
"BOL.equipmentCategory.helm": "Casco",
"BOL.equipmentCategory.jewel": "Joya",
"BOL.equipmentCategory.scroll": "Pergamino",
"BOL.equipmentCategory.ammunition": "Munición",
"BOL.equipmentCategory.container": "Contenedor",
"BOL.equipmentCategory.currency": "Moneda",
"BOL.equipmentCategory.other": "Otro",
"BOL.protectionCategory.armor": "Armadura",
"BOL.protectionCategory.shield": "Escudo",
"BOL.protectionCategory.helm": "Casco",
"BOL.protectionCategory.other": "Otro",
"BOL.spellItem.charm": "Truco",
"BOL.spellItem.circle1": "Primer Círculo",
"BOL.spellItem.circle2": "Segundo Círculo",
"BOL.spellItem.circle3": "Tercer Círculo",
"BOL.alchemyItem.common": "Común",
"BOL.alchemyItem.scarce": "Escaso",
"BOL.alchemyItem.legend": "Legendario",
"BOL.alchemyItem.mythic": "Mítico",
"BOL.weaponCategory.melee": "Melé",
"BOL.weaponCategory.ranged": "Distancia",
"BOL.weaponCategory.other": "Otro",
"BOL.itemProperty.damageMultiplier": "Multiplicador Daño",
"BOL.itemProperty.attackBonusDice": "Dado Ventaja Ataque",
"BOL.itemProperty.equipable": "Equipable",
"BOL.itemProperty.protection": "Protección",
"BOL.itemProperty.blocking": "Bloqueo",
"BOL.itemProperty.magical": "Mágico",
"BOL.itemProperty.concealable": "Ocultable",
"BOL.itemProperty.2H": "Arma 2M",
"BOL.itemProperty.helm": "Casco",
"BOL.itemProperty.improvised": "Improvisada",
"BOL.itemProperty.shield": "Escudo",
"BOL.itemProperty.melee": "Melé",
"BOL.itemProperty.throwable": "Arrojadiza",
"BOL.itemProperty.ignoreshield": "Ignora Escudo",
"BOL.itemProperty.bashing": "Golpea",
"BOL.itemProperty.stackable": "Apilable",
"BOL.itemProperty.ranged": "Distancia",
"BOL.itemProperty.weapon": "Arma",
"BOL.itemProperty.reloadable": "Recargable",
"BOL.itemProperty.worn": "Equipada",
"BOL.itemProperty.spell" : "Conjuro",
"BOL.itemProperty.armor" : "Armadura",
"BOL.itemProperty.consumable" : "Consumible",
"BOL.itemProperty.bow" : "Arco",
"BOL.itemProperty.crossbow" : "Ballesta",
"BOL.itemProperty.throwing" : "Arrojadiza",
"BOL.itemProperty.activable" : "Activable",
"BOL.itemProperty.powder" : "Polvo",
"BOL.itemProperty.attackAttribute" : "Ataque (Atributo)",
"BOL.itemProperty.attackAptitude" : "Ataque (Habilidad)",
"BOL.itemProperty.attackModifiers" : "Ataque (Modificadores)",
"BOL.itemProperty.attackReroll1" : "Ataque (Relanzar 1s)",
"BOL.itemProperty.damage" : "Daño",
"BOL.itemProperty.damageModifiers" : "Daño (Modificador)",
"BOL.itemProperty.damageAttribute" : "Daño (Atributo)",
"BOL.itemProperty.damageSpecial" : "Damage (Especial)",
"BOL.itemProperty.damageReroll1" : "Relanzar 1s",
"BOL.itemProperty.range" : "Alcance (en m)",
"BOL.itemProperty.soakFormula": "Absorver (Fórmula)",
"BOL.itemProperty.soakModifiers": "Absorver (Modificador)",
"BOL.itemProperty.soakValue": "Absorver (Valor Defecto)",
"BOL.itemProperty.armorQuality": "Calidad Armadura",
"BOL.itemProperty.blockingMalus" : "Mod. Bloqueo",
"BOL.itemProperty.blockingAttacksBlocked" : "Ataques bloqueados",
"BOL.itemProperty.blocking1Attack" : "Bloquea 1 ataque",
"BOL.itemProperty.blockingAllAttacks" : "Bloquea todos ataques",
"BOL.itemProperty.slot" : "Hueco",
"BOL.itemProperty.reload": "Recarga (Acción)",
"BOL.itemProperty.weaponSize" : "Tamaño Arma",
"BOL.itemProperty.difficulty": "Dificultad",
"BOL.itemProperty.natural": "Arma natural",
"BOL.itemProperty.onlymodifier": "Sólo modificador (ej criatura)",
"BOL.itemStat.quantity": "Cantidad",
"BOL.itemStat.weight": "Peso",
"BOL.itemStat.price": "Precio",
"BOL.itemStat.range": "Alcance",
"BOL.itemStat.damage": "Daño",
"BOL.itemStat.reload": "Recargar (Acción)",
"BOL.itemStat.soak": "Absorver",
"BOL.itemStat.blocking": "Bloqueo",
"BOL.itemStat.modifiers": "Modificadores",
"BOL.weaponSize.unarmed" : "Desarmado",
"BOL.weaponSize.improvised" : "Improvisada",
"BOL.weaponSize.light" : "Ligera",
"BOL.weaponSize.medium" : "Mediana",
"BOL.weaponSize.heavy" : "Pesada",
"BOL.itemModifiers.init": "Mod. (Iniciativa)",
"BOL.itemModifiers.social": "Mod. (Social)",
"BOL.itemModifiers.agility": "Mod. (Agilidad)",
"BOL.itemModifiers.powercost": "Mod. (Coste adicional en PP)",
"BOL.itemBlocking.malus": "Modificador",
"BOL.itemBlocking.nbAttacksPerRound": "Agilidad",
"BOL.soakFormula.none" : "-",
"BOL.soakFormula.light" : "Ligero (Cancela d6-3 daño)",
"BOL.soakFormula.medium" : "Mediano (Cancela d6-2 daño)",
"BOL.soakFormula.heavy" : "Pesado (Cancela d6-1 daño)",
"BOL.armorQuality.none" : "-",
"BOL.armorQuality.light" : "Ligera",
"BOL.armorQuality.lightQ" : "Ligera Calidad",
"BOL.armorQuality.lightSup" : "Ligera Superior",
"BOL.armorQuality.lightLeg" : "Ligera Legendaria",
"BOL.armorQuality.medium" : "Mediana",
"BOL.armorQuality.mediumQ" : "Mediana Calidad",
"BOL.armorQuality.mediumSup" : "Mediana Superior",
"BOL.armorQuality.mediumLeg" : "Mediana Legendaria",
"BOL.armorQuality.heavy" : "Pesada",
"BOL.armorQuality.heavyQ" : "Pesada Calidad",
"BOL.armorQuality.heavySup" : "Pesada Superior",
"BOL.armorQuality.heavyLeg" : "Pesada Legendaria",
"BOL.equipmentSlots.none" : "-",
"BOL.equipmentSlots.head" : "Cabeza",
"BOL.equipmentSlots.neck" : "Cuello",
"BOL.equipmentSlots.shoulders" : "Ombros",
"BOL.equipmentSlots.body" : "Cuerpo",
"BOL.equipmentSlots.rhand" : "Mano derecha",
"BOL.equipmentSlots.lhand" : "Mano izquierda",
"BOL.equipmentSlots.2hands" : "2 manos",
"BOL.equipmentSlots.rarm" : "Brazo derecho",
"BOL.equipmentSlots.larm" : "Brazo izquierdo",
"BOL.equipmentSlots.chest" : "Pecho",
"BOL.equipmentSlots.belt" : "Cintura",
"BOL.equipmentSlots.legs" : "Piernas",
"BOL.equipmentSlots.feet" : "Pies",
"BOL.equipmentSlots.finder" : "Dedo",
"BOL.equipmentSlots.ear" : "Oreja",
"BOL.vehicleCategory.mount" : "Montura terrestre",
"BOL.vehicleCategory.flying" : "Montura voladora",
"BOL.vehicleCategory.boat" : "Bote",
"BOL.vehicleCategory.other" : "Otro",
"BOL.range.PointBlank": "Quemarropa",
"BOL.range.Short": "Corta",
"BOL.range.Medium": "Media",
"BOL.range.Long": "Larga",
"BOL.range.VeryLong": "Distante",
"BOL.range.Extreme": "Extrema",
"BOL.range.Maximum": "Límite",
"BOL.notification.MacroMultipleTokensSelected": "¡Has seleccionado varios tokens!",
"BOL.notification.MacroNoActorAvailable": "¡No se pudo marcar el actor como objetivo!",
"BOL.notification.MacroNoTokenSelected": "¡Debes seleccionar un token!",
"BOL.size.tiny": "Minúsculo",
"BOL.size.verysmall": "Muy pequeño",
"BOL.size.small" : "Pequeño",
"BOL.size.medium" : "Mediano",
"BOL.size.large" : "Grande",
"BOL.size.verylarge": "Muy Grande",
"BOL.size.huge" : "Monstruoso",
"BOL.size.massive" : "Monumental",
"BOL.size.enormous": "Enorme",
"BOL.size.gigantic": "Gigante",
"BOL.size.immense": "Inmenso",
"BOL.size.colossal": "Colosal",
"BOL.chat.fightactive": "¡Activa la opción de combate {foName} este asalto!",
"BOL.chat.fightunactive": "¡Desactiva la opción de combate {foName} este asalto!",
"BOL.chat.isdead": "¡{name} esta muerto!",
"BOL.chat.epitaph": "¡Guardar el honor de su nombre y su memoria!",
"BOL.chat.vitalityzero": "Vitalidad de {name} es {hp}: ¡va a caer inconsciente!",
"BOL.chat.vitalityheroism": "Puedes gastar 1 Punto Héroe para levantarte en 1 asalto.",
"BOL.chat.vitalityheroismhint": "En este caso, tu vitalidad se incrementa a su máximo dividido por 2.",
"BOL.chat.vitalitydying": "Vitalidad de {name} es {hp}! Se esta muriendo...",
"BOL.chat.vitalitydyingheroism": "Puedes gastar 1 Punto Héroe para Desafiar la Muerte.",
"BOL.chat.alchemytitle": "Receta alquímica: {name}",
"BOL.chat.alchemypoints": "Coste Puntos Creación: {pcCostCurrent}",
"BOL.chat.alchemysuccess": "¡La receta alquímica es un éxito!<br>Crea el objeto/efecto relevante en el inventario.<br>El estadio se reinicia.",
"BOL.chat.alchemyfailure": "¡La receta alquímica ha fallado!<br>El estadio se reinicia.",
"BOL.chat.rolldamage": "Tirada de daño",
"BOL.chat.rolldamage6": "Tirada de daño +6",
"BOL.chat.rolldamage12": "Tirada de daño +12 (1 PH)",
"BOL.chat.damageresult": "Daño {name}: {total}",
"BOL.chat.damagetarget": "Objetivo: {target}",
"BOL.chat.applydamagetotarget": "Aplicar daño al objetivo",
"BOL.chat.fightoption": "Opciones de combate",
"BOL.chat.reroll": "Relanzar (1 PH)",
"BOL.chat.heroicreminder": "Adicionalmente a las acciones abajo puedes: <ul><li>Carnicería: 1 ataque adicional al mismo oponente</li><li>Golpe Preciso: 1 Dado desventaja para oponente en localización</li><li>Desarme</li><li>Asesino de Chusma</li><li>Derribado: empujas oponente al suelo (máx +1 tamaño)</li></ul>Si gastas 1 Punto Heroe adicional, todos estos efectos pueden doblarse.",
"BOL.chat.toheroic": "Convertir en éxito Asombroso (1 PH)",
"BOL.chat.tolegend": "Convertir en éxito Legendario (1 PH)",
"BOL.chat.hurttitle": "¡{name} va a recibir {damageTotal} daño!",
"BOL.chat.armordefault": "Este ataque atraviesa armadura: la armadura no se utiliza para reducir daño.",
"BOL.chat.witharmor": "Impacto con armadura",
"BOL.chat.withoutarmor": "Impacto sin armadura",
"BOL.chat.shakeoff": "Sacudirse las Heridas (1 PH)",
"BOL.chat.splinteredshield": "Sacrificar Escudo/Arma {name} (1 PH)",
"BOL.chat.nodamage": "Sin daño",
"BOL.chat.damagesummary": "{name} recibe daño",
"BOL.chat.protectvalue": "Protección armadura",
"BOL.chat.noprotectvalue": "¡Sin armadura!",
"BOL.chat.heroreducedamage": "Un Punto de Héroe se ha gastado, para reducir el daño en {total}.",
"BOL.chat.herosplintered": "No recibes daño gracias a sacrificar el escudo/arma {weaponHero.name}. ¡El escudo/arma se ha destruido! y un PH se ha gastado.",
"BOL.chat.finaldamage": "Daño Final: ¡{finalDamage} de daño!",
"BOL.chat.spell": "Conjuro",
"BOL.chat.spellcost": "Coste Puntos Poder",
"BOL.chat.spellremaining": "Puntos Poder restantes",
"BOL.chat.nodamagesummary": "Sin daño ....",
"BOL.chat.damageresume": "{name} recibe heridas ...",
"BOL.chat.fumblemessage": "Si aceptas un fallo calamitoso (DJ escoje consecuencia), puedes ganar 1 Punto Héroe adicional.",
"BOL.chat.rangeinfo": "Disparo de {attackerName} a {defenderName}",
"BOL.chat.rangeweaponinfo": "Arma: {weaponName} - Alcance base {weaponRange}",
"BOL.chat.rangeout": "Mod: Fuera de alcance",
"BOL.chat.range0": "Mod: Quemarropa (+1)",
"BOL.chat.range1": "Mod: Alcance Corto (0)",
"BOL.chat.range2": "Mod: Alcance Medio (-1)",
"BOL.chat.range3": "Mod: Alcance Largo (-2)",
"BOL.chat.range4": "Mod: Alcance Distante (-4)",
"BOL.chat.range5": "Mod: Alcance Extremo (-6)",
"BOL.chat.range6": "Mod: Alcance Límite (-8)",
"BOL.chat.rangeprefix": "Distancia calculada: ",
"BOL.chat.rangevisible": "Linea de visión limpia entre tokens.",
"BOL.chat.rangenotvisible": "Linea de visión bloqueada entre tokens.",
"BOL.chat.rangetitle": "Información DJ",
"BOL.chat.weaponreroll1": "Recordatorio, este arma vuelve a tirar los 1s en daño.",
"BOL.chat.rollbougette": "Tirada moneda",
"BOL.chat.bougettesuccess": "¡Tus fondos monetarios no varían!",
"BOL.chat.bougettefailure": "Has gastado demasiado dinero, tu balance se decrementa un nivel...",
"BOL.chat.initiative": "Rango iniciativa (10 a 1)",
"BOL.chat.horoscope": "Horóscopo",
"BOL.chat.horoscopepoints": "Coste: {points} Puntos Astrología",
"BOL.chat.horoscopeminorsuccess": "Éxito horóscopo menor: cambia el nombre del horóscopo en la hoja. Te beneficias de 1 Dado Ventaja en la situación.",
"BOL.chat.horoscopeminorfailure": "Fallo horóscopo menor: cambia el nombre del horóscopo en la hoja. Sufres 1 Dado Desventaja en la situación.",
"BOL.chat.horoscopemajorsuccess": "Éxito horóscopo mayor: {horoscopeName} consigue 1 Punto Héroe en esta aventura. El punto ha sido añadido automáticamente.",
"BOL.chat.horoscopemajorfailure": "Fallo horóscopo mayor: {horoscopeName} pierde 1 Punto Héroe en esta aventura. El punto ha sido reducido automáticamente.",
"BOL.chat.horoscopemajorgroupsuccess": "Éxito en tu grupo de horóscopo mayor. Tu y tus compañeros ganáis {careerBonus} Dado Ventaja durante esta aventura.",
"BOL.chat.horoscopemajorgroupfailure": "Fallo en tu grupo de horóscopo mayor. Tu y tus compañeros sufrís {careerBonus} Dado Desventaja durante esta aventura.",
"BOL.chat.usedhoroscope": "Se ha utilizado Horóscopo",
"BOL.chat.horoscopedeleted": "Los horóscopos utilizados son borrados automáticamente.",
"BOL.chat.criticaloptions": "¡Éxito Asombroso! Selecciona 1 opción:",
"BOL.chat.criticalcarnage": "Carnicería: ganas 1 ataque adicional. Este segundo ataque no se puede beneficiar de Puntos Héroe/Villano.",
"BOL.chat.criticalplus6": "Golpe Devastador: añade +6 al daño causado (botón abajo).",
"BOL.chat.criticalprecise": "Golpe Preciso: impactas y dañas a tu oponente. Describe lo que haces (DJ de acuerdo), tu oponente sufre 1 Dado Desventaja en acciones relevantes.",
"BOL.chat.criticalunarm": "Desarme: si su oponente lleva algún arma, puede decidir desarmarlo en lugar de hacerle daño.",
"BOL.chat.criticalrabble": "Asesino de Chusma: si luchas contra Chusma, el daño resultante se convierte en el número de enemigos que derrotas.",
"BOL.chat.criticalpush": "Derribado: si el tamaño lo permite, empujas oponente al suelo. Sufre un 1 Dado Desventaja en todas sus acciones el siguiente asalto.",
"BOL.chat.criticalup": "Transforma en Legendario: si gastas 1 Punto Héroe/Villano transformas el éxito Asombroso en Legendario. Selecciona 2 opciones de la lista.",
"BOL.chat.criticalinfo": "¡Esto es un éxito Asombroso o Legendario! Escoge tus opciones y efectos",
"BOL.chat.criticalbuttonjournal": "Éxito Asombroso/Legendario",
"BOL.chat.armorRoll": "Tirada de Armadura",
"BOL.dialog.soeasy": "Demasiado fácil (+4)",
"BOL.dialog.veryeasy": "Muy fácil (+2)",
"BOL.dialog.easy": "Fácil (+1)",
"BOL.dialog.moderate": "Moderado (0)",
"BOL.dialog.hard": "Difícil (-1)",
"BOL.dialog.tough": "Duro (-2)",
"BOL.dialog.demanding": "Exigente (-4)",
"BOL.dialog.formidable": "Formidable (-6)",
"BOL.dialog.heroic": "Heroica (-8)",
"BOL.dialog.mythic": "Mítica (-10)",
"BOL.dialog.divine": "Divina (-12)",
"BOL.dialog.pointblank": "Quemarropa (+1)",
"BOL.dialog.close": "Corta (0)",
"BOL.dialog.medium": "Media (-1))",
"BOL.dialog.long": "Larga (-2)",
"BOL.dialog.distant": "Distante (-4)",
"BOL.dialog.extreme": "Extrema (-6)",
"BOL.dialog.utmost": "Límite (-8)",
"BOL.ui.name": "Nombre",
"BOL.ui.xp": "Experiencia",
"BOL.ui.xpspent": "Consumida",
"BOL.ui.xptotal": "Total",
"BOL.ui.biosize": "Tamaño",
"BOL.ui.bioweight": "Peso",
"BOL.ui.bioage": "Edad",
"BOL.ui.biohair": "Pelo",
"BOL.ui.bioeyes": "Ojos",
"BOL.ui.biosigns": "Marcas",
"BOL.ui.biodescription": "Descripción",
"BOL.ui.bionotes": "Notas",
"BOL.chat.welcome1": "Bienvenidos a Bárbaros de Lemuria (Ludospherik)",
"BOL.chat.welcome2": "Para jugar es necesario usar el manual, que lo podéis conseguir aquí: https://www.ludospherik-editions.com/en_gb/",
"BOL.chat.welcome3": "Los mapas incluidos tienen autorización de Guillaume Tavernier y Ludospherik. ¡Nuestro agradecimiento!",
"BOL.chat.welcome4": "Todo el soporte para el sistema es a través del servidor Discord: https://discord.gg/pPSDNJk",
"BOL.chat.welcome5": "¡Buena partida en Lemuria!",
"BOL.chat.welcome6": "",
"BOL.settings.rollArmor": "Tiradas de armadura",
"BOL.settings.rollArmorTooltip": "Tiradas de armadura, si no esta activo usará el valor fijo",
"BOL.settings.useBougette": "Utilizar Bougette (regla casera francesa)",
"BOL.settings.useBougetteTooltip": "Utilizar valor Bougette (Monedero), descrito en Annales Lemurienne de LeRatierBretonnien (https://www.lahiette.com/leratierbretonnien/)",
"BOL.settings.removeDead": "Automáticamente eliminar PNJs muertos al final del asalto",
"BOL.settings.removeDeadTooltip": "Automáticamente eliminar PNJs, cuando la Vitalidad es menor de 0 al final de cada asalto",
"BOL.settings.diceFormula": "Fórmula de Dados",
"BOL.settings.diceFormulaTooltip": "Fórmula general de dados (2d6 por defecto)",
"BOL.settings.diceSuccessValue" : "Valor éxito",
"BOL.settings.diceSuccessValueTooltip": "Valor del umbral para el éxito (9 por defecto en 2d6)",
"BOL.settings.diceCriticalValue" : "Valor éxito crítico",
"BOL.settings.diceCriticalValueTooltip": "Valor del umbral mínimo para el éxito crítico (12 por defecto en 2d6)",
"BOL.settings.diceCriticalFailure" : "Valor fallo crítico",
"BOL.settings.diceCriticalFailureTooltip": "Valor del umbral máximo para el fallo crítico (2 por defecto en 2d6)",
"BOL.settings.defaultLogoActorSheetPath" : "Logo para la Hoja",
"BOL.settings.defaultLogoPathActorSheetTooltip": "Hubicación del logo para la hoja del Actor (346x200, por defecto: /systems/bol/ui/logo.webp)",
"BOL.settings.defaultLogoTopLeftPath" : "Logo esquina superior izquierda",
"BOL.settings.defaultLogoTopLeftPathTooltip": "Hubicación logo ventana principal superior izquierda (718x416, por defecto: /systems/bol/ui/logo2.webp)"
}

View File

@ -1,15 +1,28 @@
{ {
"ACTOR.TypeCharacter": "Personnage", "TYPES": {
"ACTOR.TypeEncounter": "Rencontre", "Actor": {
"ITEM.TypeItem": "Objet", "character": "Personnage",
"ITEM.TypeFeature": "Trait", "encounter": "PNJ",
"ITEM.TypeWeapon": "Arme", "npc": "PNJ",
"ITEM.TypeArmor": "Armure", "vehicle": "Véhicule",
"horde": "Horde"
},
"Item": {
"item": "Objet",
"feature": "Trait",
"weapon": "Arme",
"armure": "Armure"
}
},
"BOL.attributes.vigor": "Vigueur", "BOL.attributes.vigor": "Vigueur",
"BOL.attributes.halfvigor": "Demi-vigueur", "BOL.attributes.halfvigor": "Demi-vigueur",
"BOL.attributes.agility": "Agilité", "BOL.attributes.agility": "Agilité",
"BOL.attributes.mind": "Esprit", "BOL.attributes.mind": "Esprit",
"BOL.attributes.appeal": "Aura", "BOL.attributes.appeal": "Aura",
"BOL.attributes.hull": "Coque",
"BOL.attributes.crew": "Equipage",
"BOL.attributes.resources": "Resources",
"BOL.attributes.row": "Rames",
"BOL.aptitudes.init": "Initiative", "BOL.aptitudes.init": "Initiative",
"BOL.aptitudes.melee": "Mêlée", "BOL.aptitudes.melee": "Mêlée",
"BOL.aptitudes.ranged": "Tir", "BOL.aptitudes.ranged": "Tir",
@ -22,7 +35,9 @@
"BOL.resources.power": "Pouvoir", "BOL.resources.power": "Pouvoir",
"BOL.resources.villainy": "Vilénie", "BOL.resources.villainy": "Vilénie",
"BOL.resources.alchemypoints": "Points de Creation", "BOL.resources.alchemypoints": "Points de Creation",
"BOL.resources.astrologypoints": "Points d'Astrologie",
"BOL.traits.xp": "Expérience", "BOL.traits.xp": "Expérience",
"BOL.ui.tab.stats": "Attributs", "BOL.ui.tab.stats": "Attributs",
"BOL.ui.tab.combat": "Combat", "BOL.ui.tab.combat": "Combat",
"BOL.ui.tab.actions": "Actions", "BOL.ui.tab.actions": "Actions",
@ -30,7 +45,19 @@
"BOL.ui.tab.equipment": "Equipement", "BOL.ui.tab.equipment": "Equipement",
"BOL.ui.tab.description": "Description", "BOL.ui.tab.description": "Description",
"BOL.ui.tab.details": "Details", "BOL.ui.tab.details": "Details",
"BOL.ui.tab.spellalchemy": "Sorts&Alchimie", "BOL.ui.tab.spellalchemy": "Mystères",
"BOL.ui.astrologerPoints": "Points d'Astrologie",
"BOL.ui.astrologerPointsLabel": "Points d'Astrologie actuels",
"BOL.ui.ishoroscopemajor": "Horoscope Majeur (ie de groupe) ?",
"BOL.ui.answer": "Réponse",
"BOL.ui.horoscopefavorable": "Favorable (1dB)",
"BOL.ui.horoscopeunfavorable": "Défavorable (1dM)",
"BOL.ui.horoscopes": "Horoscopes",
"BOL.ui.horoscopesBonus": "Horoscopes (Bonus)",
"BOL.ui.horoscopesMalus": "Horoscopes (Malus)",
"BOL.ui.groupHoroscope": "Horoscrope de Groupe de ",
"BOL.ui.properties": "Propriétés", "BOL.ui.properties": "Propriétés",
"BOL.ui.description": "Description", "BOL.ui.description": "Description",
"BOL.ui.actions": "Actions", "BOL.ui.actions": "Actions",
@ -86,8 +113,8 @@
"BOL.ui.success": "Succès", "BOL.ui.success": "Succès",
"BOL.ui.failure": "Échec", "BOL.ui.failure": "Échec",
"BOL.ui.fumble": "Échec critique", "BOL.ui.fumble": "Échec critique",
"BOL.ui.critical": "Succès critique", "BOL.ui.critical": "Succès Héroïque",
"BOL.ui.criticallegend": "Succès légendaire !", "BOL.ui.criticallegend": "Succès Légendaire !",
"BOL.ui.maneuvers": "Actions de combat", "BOL.ui.maneuvers": "Actions de combat",
"BOL.ui.stacksize": "Taille de pile (max)", "BOL.ui.stacksize": "Taille de pile (max)",
"BOL.ui.weapons": "Armes", "BOL.ui.weapons": "Armes",
@ -108,12 +135,23 @@
"BOL.ui.difficulty": "Difficulté", "BOL.ui.difficulty": "Difficulté",
"BOL.ui.spellProperties": "Propriétés du Sort", "BOL.ui.spellProperties": "Propriétés du Sort",
"BOL.ui.duration": "Durée", "BOL.ui.duration": "Durée",
"BOL.ui.spellkeep": "Prolongation", "BOL.ui.spellkeep": "Prolongation possible ?",
"BOL.ui.concentrate": "Concentration", "BOL.ui.concentrate": "Concentration à maintenir ?",
"BOL.ui.aggressive": "Sort aggressif ?",
"BOL.ui.registerInit": "Enregistrer comme Init. de combat", "BOL.ui.registerInit": "Enregistrer comme Init. de combat",
"BOL.ui.initMalus": "Malus d'initiative",
"BOL.ui.magicnewrules": "Règles supplémentaires (cf. supplément fan-made Sorcellerie!)",
"BOL.ui.other":"Autre",
"BOL.ui.career":"Carrière",
"BOL.ui.boon":"Avantage",
"BOL.ui.flaw":"Désanvatage",
"BOL.ui.cost":"Cout XP",
"BOL.ui.date":"Date",
"BOL.ui.isSorcerer": "Carrière de Sorcier ?", "BOL.ui.isSorcerer": "Carrière de Sorcier ?",
"BOL.ui.isAlchemist": "Carrière d'Alchimiste ?", "BOL.ui.isAlchemist": "Carrière d'Alchimiste ?",
"BOL.ui.isPriest": "Carrière de Prêtre/Druide ?", "BOL.ui.isPriest": "Carrière de Prêtre/Druide ?",
"BOL.ui.isAstrologer": "Carrière d'Astrologue?",
"BOL.ui.circle": "Cercle", "BOL.ui.circle": "Cercle",
"BOL.ui.spells": "Sorts", "BOL.ui.spells": "Sorts",
"BOL.ui.focusSpell": "Lance un sort", "BOL.ui.focusSpell": "Lance un sort",
@ -131,6 +169,21 @@
"BOL.ui.alchemyCostTotal": "Points de Création nécessaires pour la Préparation", "BOL.ui.alchemyCostTotal": "Points de Création nécessaires pour la Préparation",
"BOL.ui.alchemyInvest": "Points de Création investis", "BOL.ui.alchemyInvest": "Points de Création investis",
"BOL.ui.alchemyCurrent": "Points de Création actuel dans la Préparation", "BOL.ui.alchemyCurrent": "Points de Création actuel dans la Préparation",
"BOL.ui.astrology": "Astrologie et Horoscopes",
"BOL.ui.astrologyMinor": "Etablir un Horoscope Mineur",
"BOL.ui.astrologyMajor": "Etablir un Horoscope Majeur",
"BOL.ui.astrologyMajorGroup": "Etablir un Horoscope Majeur de Groupe",
"BOL.ui.makeHoroscope": "Etablir un Horoscope",
"BOL.ui.astrologerRank": "Rang de l'Astrologue",
"BOL.ui.horoscopeCost": "Cout en Points d'Astrologie",
"BOL.ui.minor": "Mineur",
"BOL.ui.major": "Majeur",
"BOL.ui.majorgroup": "Majeur de Groupe",
"BOL.ui.horoscopeGroup": "Horoscopes de Groupe",
"BOL.ui.horoscopeDiceRemaining": "Dés restants",
"BOL.ui.horoscopeDiceMax": "Dés Max",
"BOL.ui.astrologyNoPoints": "Vous n'avez pas assez de Points d'Astrologie!",
"BOL.ui.advance": "Avancement", "BOL.ui.advance": "Avancement",
"BOL.ui.isbonusdice": "Fourni un dé bonus?", "BOL.ui.isbonusdice": "Fourni un dé bonus?",
"BOL.ui.ismalusdice": "Fourni un dé malus?", "BOL.ui.ismalusdice": "Fourni un dé malus?",
@ -151,6 +204,49 @@
"BOL.ui.armorAgiMalus": "Malus d'Armure+Bouclier (Agi)", "BOL.ui.armorAgiMalus": "Malus d'Armure+Bouclier (Agi)",
"BOL.ui.armorInitMalus": "Malus d'Armure (Init)", "BOL.ui.armorInitMalus": "Malus d'Armure (Init)",
"BOL.ui.attackValue": "Valeur d'attaque", "BOL.ui.attackValue": "Valeur d'attaque",
"BOL.ui.attackModifier": "Attaque",
"BOL.ui.vehicleWeapons": "Armes de véhicules",
"BOL.ui.hullDamage": "D.coque",
"BOL.ui.crewDamage": "D.équipage",
"BOL.ui.fireDamage": "Feu ?",
"BOL.ui.weaponbonus": "Cette arme bénéficie déja d'un Dé de Bonus (Arme Favorite prise en compte, par exemple)",
"BOL.ui.creature": "Créature",
"BOL.ui.undead": "Mort vivant",
"BOL.ui.daemon": "Démon",
"BOL.ui.rabble": "Piétaille",
"BOL.ui.tough": "Coriace",
"BOL.ui.villain": "Rival",
"BOL.ui.attributaptitude": "Attribut ou Aptitude",
"BOL.ui.always": "Tout les jets (ie toujours)",
"BOL.ui.effectbonusmalus": "Bonus ou Malus à appliquer",
"BOL.ui.boleffects": "Effets (automatiques)",
"BOL.ui.modifier": "Modificateur",
"BOL.ui.effects": "Effets en cours",
"BOL.ui.pcname": "PJs",
"BOL.ui.npcname": "PNJs",
"BOL.ui.pclistbutton": "Vue compacte",
"BOL.ui.noactorfound": "PNJ inconnu, le PNJ doit être présent dans le monde pour s'afficher ici.",
"BOL.ui.deletetitle": "Suppression",
"BOL.ui.confirmdelete": "Vous êtes sûr de vouloir supprimer cet item ?",
"BOL.ui.nomorealchemypoints": "Plus assez de Points de Création !",
"BOL.ui.armornoformula": "L'armure {protect.name} n'a pas de formule pour la protection !",
"BOL.ui.selectactor": "Selectionnez votre personnage pour utiliser la macro",
"BOL.ui.itemnotfound": "Impossible de trouver l'objet de cette macro",
"BOL.ui.noinit": "Pas d'initiative trouvée, veuillez en enregistrer une.",
"BOL.ui.warninitiative": "Votre initiative n'est pas disponible. Effectuez un jet d'Initiative pour ce combat.",
"BOL.ui.isspecial": "Spéciale ?",
"BOL.ui.createEquipment": "Créer un Equipement",
"BOL.ui.newEquipment": "Nouvel équipement",
"BOL.ui.newNaturalWeapon": "Arme naturelle",
"BOL.ui.newNaturalProtection": "Protection naturelle",
"BOL.ui.createNaturalWeapon": "Créer une arme naturelle",
"BOL.ui.createNaturalProtection": "Créer une protection naturelle",
"BOL.ui.hordeSize": "Taille de la horde",
"BOL.ui.hordeAttack": "Attaque de Horde",
"BOL.ui.hordeName": "Nom de la Horde",
"BOL.ui.hordeHP": "Vitalité (1 membre)",
"BOL.ui.hordehp": "Vitalité (total)",
"BOL.featureCategory.origins": "Origines", "BOL.featureCategory.origins": "Origines",
"BOL.featureCategory.races": "Races", "BOL.featureCategory.races": "Races",
"BOL.featureCategory.careers": "Carrières", "BOL.featureCategory.careers": "Carrières",
@ -163,6 +259,7 @@
"BOL.bougette.easylife": "A l'aise", "BOL.bougette.easylife": "A l'aise",
"BOL.bougette.luxury": "Luxe&Volupté", "BOL.bougette.luxury": "Luxe&Volupté",
"BOL.bougette.rich": "Richissime", "BOL.bougette.rich": "Richissime",
"BOL.featureSubtypes.origin": "Origine", "BOL.featureSubtypes.origin": "Origine",
"BOL.featureSubtypes.race": "Race", "BOL.featureSubtypes.race": "Race",
"BOL.featureSubtypes.career": "Carrière", "BOL.featureSubtypes.career": "Carrière",
@ -171,6 +268,12 @@
"BOL.featureSubtypes.language": "Langue", "BOL.featureSubtypes.language": "Langue",
"BOL.featureSubtypes.gods": "Dieux & Foi", "BOL.featureSubtypes.gods": "Dieux & Foi",
"BOL.featureSubtypes.fightOption": "Option de Combat", "BOL.featureSubtypes.fightOption": "Option de Combat",
"BOL.featureSubtypes.effect": "Effet",
"BOL.featureSubtypes.effects": "Effets",
"BOL.featureSubtypes.boleffect": "Effet",
"BOL.featureSubtypes.horoscope": "Horoscope",
"BOL.featureSubtypes.xplog": "Log d'XP",
"BOL.fightOptionTypes.armor": "Attaque au défaut d'armure", "BOL.fightOptionTypes.armor": "Attaque au défaut d'armure",
"BOL.fightOptionTypes.intrepid": "Attaque intrépide", "BOL.fightOptionTypes.intrepid": "Attaque intrépide",
"BOL.fightOptionTypes.twoweaponsdef": "Combat à 2 armes (Défense)", "BOL.fightOptionTypes.twoweaponsdef": "Combat à 2 armes (Défense)",
@ -178,6 +281,8 @@
"BOL.fightOptionTypes.fulldefense": "Défense totale", "BOL.fightOptionTypes.fulldefense": "Défense totale",
"BOL.fightOptionTypes.defense": "Posture défensive", "BOL.fightOptionTypes.defense": "Posture défensive",
"BOL.fightOptionTypes.attack": "Posture offensive", "BOL.fightOptionTypes.attack": "Posture offensive",
"BOL.fightOptionTypes.other": "Autres",
"BOL.itemCategory.object": "Objet", "BOL.itemCategory.object": "Objet",
"BOL.itemCategory.equipment": "Équipement", "BOL.itemCategory.equipment": "Équipement",
"BOL.itemCategory.consumable": "Consommable", "BOL.itemCategory.consumable": "Consommable",
@ -186,12 +291,15 @@
"BOL.itemCategory.other": "Autre", "BOL.itemCategory.other": "Autre",
"BOL.itemCategory.capacity": "Capacité", "BOL.itemCategory.capacity": "Capacité",
"BOL.itemCategory.alchemy": "Préparation Alchimique", "BOL.itemCategory.alchemy": "Préparation Alchimique",
"BOL.itemCategory.vehicleweapon": "Armes de Véhicule",
"BOL.combatCategory.protections": "Protections", "BOL.combatCategory.protections": "Protections",
"BOL.combatCategory.shields": "Boucliers", "BOL.combatCategory.shields": "Boucliers",
"BOL.combatCategory.melee": "Armes de contact", "BOL.combatCategory.melee": "Armes de contact",
"BOL.combatCategory.ranged": "Armes à distance", "BOL.combatCategory.ranged": "Armes à distance",
"BOL.combatCategory.fightOptions": "Options de combat", "BOL.combatCategory.fightOptions": "Options de combat",
"BOL.combatCategory.natural": "Armes Naturelless", "BOL.combatCategory.natural": "Armes Naturelless",
"BOL.equipmentCategory.weapon": "Arme", "BOL.equipmentCategory.weapon": "Arme",
"BOL.equipmentCategory.armor": "Armure", "BOL.equipmentCategory.armor": "Armure",
"BOL.equipmentCategory.protection": "Protection", "BOL.equipmentCategory.protection": "Protection",
@ -203,21 +311,26 @@
"BOL.equipmentCategory.container": "Conteneur", "BOL.equipmentCategory.container": "Conteneur",
"BOL.equipmentCategory.currency": "Monnaie", "BOL.equipmentCategory.currency": "Monnaie",
"BOL.equipmentCategory.other": "Autre", "BOL.equipmentCategory.other": "Autre",
"BOL.protectionCategory.armor": "Armure", "BOL.protectionCategory.armor": "Armure",
"BOL.protectionCategory.shield": "Bouclier", "BOL.protectionCategory.shield": "Bouclier",
"BOL.protectionCategory.helm": "Casque", "BOL.protectionCategory.helm": "Casque",
"BOL.protectionCategory.other": "Autre", "BOL.protectionCategory.other": "Autre",
"BOL.spellItem.charm": "Charme", "BOL.spellItem.charm": "Charme",
"BOL.spellItem.circle1": "Premier Cercle", "BOL.spellItem.circle1": "Premier Cercle",
"BOL.spellItem.circle2": "Second Cercle", "BOL.spellItem.circle2": "Second Cercle",
"BOL.spellItem.circle3": "Troisième Cercle", "BOL.spellItem.circle3": "Troisième Cercle",
"BOL.alchemyItem.common": "Courante", "BOL.alchemyItem.common": "Courante",
"BOL.alchemyItem.scarce": "Rare", "BOL.alchemyItem.scarce": "Rare",
"BOL.alchemyItem.legend": "Légendaire", "BOL.alchemyItem.legend": "Légendaire",
"BOL.alchemyItem.mythic": "Mythique", "BOL.alchemyItem.mythic": "Mythique",
"BOL.weaponCategory.melee": "Arme de mêlée", "BOL.weaponCategory.melee": "Arme de mêlée",
"BOL.weaponCategory.ranged": "Arme de tir", "BOL.weaponCategory.ranged": "Arme de tir",
"BOL.weaponCategory.other": "Autre", "BOL.weaponCategory.other": "Autre",
"BOL.itemProperty.damageMultiplier": "Multiplicateur de dommages", "BOL.itemProperty.damageMultiplier": "Multiplicateur de dommages",
"BOL.itemProperty.attackBonusDice": "Dé de Bonus d'attaque", "BOL.itemProperty.attackBonusDice": "Dé de Bonus d'attaque",
"BOL.itemProperty.equipable": "Équipable", "BOL.itemProperty.equipable": "Équipable",
@ -270,6 +383,18 @@
"BOL.itemProperty.difficulty": "Difficulté", "BOL.itemProperty.difficulty": "Difficulté",
"BOL.itemProperty.natural": "Arme naturelle", "BOL.itemProperty.natural": "Arme naturelle",
"BOL.itemProperty.onlymodifier": "Modificateur uniquement (ie attaques de créatures)", "BOL.itemProperty.onlymodifier": "Modificateur uniquement (ie attaques de créatures)",
"BOL.itemProperty.vehicleDamageType": "Type de dommages de véhicules",
"BOL.itemProperty.isfiredamage": "Dommages de Feu",
"BOL.itemProperty.ishulldamage": "Dommages à la coque",
"BOL.itemProperty.iscrewdamage": "Dommages à l'équipage",
"BOL.itemProperty.hulldamage": "Valeur des dommages à la coque",
"BOL.itemProperty.crewdamage": "Valeur des dommages à l'équipage",
"BOL.itemProperty.hullDamageMultiplier": "Multiplicateur",
"BOL.itemProperty.crewDamageMultiplier": "Multiplicateur",
"BOL.itemProperty.isboarding": "Abordage",
"BOL.itemProperty.isspur": "Eperonnage",
"BOL.itemProperty.isbreakrow": "Briser les rames",
"BOL.itemStat.quantity": "Quantité", "BOL.itemStat.quantity": "Quantité",
"BOL.itemStat.weight": "Poids", "BOL.itemStat.weight": "Poids",
"BOL.itemStat.price": "Prix", "BOL.itemStat.price": "Prix",
@ -279,21 +404,26 @@
"BOL.itemStat.soak": "Valeur de protection", "BOL.itemStat.soak": "Valeur de protection",
"BOL.itemStat.blocking": "Bloquage", "BOL.itemStat.blocking": "Bloquage",
"BOL.itemStat.modifiers": "Modificateurs", "BOL.itemStat.modifiers": "Modificateurs",
"BOL.weaponSize.unarmed": "Mains nues", "BOL.weaponSize.unarmed": "Mains nues",
"BOL.weaponSize.improvised": "Arme improvisée", "BOL.weaponSize.improvised": "Arme improvisée",
"BOL.weaponSize.light": "Légère", "BOL.weaponSize.light": "Légère",
"BOL.weaponSize.medium": "Moyenne", "BOL.weaponSize.medium": "Moyenne",
"BOL.weaponSize.heavy": "Lourde", "BOL.weaponSize.heavy": "Lourde",
"BOL.itemModifiers.init": "Malus (Initiative)", "BOL.itemModifiers.init": "Malus (Initiative)",
"BOL.itemModifiers.social": "Malus (Social)", "BOL.itemModifiers.social": "Malus (Social)",
"BOL.itemModifiers.agility": "Malus (Agilité)", "BOL.itemModifiers.agility": "Malus (Agilité)",
"BOL.itemModifiers.powercost": "Malus (Coût supplémentaire en PP)", "BOL.itemModifiers.powercost": "Malus (Coût supplémentaire en PP)",
"BOL.itemBlocking.malus": "Social", "BOL.itemBlocking.malus": "Social",
"BOL.itemBlocking.nbAttacksPerRound": "Agilité", "BOL.itemBlocking.nbAttacksPerRound": "Agilité",
"BOL.soakFormula.none": "-", "BOL.soakFormula.none": "-",
"BOL.soakFormula.light": "Légère (Annule d6-3 dégâts subis)", "BOL.soakFormula.light": "Légère (Annule d6-3 dégâts subis)",
"BOL.soakFormula.medium": "Moyenne (Annule d6-2 dégâts subis)", "BOL.soakFormula.medium": "Moyenne (Annule d6-2 dégâts subis)",
"BOL.soakFormula.heavy": "Lourde (Annule d6-1 dégâts subis)", "BOL.soakFormula.heavy": "Lourde (Annule d6-1 dégâts subis)",
"BOL.armorQuality.none": "-", "BOL.armorQuality.none": "-",
"BOL.armorQuality.light": "Légère", "BOL.armorQuality.light": "Légère",
"BOL.armorQuality.lightQ": "Légère de qualité", "BOL.armorQuality.lightQ": "Légère de qualité",
@ -307,6 +437,7 @@
"BOL.armorQuality.heavyQ": "Lourde de qualité", "BOL.armorQuality.heavyQ": "Lourde de qualité",
"BOL.armorQuality.heavySup": "Lourde Supérieure", "BOL.armorQuality.heavySup": "Lourde Supérieure",
"BOL.armorQuality.heavyLeg": "Lourde Légendaire", "BOL.armorQuality.heavyLeg": "Lourde Légendaire",
"BOL.equipmentSlots.none": "-", "BOL.equipmentSlots.none": "-",
"BOL.equipmentSlots.head": "Tête", "BOL.equipmentSlots.head": "Tête",
"BOL.equipmentSlots.neck": "Cou", "BOL.equipmentSlots.neck": "Cou",
@ -323,10 +454,12 @@
"BOL.equipmentSlots.feet": "Pieds", "BOL.equipmentSlots.feet": "Pieds",
"BOL.equipmentSlots.finder": "Doigt", "BOL.equipmentSlots.finder": "Doigt",
"BOL.equipmentSlots.ear": "Oreille", "BOL.equipmentSlots.ear": "Oreille",
"BOL.vehicleCategory.mount": "Monture terrestre", "BOL.vehicleCategory.mount": "Monture terrestre",
"BOL.vehicleCategory.flying": "Monture volante", "BOL.vehicleCategory.flying": "Monture volante",
"BOL.vehicleCategory.boat": "Bateau", "BOL.vehicleCategory.boat": "Bateau",
"BOL.vehicleCategory.other": "Autre", "BOL.vehicleCategory.other": "Autre",
"BOL.range.PointBlank": "Bout portant", "BOL.range.PointBlank": "Bout portant",
"BOL.range.Short": "Courte", "BOL.range.Short": "Courte",
"BOL.range.Medium": "Moyenne", "BOL.range.Medium": "Moyenne",
@ -334,6 +467,7 @@
"BOL.range.VeryLong": "Très longue", "BOL.range.VeryLong": "Très longue",
"BOL.range.Extreme": "Extrême", "BOL.range.Extreme": "Extrême",
"BOL.range.Maximum": "Maximale", "BOL.range.Maximum": "Maximale",
"BOL.notification.MacroMultipleTokensSelected": "Vous avez sélectionné plusieurs tokens", "BOL.notification.MacroMultipleTokensSelected": "Vous avez sélectionné plusieurs tokens",
"BOL.notification.MacroNoActorAvailable": "Aucun acteur n'a pu être ciblé", "BOL.notification.MacroNoActorAvailable": "Aucun acteur n'a pu être ciblé",
"BOL.notification.MacroNoTokenSelected": "Vous devez sélectionner un token", "BOL.notification.MacroNoTokenSelected": "Vous devez sélectionner un token",
@ -356,10 +490,10 @@
"BOL.chat.isdead": "{name} est mort !", "BOL.chat.isdead": "{name} est mort !",
"BOL.chat.epitaph": "Que son nom soit honoré sur les champs de batailles de Lémurie !", "BOL.chat.epitaph": "Que son nom soit honoré sur les champs de batailles de Lémurie !",
"BOL.chat.vitalityzero": "La Vitalité de {name} est {hp} : il va s'écrouler au sol et sombrer dans l'inconscience !", "BOL.chat.vitalityzero": "La Vitalité de {name} est {hp} : il va s'écrouler au sol et sombrer dans l'inconscience !",
"BOL.chat.vitalityheroism": "Vous pouvez dépenser 1 Point d'Héroisme pour reprendre vos esprits pendant 1 round.", "BOL.chat.vitalityheroism": "Vous pouvez dépenser 1 Point d'Héroisme/Vilainie pour reprendre vos esprits pendant 1 round.",
"BOL.chat.vitalityheroismhint": "Dans ce cas votre vitalité remonte à son maximum divisé par 2 (arrondi au supérieur).", "BOL.chat.vitalityheroismhint": "Dans ce cas votre vitalité remonte à son maximum divisé par 2 (arrondi au supérieur).",
"BOL.chat.vitalitydying": "La Vitalité de {name} est de {hp} ! Il est mourant ...", "BOL.chat.vitalitydying": "La Vitalité de {name} est de {hp} ! Il est mourant ...",
"BOL.chat.vitalitydyingheroism": "Vous pouvez cependant dépenser 1 Point d'Héroisme pour Défier la Mort (cf. page 58).", "BOL.chat.vitalitydyingheroism": "Vous pouvez cependant dépenser 1 Point d'Héroisme/Vilainie pour Défier la Mort (cf. page 58).",
"BOL.chat.alchemytitle": "Préparation Alchimique : {name}", "BOL.chat.alchemytitle": "Préparation Alchimique : {name}",
"BOL.chat.alchemypoints": "Points de Création Investis : {pcCostCurrent}", "BOL.chat.alchemypoints": "Points de Création Investis : {pcCostCurrent}",
"BOL.chat.alchemysuccess": "La préparation alchimique a été réalisée avec succès !<br>Créez l'item ou l'effet correspondant dans votre Inventaire.<br>L'avancement dans la préparation a été remis à 0.", "BOL.chat.alchemysuccess": "La préparation alchimique a été réalisée avec succès !<br>Créez l'item ou l'effet correspondant dans votre Inventaire.<br>L'avancement dans la préparation a été remis à 0.",
@ -367,30 +501,78 @@
"BOL.chat.rolldamage": "Lancer les dommages", "BOL.chat.rolldamage": "Lancer les dommages",
"BOL.chat.rolldamage6": "Lancer les dommages +6", "BOL.chat.rolldamage6": "Lancer les dommages +6",
"BOL.chat.rolldamage12": "Dommages +12 (1 Pt. d'Heroisme)", "BOL.chat.rolldamage12": "Dommages +12 (1 Pt. d'Heroisme)",
"BOL.chat.rolldamage12Legend": "Dommages +12",
"BOL.chat.damageresult": "Dommages de {name} : {total}", "BOL.chat.damageresult": "Dommages de {name} : {total}",
"BOL.chat.damagetarget": "Cible : {target}", "BOL.chat.damagetarget": "Cible : {target}",
"BOL.chat.applydamagetotarget": "Appliquer les dommages à la cible", "BOL.chat.applydamagetotarget": "Appliquer les dommages à la cible",
"BOL.chat.fightoption": "Option de combat", "BOL.chat.fightoption": "Option de combat",
"BOL.chat.reroll": "Relancer (1 P. Heroisme)", "BOL.chat.reroll": "Relancer (1 P. Heroisme)",
"BOL.chat.toheroic": "Transformer en succés Héroïque (1 P. Héroisme)", "BOL.chat.heroicreminder": "En plus des actions indiquées sur les boutons ci-dessous, vous pouvez : <ul><li>Carnage : Attaquer une seconde fois le même adversaire</li><li>Coup précis : Un dé de malus à votre adversaire sur une localisation choisie</li><li>Désarmement</li><li>Massacrer la piétaille</li><li>Renversement : Renversez votre adversaire (1 taille de plus max)</li></ul>Si vous dépensez un Point d'Héroisme en plus, tout ces effets peuvent être doublés",
"BOL.chat.tolegend": "Transformer en succes Légendaire (1 P. Heroisme)", "BOL.chat.legendaryreminder": "En plus des actions indiquées sur les boutons ci-dessous, vous pouvez effectuer 2 actions parmis: <ul><li>Carnage : Attaquer une seconde fois le même adversaire</li><li>Coup précis : Un dé de malus à votre adversaire sur une localisation choisie</li><li>Désarmement</li><li>Massacrer la piétaille</li><li>Renversement : Renversez votre adversaire (1 taille de plus max)</li></ul>",
"BOL.chat.toheroic": "Transformer en succés Héroïque (1 P. Héroisme/Vilainie)",
"BOL.chat.tolegend": "Transformer en succes Légendaire (1 P. Heroisme/Vilainie)",
"BOL.chat.hurttitle": "{name} va encaisser {damageTotal} dégats !", "BOL.chat.hurttitle": "{name} va encaisser {damageTotal} dégats !",
"BOL.chat.armordefault": "C'est une attaque au défaut de l'armure : vous devez encaisser SANS la protection de l'armure !", "BOL.chat.armordefault": "C'est une attaque au défaut de l'armure : vous devez encaisser SANS la protection de l'armure !",
"BOL.chat.witharmor": "Encaisser avec la protection de l'armure", "BOL.chat.witharmor": "Encaisser avec la protection de l'armure",
"BOL.chat.withoutarmor": "Encaisser sans la protection de l'armure", "BOL.chat.withoutarmor": "Encaisser sans la protection de l'armure",
"BOL.chat.shakeoff": "Juste une égratignure (1 Point d'Héroisme)", "BOL.chat.shakeoff": "Juste une égratignure (1 Point d'Héroisme/Vilainie)",
"BOL.chat.splinteredshield": "Parade in Extremis avec {name} (1 Point d'Héroisme)", "BOL.chat.splinteredshield": "Parade in Extremis avec {name} (1 Point d'Héroisme/Vilainie)",
"BOL.chat.damagesummary": "Dégats subis par {name}", "BOL.chat.damagesummary": "Dégats subis par {name}",
"BOL.chat.protectvalue": "Protection de l'armure", "BOL.chat.protectvalue": "Protection de l'armure",
"BOL.chat.noprotectvalue": "Aucune protection d'armure !", "BOL.chat.noprotectvalue": "Aucune protection d'armure !",
"BOL.chat.heroreducedamage": "Un point d'héroisme dépensé, pour une réduction des dommages supplémentaire de {total}.", "BOL.chat.heroreducedamage": "Un point d'héroisme/vilainie dépensé, pour une réduction des dommages supplémentaire de {total}.",
"BOL.chat.herosplintered": "Aucun dommage encaissé, grâce à la parade in-extremis avec {weaponHero.name}. L'arme a été détruite pendant cette parade ! Un point d'héroisme a également été dépensé.", "BOL.chat.herosplintered": "Aucun dommage encaissé, grâce à la parade in-extremis avec {weaponHero.name}. L'arme a été détruite pendant cette parade ! Un point d'héroisme/vilainie a également été dépensé.",
"BOL.chat.finaldamage": "Encaissement final : {finalDamage} dégats !", "BOL.chat.finaldamage": "Encaissement final : {finalDamage} dégats !",
"BOL.chat.spell": "Sort", "BOL.chat.spell": "Sort",
"BOL.chat.spellcost": "Cout en Points de Pouvoir", "BOL.chat.spellcost": "Cout en Points de Pouvoir",
"BOL.chat.spellremaining": "Points de Pouvoir restants", "BOL.chat.spellremaining": "Points de Pouvoir restants",
"BOL.chat.nodamagesummary": "Aucun dégats n'a été subi ....", "BOL.chat.nodamagesummary": "Aucun dégats n'a été subi ....",
"BOL.chat.damageresume": "{name} a subi des blessures ...", "BOL.chat.damageresume": "{name} a subi des blessures ...",
"BOL.chat.fumblemessage": "Si vous acceptez les conséquences d'un echec catastrophique (au choix du MJ), vous pourrez bénéficier d'1 point d'Héroïsme supplémentaire",
"BOL.chat.rangeinfo": "Tir/Lancer de {attackerName} vers {defenderName}",
"BOL.chat.rangeweaponinfo": "Arme : {weaponName} - Portée de base {weaponRange}",
"BOL.chat.rangeout": "Modificateur : Hors de portée",
"BOL.chat.range0": "Modificateur : Bout portant (+1)",
"BOL.chat.range1": "Modificateur : Portée courte (0)",
"BOL.chat.range2": "Modificateur : Portée moyenne (-1)",
"BOL.chat.range3": "Modificateur : Portée longue (-2)",
"BOL.chat.range4": "Modificateur : Portée très longue (-4)",
"BOL.chat.range5": "Modificateur : Portée extrême (-6)",
"BOL.chat.range6": "Modificateur : Portée maximale (-8)",
"BOL.chat.rangeprefix": "Distance évaluée : ",
"BOL.chat.rangevisible": "La ligne de vue est dégagée entre les protagonistes.",
"BOL.chat.rangenotvisible": "La ligne de vue est bloquée entre les protagonistes.",
"BOL.chat.rangetitle": "Information MJ",
"BOL.chat.weaponreroll1": "Pour information, cette arme relance les 1 sur ses dégâts.",
"BOL.chat.rollbougette": "Jet de Bougette",
"BOL.chat.bougettesuccess": "Votre bougette reste inchangée !",
"BOL.chat.bougettefailure": "Vous avez trop dépensé, votre bougette s'est réduite...",
"BOL.chat.initiative": "Rang d'intiative (10 à 1)",
"BOL.chat.horoscope": "Horoscope",
"BOL.chat.horoscopepoints": "Coût : {points} Points d'Astrologie",
"BOL.chat.horoscopeminorsuccess": "Votre horoscope mineur est un succès : éditez le nom de l'horoscope sur votre fiche. Vous bénéficiez d'1 dé Bonus pour cette situation.",
"BOL.chat.horoscopeminorfailure": "Votre horoscope mineur est un échec : éditez le nom de l'horoscope sur votre fiche. Vous souffrez d'1 dé Malus pour cette situation.",
"BOL.chat.horoscopemajorsuccess": "Votre horoscope majeur est un succès : {horoscopeName} bénéficie d'1 point d'Héroisme de plus pour cette aventure. Ce point a été ajouté automatiquement.",
"BOL.chat.horoscopemajorfailure": "Votre horoscope majeur est un échec : {horoscopeName} a perdu 1 point d'Héroisme pour cette aventure. Ce point a été enlevé automatiquement.",
"BOL.chat.horoscopemajorgroupsuccess": "Votre horoscope majeur de groupe est un succès. Vous et vos amis bénéficiez de {careerBonus} dés bonus pendant cette aventure.",
"BOL.chat.horoscopemajorgroupfailure": "Votre horoscope majeur de groupe est un échec. Vous et vos amis souffrez de {careerBonus} dés malus pendant cette aventure.",
"BOL.chat.usedhoroscope": "Horoscope utilisé",
"BOL.chat.horoscopedeleted": "Le(s) Horoscopes utilisé(s) a/ont été supprimé(s) automatiquement.",
"BOL.chat.criticaloptions": "Succès critique !! Vous pouvez faire (1 option au choix) :",
"BOL.chat.criticalcarnage": "Faire un Carnage : vous avez une attaque gratuite supplémentaire. Cette seconde attaque ne peut bénéficier d'un Point d'Héroisme/vilainie.",
"BOL.chat.criticalplus6": "Coup Dévastateur : +6 aux dommages (cf bouton ci-dessous).",
"BOL.chat.criticalprecise": "Coup Précis : Vous frappez pour diminuer les capacités de votre adversaire. Décrivez ce que vous faites, et si le MJ l'accepte, votre opposant subira un Dé de Malus pour les actions concernées.",
"BOL.chat.criticalunarm": "Désarmement : Si votre adversaire a une arme en main, vous le désarmez.",
"BOL.chat.criticalrabble": "Massacrer la piétaille : Si vous combattez de la Piétaille, les résultats des dommages indiquent le nombre d'adversaires mis hors de combat.",
"BOL.chat.criticalpush": "Renversement : Si la taille le permet, vous poussez votre adversaire au sol, il souffrira d'1 Dé de Malus pour toutes ses actions au round suivant.",
"BOL.chat.criticalup": "Transformer en Légendaire : En dépensant 1 point d'Héroisme/Vilainie, vous pouvez transformer ce Succès Héroïque en Légendaire, qui vous permet de prendre 2 options dans la liste ci-dessus (cf. bouton pour un +12 aux dommages par exemple).",
"BOL.chat.criticalinfo": "C'est un succès Héroïque ! Choisissez vos options et effets !",
"BOL.chat.criticallegendaryinfo": "C'est un succès Légendaire ! Choisissez vos options et effets !",
"BOL.chat.criticalbuttonjournal": "Succès Héroïque/Légendaire",
"BOL.chat.losshp": "{name} a perdu {lossHP} points de Vitalité. Si il se repose quelques minutes, il peut récupérer {recupHP} points de Vitalité.",
"BOL.chat.applyrecup": "Récupérer pendant quelques minutes (+{recupHP} Vitalité)",
"BOL.chat.inforecup": "{name} vient de récupérer {recupHP} points de Vitalité après quelques minutes de repos.",
"BOL.dialog.soeasy": "Inmanquable (+4)", "BOL.dialog.soeasy": "Inmanquable (+4)",
"BOL.dialog.veryeasy": "Trés Facile (+2)", "BOL.dialog.veryeasy": "Trés Facile (+2)",
@ -424,11 +606,41 @@
"BOL.ui.biosigns": "Signes distinctifs", "BOL.ui.biosigns": "Signes distinctifs",
"BOL.ui.biodescription": "Description", "BOL.ui.biodescription": "Description",
"BOL.ui.bionotes": "Notes", "BOL.ui.bionotes": "Notes",
"BOL.ui.xplog":"Journal d'XP",
"BOL.ui.value":"Valeur",
"BOL.chat.welcome1": "Bienvenue dans Barbarians of Lemuria (Ludospherik version)", "BOL.chat.welcome1": "Bienvenue dans Barbarians of Lemuria (Ludospherik version)",
"BOL.chat.welcome2": "Les livres nécessaires pour jouer sont disponibles sur le site de l'éditeur : http://www.ludospherik.fr/content/14-barbarians-of-lemuria", "BOL.chat.welcome2": "Les livres nécessaires pour jouer sont disponibles sur le site de <a href='http://www.ludospherik.fr/content/14-barbarians-of-lemuria'>l'éditeur Ludospherik.</a>",
"BOL.chat.welcome3": "Les cartes intégrées au système le sont grace à l'aimable autorisation de leur auteur Guillaume Tavernier et des éditions Ludospherik. Merci à eux !.", "BOL.chat.welcome3": "Les cartes intégrées au système le sont grace à l'aimable autorisation de leur auteur Guillaume Tavernier et des éditions Ludospherik. Merci à eux !.",
"BOL.chat.welcome4": "Tout le support et le suivi de ce système est disponible via le Discord Foundry FR : https://discord.gg/pPSDNJk", "BOL.chat.welcome4": "Tout le support et le suivi de ce système est disponible via le <a href='https://discord.gg/pPSDNJk'>Discord Foundry FR</a>.",
"BOL.chat.welcome5": "Bon jeu en Lemurie !" "BOL.chat.welcome5": "Consulter l'aide en ligne pour plus d'informations : @UUID[Compendium.bol.aides-de-jeu.97rugQOtiwt8zPfQ]{Aide du Jeu}.",
"BOL.chat.welcome6": "Bon jeu en Lemurie !",
"BOL.chat.nodamage": "Ne pas appliquer les dommages",
"BOL.chat.pcwarning": "Attention ! Aucun personnage n'est relié au joueur !",
"BOL.chat.pcwarningmsg": "<b>ATTENTION</b> Le joueur n'est relié à aucun personnage !",
"BOL.chat.pcnotlinked": "Le token du personnage joueur n'est pas relié à l'acteur",
"BOL.chat.pcnotlinkedmsg": "<b>ATTENTION</b> Le token du personnage joueur n'est pas relié à l'acteur !",
"BOL.chat.armorRoll": "Jet d'armure",
"BOL.settings.rollArmor": "Effectuer des jets pour les armures",
"BOL.settings.rollArmorTooltip": "Effectue un jet de dés pour les armures (valeur fixe si désactivé)",
"BOL.settings.useBougette": "Utiliser la Bougette (règle fan-made)",
"BOL.settings.useBougetteTooltip": "Utilise un indicateur de Bougette, comme décrit dans l'aide de jeu Annales Lemurienne du RatierBretonnien (https://www.lahiette.com/leratierbretonnien/)",
"BOL.settings.removeDead": "Enlever les PNJs morts automatiquement au round suivant",
"BOL.settings.removeDeadTooltip": "Supprime les PNJ (piétaille, créatures, coriaces) automatiquement du combat lorsqu'ils sont à 0 Vitalité ou moins, lors du passage au round suivant",
"BOL.settings.diceFormula": "Formule de dés",
"BOL.settings.diceFormulaTooltip": "Formule de dés utilisée pour les jets de dés (par défaut 2d6)",
"BOL.settings.diceSuccessValue" : "Seuil de succès",
"BOL.settings.diceSuccessValueTooltip": "Seuil de succès pour les jets de dés (par défaut 9 pour 2d6)",
"BOL.settings.diceCriticalValue" : "Seuil de succès critique",
"BOL.settings.diceCriticalValueTooltip": "Seuil de succès critique pour les jets de dés (par défaut 12 pour 2d6)",
"BOL.settings.diceCriticalFailure" : "Valeur max d'échec critique",
"BOL.settings.diceCriticalFailureTooltip": "Valeur max d'échec critique pour les jets de dés (par défaut 2 pour 2d6)",
"BOL.settings.defaultLogoActorSheetPath" : "Chemin du logo des fiches de perso",
"BOL.settings.defaultLogoPathActorSheetTooltip": "Vous pouvez changer le logo BoL des fiches de perso, pour jouer dans un autre univers (idéalement 346 x 200, défaut : /systems/bol/ui/logo.webp)",
"BOL.settings.defaultLogoTopLeftPath" : "Chemin du logo haut gauche",
"BOL.settings.defaultLogoTopLeftPathTooltip": "Vous pouvez changer le logo BoL en haut à gauche de chaque écran (idéalement 718 x 416, défaut : /systems/bol/ui/logo2.webp)",
"EFFECT.StatusProne": "A terre",
"EFFECT.StatusDead": "Mort"
} }

View File

@ -9,10 +9,10 @@ export class BoLActorSheet extends ActorSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["bol", "sheet", "actor"], classes: ["bol", "sheet", "actor"],
template: "systems/bol/templates/actor/actor-sheet.hbs", template: "systems/bol/templates/actor/actor-sheet.hbs",
width: 600, width: 860,
height: 600, height: 600,
dragDrop: [{ dragSelector: ".items-list .item", dropSelector: null }], dragDrop: [{ dragSelector: ".items-list .item", dropSelector: null }],
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "stats" }] tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "stats" }]
@ -27,7 +27,7 @@ export class BoLActorSheet extends ActorSheet {
function onLoad() { function onLoad() {
let logoSheet = BoLUtility.getLogoActorSheet() let logoSheet = BoLUtility.getLogoActorSheet()
$(".bol-actor-form").css("backgroundImage",`url(${logoSheet})`) $(".bol-actor-form").css("backgroundImage", `url(${logoSheet})`)
} }
// Setup everything onload // Setup everything onload
$(function () { onLoad(); }); $(function () { onLoad(); });
@ -47,10 +47,19 @@ export class BoLActorSheet extends ActorSheet {
// Equip/Unequip item // Equip/Unequip item
html.find('.item-equip').click(this._onToggleEquip.bind(this)); html.find('.item-equip').click(this._onToggleEquip.bind(this));
html.find('.create_item').click(ev => { html.find('.create-item').click(ev => {
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvel Equipement", type: "item" }], { renderSheet: true }); this.actor.createEmbeddedDocuments('Item', [{ name: game.i18n.localize("BOL.ui.newEquipment"), type: "item" }], { renderSheet: true });
}); });
html.find('.create-natural-weapon').click(ev => {
let system = foundry.utils.duplicate(game.bol.config.defaultNaturalWeapon)
this.actor.createEmbeddedDocuments('Item', [{ name: game.i18n.localize("BOL.ui.newNaturalWeapon"), type: "item", system }], { renderSheet: true });
});
html.find('.create-natural-protection').click(ev => {
let system = foundry.utils.duplicate(game.bol.config.defaultNaturalProtection)
this.actor.createEmbeddedDocuments('Item', [{ name: game.i18n.localize("BOL.ui.newNaturalProtection"), type: "item", system }], { renderSheet: true });
});
html.find(".toggle-fight-option").click((ev) => { html.find(".toggle-fight-option").click((ev) => {
const li = $(ev.currentTarget).parents(".item") const li = $(ev.currentTarget).parents(".item")
this.actor.toggleFightOption(li.data("itemId")) this.actor.toggleFightOption(li.data("itemId"))
@ -60,6 +69,12 @@ export class BoLActorSheet extends ActorSheet {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
this.actor.spendAlchemyPoint(li.data("itemId"), 1) this.actor.spendAlchemyPoint(li.data("itemId"), 1)
}) })
html.find(".inc-dec-btns-resource").click((ev) => {
const dataset = ev.currentTarget.dataset;
const target = dataset.target
const incr = parseInt(dataset.incr)
this.actor.incDecResources(target, incr)
})
// Incr./Decr. career ranks // Incr./Decr. career ranks
html.find(".inc-dec-btns").click((ev) => { html.find(".inc-dec-btns").click((ev) => {
@ -73,10 +88,9 @@ export class BoLActorSheet extends ActorSheet {
const incr = parseInt(dataset.incr) const incr = parseInt(dataset.incr)
const min = parseInt(dataset.min) const min = parseInt(dataset.min)
const max = parseInt(dataset.max) || 10000 const max = parseInt(dataset.max) || 10000
const itemData = item.data; let value = eval("item." + target)
let value = eval("itemData." + target)
value = value || 0 value = value || 0
console.log("IncDec", item, target, value, operator, min, max) //console.log("IncDec", item, target, value, operator, min, max)
if (operator === "minus") { if (operator === "minus") {
if (value >= min + incr) value -= incr; if (value >= min + incr) value -= incr;
else value = min; else value = min;
@ -95,8 +109,8 @@ export class BoLActorSheet extends ActorSheet {
// Delete Inventory Item // Delete Inventory Item
html.find('.item-delete').click(ev => { html.find('.item-delete').click(ev => {
Dialog.confirm({ Dialog.confirm({
title: "Suppression", title: game.i18n.localize("BOL.ui.deletetitle"),
content: `Vous êtes sûr de vouloir supprimer cet item ?`, content: game.i18n.localize("BOL.ui.confirmdelete"),
yes: () => { yes: () => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
this.actor.deleteEmbeddedDocuments("Item", [li.data("itemId")]) this.actor.deleteEmbeddedDocuments("Item", [li.data("itemId")])
@ -115,17 +129,18 @@ export class BoLActorSheet extends ActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
getData(options) { async getData(options) {
const data = super.getData(options); const data = super.getData(options)
const actorData = duplicate(data.data); const actorData = foundry.utils.duplicate(data)
let formData = duplicate(data) let formData = foundry.utils.duplicate(data)
formData.config = game.bol.config formData.config = game.bol.config
formData.data = actorData.data formData.data = actorData
formData.details = this.actor.details formData.details = this.actor.details
formData.attributes = this.actor.attributes formData.attributes = this.actor.attributes
formData.aptitudes = this.actor.aptitudes formData.aptitudes = this.actor.aptitudes
formData.resources = this.actor.getResourcesFromType() formData.resources = this.actor.getResourcesFromType()
formData.xp = this.actor.system.xp
formData.equipment = this.actor.equipment formData.equipment = this.actor.equipment
formData.equipmentCreature = this.actor.equipmentCreature formData.equipmentCreature = this.actor.equipmentCreature
formData.weapons = this.actor.weapons formData.weapons = this.actor.weapons
@ -134,23 +149,35 @@ export class BoLActorSheet extends ActorSheet {
formData.alchemy = this.actor.alchemy formData.alchemy = this.actor.alchemy
formData.containers = this.actor.containers formData.containers = this.actor.containers
formData.treasure = this.actor.treasure formData.treasure = this.actor.treasure
formData.boleffects = this.actor.boleffects
formData.alchemyrecipe = this.actor.alchemyrecipe formData.alchemyrecipe = this.actor.alchemyrecipe
formData.horoscopes = this.actor.horoscopes
formData.vehicles = this.actor.vehicles formData.vehicles = this.actor.vehicles
formData.fightoptions = this.actor.fightoptions formData.fightoptions = this.actor.fightoptions
formData.ammos = this.actor.ammos formData.ammos = this.actor.ammos
formData.misc = this.actor.misc formData.misc = this.actor.misc
formData.xplog = this.actor.xplog
formData.combat = this.actor.buildCombat() formData.combat = this.actor.buildCombat()
formData.combatCreature = this.actor.buildCombatCreature() formData.initiativeRank = this.actor.getInitiativeRank()
//formData.combatCreature = this.actor.buildCombatCreature()
formData.features = this.actor.buildFeatures() formData.features = this.actor.buildFeatures()
formData.isGM = game.user.isGM formData.isGM = game.user.isGM
formData.options = this.options formData.options = this.options
formData.owner = this.document.isOwner formData.owner = this.document.isOwner
formData.editScore = this.options.editScore formData.editScore = this.options.editScore
formData.useBougette = BoLUtility.getUseBougette() formData.useBougette = (this.actor.type == "character" && BoLUtility.getUseBougette()) || false
formData.bougette = this.actor.getBougette()
formData.charType = this.actor.getCharType()
formData.villainy = this.actor.getVillainy()
formData.isUndead = this.actor.isUndead()
formData.biography = await TextEditor.enrichHTML(this.object.system.details?.biography || "", { async: true })
formData.notes = await TextEditor.enrichHTML(this.object.system.details.notes || "", { async: true })
formData.isSorcerer = this.actor.isSorcerer() formData.isSorcerer = this.actor.isSorcerer()
formData.isAlchemist = this.actor.isAlchemist() formData.isAlchemist = this.actor.isAlchemist()
formData.isAstrologer = this.actor.isAstrologer()
formData.isMysteries = formData.isSorcerer || formData.isAlchemist || formData.isAstrologer
formData.isPriest = this.actor.isPriest() formData.isPriest = this.actor.isPriest()
formData.horoscopeGroupList = game.settings.get("bol", "horoscope-group")
formData.isGM = game.user.isGM formData.isGM = game.user.isGM
@ -170,7 +197,7 @@ export class BoLActorSheet extends ActorSheet {
// Get the type of item to create. // Get the type of item to create.
const type = header.dataset.type; const type = header.dataset.type;
// Grab any data associated with this control. // Grab any data associated with this control.
const data = duplicate(header.dataset); const data = foundry.utils.duplicate(header.dataset);
// Initialize a default name. // Initialize a default name.
const name = `New ${type.capitalize()}`; const name = `New ${type.capitalize()}`;
// Prepare the item object. // Prepare the item object.
@ -233,7 +260,19 @@ export class BoLActorSheet extends ActorSheet {
this.actor.incAttributeXP(dataset.key) this.actor.incAttributeXP(dataset.key)
break; break;
case "careerxp": case "careerxp":
this.actor.incCareerXP( li.data("item-id")) this.actor.incCareerXP(li.data("item-id"))
break;
case "horoscope-minor":
BoLRoll.horoscopeCheck(this.actor, event, "minor")
break
case "horoscope-major":
BoLRoll.horoscopeCheck(this.actor, event, "major")
break
case "horoscope-major-group":
BoLRoll.horoscopeCheck(this.actor, event, "majorgroup")
break
case "bougette":
this.actor.rollBougette()
break; break;
default: break; default: break;

File diff suppressed because it is too large Load Diff

217
module/actor/horde-sheet.js Normal file
View File

@ -0,0 +1,217 @@
/**
* Extend the basic ActorSheet with some very simple modifications
* @extends {ActorSheet}
*/
import { BoLRoll } from "../controllers/bol-rolls.js";
import { BoLUtility } from "../system/bol-utility.js";
export class BoLHordeSheet extends ActorSheet {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["bol", "sheet", "actor"],
template: "systems/bol/templates/actor/horde-sheet.hbs",
width: 860,
height: 600,
dragDrop: [{ dragSelector: ".items-list .item", dropSelector: null }],
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "stats" }]
});
}
/* -------------------------------------------- */
/** @override */
activateListeners(html) {
super.activateListeners(html);
function onLoad() {
let logoSheet = BoLUtility.getLogoActorSheet()
$(".bol-actor-form").css("backgroundImage",`url(${logoSheet})`)
}
// Setup everything onload
$(function () { onLoad(); });
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
// Add Inventory Item
html.find('.item-create').click(this._onItemCreate.bind(this));
// Update Inventory Item
html.find('.item-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item");
const item = this.actor.items.get(li.data("itemId"));
item.sheet.render(true);
})
// Equip/Unequip item
html.find('.item-equip').click(this._onToggleEquip.bind(this));
html.find('.create_item').click(ev => {
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvel Equipement", type: "item" }], { renderSheet: true });
});
// Incr./Decr. career ranks
html.find(".inc-dec-btns").click((ev) => {
const li = $(ev.currentTarget).parents(".item");
if (li) {
const item = this.actor.items.get(li.data("itemId"));
if (item) {
const dataset = ev.currentTarget.dataset;
const operator = dataset.operator;
const target = dataset.target;
const incr = parseInt(dataset.incr)
const min = parseInt(dataset.min)
const max = parseInt(dataset.max) || 10000
let value = eval("item." + target)
value = value || 0
//console.log("IncDec", item, target, value, operator, min, max)
if (operator === "minus") {
if (value >= min + incr) value -= incr;
else value = min;
}
if (operator === "plus") {
if (value <= max - incr) value += incr;
else value = max;
}
let update = { [`${target}`]: value };
item.update(update);
}
}
});
// Delete Inventory Item
html.find('.item-delete').click(ev => {
Dialog.confirm({
title: "Suppression",
content: `Vous êtes sûr de vouloir supprimer cet item ?`,
yes: () => {
const li = $(ev.currentTarget).parents(".item");
this.actor.deleteEmbeddedDocuments("Item", [li.data("itemId")])
li.slideUp(200, () => this.render(false));
},
no: () => { },
defaultYes: false,
});
});
// Rollable abilities.
html.find('.rollable').click(this._onRoll.bind(this));
}
/* -------------------------------------------- */
/** @override */
async getData(options) {
const data = super.getData(options)
let formData = foundry.utils.duplicate(data)
formData.config = game.bol.config
formData.name = this.actor.name
formData.img = this.actor.img
formData.system = foundry.utils.duplicate(this.actor.system)
formData.isGM = game.user.isGM
formData.options = this.options
formData.owner = this.document.isOwner
formData.editScore = this.options.editScore
formData.description = await TextEditor.enrichHTML(this.actor.system.description, {async: true})
formData.isGM = game.user.isGM
console.log("HORDE", formData)
return formData;
}
/* -------------------------------------------- */
/**
* Handle creating a new Owned Item for the actor using initial data defined in the HTML dataset
* @param {Event} event The originating click event
* @private
*/
_onItemCreate(event) {
event.preventDefault();
const header = event.currentTarget;
// Get the type of item to create.
const type = header.dataset.type;
// Grab any data associated with this control.
const data = foundry.utils.duplicate(header.dataset);
// Initialize a default name.
const name = `New ${type.capitalize()}`;
// Prepare the item object.
const itemData = {
name: name,
type: type,
data: data
};
// Remove the type from the dataset since it's in the itemData.type prop.
delete itemData.data["type"];
// Finally, create the item!
return this.actor.createEmbeddedDocuments("Item", [itemData]);
}
_onToggleEquip(event) {
event.preventDefault();
const li = $(event.currentTarget).closest(".item");
const item = this.actor.items.get(li.data("itemId"));
return this.actor.toggleEquipItem(item);
}
/**
* Handle clickable rolls.
* @param {Event} event The originating click event
* @private
*/
_onRoll(event) {
event.preventDefault();
const element = event.currentTarget
const dataset = element.dataset
const rollType = dataset.rollType
const li = $(event.currentTarget).closest(".item")
switch (rollType) {
case "attribute":
BoLRoll.attributeCheck(this.actor, dataset.key, event)
break;
case "aptitude":
BoLRoll.aptitudeCheck(this.actor, dataset.key, event)
break;
case "weapon":
BoLRoll.weaponCheck(this.actor, event)
break;
case "spell":
BoLRoll.spellCheck(this.actor, event)
break;
case "alchemy":
BoLRoll.alchemyCheck(this.actor, event)
break;
case "protection":
this.actor.rollProtection(li.data("item-id"))
break;
case "damage":
this.actor.rollWeaponDamage(li.data("item-id"))
break;
case "aptitudexp":
this.actor.incAptitudeXP(dataset.key)
break;
case "attributexp":
this.actor.incAttributeXP(dataset.key)
break;
case "careerxp":
this.actor.incCareerXP( li.data("item-id"))
break;
default: break;
}
}
/** @override */
setPosition(options = {}) {
const position = super.setPosition(options);
const sheetBody = this.element.find(".sheet-body");
const bodyHeight = position.height - 192;
sheetBody.css("height", bodyHeight);
return position;
}
}

View File

@ -0,0 +1,228 @@
/**
* Extend the basic ActorSheet with some very simple modifications
* @extends {ActorSheet}
*/
import { BoLRoll } from "../controllers/bol-rolls.js";
import { BoLUtility } from "../system/bol-utility.js";
export class BoLVehicleSheet extends ActorSheet {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["bol", "sheet", "actor"],
template: "systems/bol/templates/actor/vehicle-sheet.hbs",
width: 860,
height: 600,
dragDrop: [{ dragSelector: ".items-list .item", dropSelector: null }],
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "stats" }]
});
}
/* -------------------------------------------- */
/** @override */
activateListeners(html) {
super.activateListeners(html);
function onLoad() {
let logoSheet = BoLUtility.getLogoActorSheet()
$(".bol-actor-form").css("backgroundImage",`url(${logoSheet})`)
}
// Setup everything onload
$(function () { onLoad(); });
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
// Add Inventory Item
html.find('.item-create').click(this._onItemCreate.bind(this));
// Update Inventory Item
html.find('.item-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item");
const item = this.actor.items.get(li.data("itemId"));
item.sheet.render(true);
})
// Equip/Unequip item
html.find('.item-equip').click(this._onToggleEquip.bind(this));
html.find('.create_item').click(ev => {
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvel Equipement", type: "item" }], { renderSheet: true });
});
html.find(".toggle-fight-option").click((ev) => {
const li = $(ev.currentTarget).parents(".item")
this.actor.toggleFightOption(li.data("itemId"))
})
html.find(".inc-dec-btns-alchemy").click((ev) => {
const li = $(ev.currentTarget).parents(".item");
this.actor.spendAlchemyPoint(li.data("itemId"), 1)
})
// Incr./Decr. career ranks
html.find(".inc-dec-btns").click((ev) => {
const li = $(ev.currentTarget).parents(".item");
if (li) {
const item = this.actor.items.get(li.data("itemId"));
if (item) {
const dataset = ev.currentTarget.dataset;
const operator = dataset.operator;
const target = dataset.target;
const incr = parseInt(dataset.incr)
const min = parseInt(dataset.min)
const max = parseInt(dataset.max) || 10000
let value = eval("item." + target)
value = value || 0
//console.log("IncDec", item, target, value, operator, min, max)
if (operator === "minus") {
if (value >= min + incr) value -= incr;
else value = min;
}
if (operator === "plus") {
if (value <= max - incr) value += incr;
else value = max;
}
let update = { [`${target}`]: value };
item.update(update);
}
}
});
// Delete Inventory Item
html.find('.item-delete').click(ev => {
Dialog.confirm({
title: "Suppression",
content: `Vous êtes sûr de vouloir supprimer cet item ?`,
yes: () => {
const li = $(ev.currentTarget).parents(".item");
this.actor.deleteEmbeddedDocuments("Item", [li.data("itemId")])
li.slideUp(200, () => this.render(false));
},
no: () => { },
defaultYes: false,
});
});
// Rollable abilities.
html.find('.rollable').click(this._onRoll.bind(this));
}
/* -------------------------------------------- */
/** @override */
async getData(options) {
const data = super.getData(options)
let formData = foundry.utils.duplicate(data)
formData.config = game.bol.config
formData.name = this.actor.name
formData.img = this.actor.img
formData.system = foundry.utils.duplicate(this.actor.system)
formData.weapons = this.actor.vehicleWeapons
formData.isGM = game.user.isGM
formData.options = this.options
formData.owner = this.document.isOwner
formData.editScore = this.options.editScore
formData.description = await TextEditor.enrichHTML(this.actor.system.description, {async: true})
formData.isGM = game.user.isGM
console.log("VEHICLEDATA", formData)
return formData;
}
/* -------------------------------------------- */
/**
* Handle creating a new Owned Item for the actor using initial data defined in the HTML dataset
* @param {Event} event The originating click event
* @private
*/
_onItemCreate(event) {
event.preventDefault();
const header = event.currentTarget;
// Get the type of item to create.
const type = header.dataset.type;
// Grab any data associated with this control.
const data = foundry.utils.duplicate(header.dataset);
// Initialize a default name.
const name = `New ${type.capitalize()}`;
// Prepare the item object.
const itemData = {
name: name,
type: type,
data: data
};
// Remove the type from the dataset since it's in the itemData.type prop.
delete itemData.data["type"];
// Finally, create the item!
return this.actor.createEmbeddedDocuments("Item", [itemData]);
}
_onToggleEquip(event) {
event.preventDefault();
const li = $(event.currentTarget).closest(".item");
const item = this.actor.items.get(li.data("itemId"));
return this.actor.toggleEquipItem(item);
}
/**
* Handle clickable rolls.
* @param {Event} event The originating click event
* @private
*/
_onRoll(event) {
event.preventDefault();
const element = event.currentTarget
const dataset = element.dataset
const rollType = dataset.rollType
const li = $(event.currentTarget).closest(".item")
switch (rollType) {
case "attribute":
BoLRoll.attributeCheck(this.actor, dataset.key, event)
break;
case "aptitude":
BoLRoll.aptitudeCheck(this.actor, dataset.key, event)
break;
case "weapon":
BoLRoll.weaponCheck(this.actor, event)
break;
case "spell":
BoLRoll.spellCheck(this.actor, event)
break;
case "alchemy":
BoLRoll.alchemyCheck(this.actor, event)
break;
case "protection":
this.actor.rollProtection(li.data("item-id"))
break;
case "damage":
this.actor.rollWeaponDamage(li.data("item-id"))
break;
case "aptitudexp":
this.actor.incAptitudeXP(dataset.key)
break;
case "attributexp":
this.actor.incAttributeXP(dataset.key)
break;
case "careerxp":
this.actor.incCareerXP( li.data("item-id"))
break;
default: break;
}
}
/** @override */
setPosition(options = {}) {
const position = super.setPosition(options);
const sheetBody = this.element.find(".sheet-body");
const bodyHeight = position.height - 192;
sheetBody.css("height", bodyHeight);
return position;
}
}

View File

@ -2,6 +2,8 @@
// Import Modules // Import Modules
import { BoLActor } from "./actor/actor.js" import { BoLActor } from "./actor/actor.js"
import { BoLActorSheet } from "./actor/actor-sheet.js" import { BoLActorSheet } from "./actor/actor-sheet.js"
import { BoLVehicleSheet } from "./actor/vehicle-sheet.js"
import { BoLHordeSheet } from "./actor/horde-sheet.js"
import { BoLItem } from "./item/item.js" import { BoLItem } from "./item/item.js"
import { BoLItemSheet } from "./item/item-sheet.js" import { BoLItemSheet } from "./item/item-sheet.js"
import { System, BOL } from "./system/config.js" import { System, BOL } from "./system/config.js"
@ -13,8 +15,8 @@ import { BoLUtility } from "./system/bol-utility.js"
import { BoLCombatManager } from "./system/bol-combat.js" import { BoLCombatManager } from "./system/bol-combat.js"
import { BoLTokenHud } from "./system/bol-action-hud.js" import { BoLTokenHud } from "./system/bol-action-hud.js"
import { BoLHotbar } from "./system/bol-hotbar.js" import { BoLHotbar } from "./system/bol-hotbar.js"
import { BoLAdventureGenerator } from "./system/bol-adventure-generator.js" import { BoLCommands } from "./system/bol-commands.js"
import { BoLCommands} from "./system/bol-commands.js" import { BoLRoll } from "./controllers/bol-rolls.js"
/* -------------------------------------------- */ /* -------------------------------------------- */
Hooks.once('init', async function () { Hooks.once('init', async function () {
@ -23,10 +25,12 @@ Hooks.once('init', async function () {
BoLActor, BoLActor,
BoLItem, BoLItem,
BoLHotbar, BoLHotbar,
BoLRoll,
BoLUtility,
macros: Macros, macros: Macros,
config: BOL config: BOL
}; };
// Game socket // Game socket
game.socket.on("system.bol", sockmsg => { game.socket.on("system.bol", sockmsg => {
BoLUtility.onSocketMessage(sockmsg); BoLUtility.onSocketMessage(sockmsg);
@ -39,7 +43,7 @@ Hooks.once('init', async function () {
*/ */
CONFIG.Combat.initiative = { CONFIG.Combat.initiative = {
formula: "2d6+@attributes.mind.value+@aptitudes.init.value", formula: "2d6+@attributes.mind.value+@aptitudes.init.value",
decimals: 3 decimals: 2
}; };
// Define custom Entity classes // Define custom Entity classes
@ -49,7 +53,10 @@ Hooks.once('init', async function () {
// Register sheet application classes // Register sheet application classes
Actors.unregisterSheet("core", ActorSheet); Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("bol", BoLActorSheet, { makeDefault: true }); Actors.registerSheet("bol", BoLActorSheet, { types: ["character", "encounter"], makeDefault: true })
Actors.registerSheet("bol", BoLVehicleSheet, { types: ["vehicle"], makeDefault: true })
Actors.registerSheet("bol", BoLHordeSheet, { types: ["horde"], makeDefault: true })
Items.unregisterSheet("core", ItemSheet); Items.unregisterSheet("core", ItemSheet);
Items.registerSheet("bol", BoLItemSheet, { makeDefault: true }); Items.registerSheet("bol", BoLItemSheet, { makeDefault: true });
@ -58,8 +65,7 @@ Hooks.once('init', async function () {
BoLTokenHud.init() BoLTokenHud.init()
BoLHotbar.init() BoLHotbar.init()
BoLCommands.init() BoLCommands.init()
BoLAdventureGenerator.init()
// Preload Handlebars Templates // Preload Handlebars Templates
await preloadHandlebarsTemplates(); await preloadHandlebarsTemplates();
@ -71,49 +77,52 @@ Hooks.once('init', async function () {
}); });
/* -------------------------------------------- */
// Register world usage statistics
function registerUsageCount( registerKey ) {
if ( game.user.isGM ) {
game.settings.register(registerKey, "world-key", {
name: "Unique world key",
scope: "world",
config: false,
type: String
});
let worldKey = game.settings.get(registerKey, "world-key")
if ( worldKey == undefined || worldKey == "" ) {
worldKey = randomID(32)
game.settings.set(registerKey, "world-key", worldKey )
}
// Simple API counter
let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.data.version}"`
$.ajax(regURL)
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
function welcomeMessage() { function welcomeMessage() {
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user.id,
whisper: [game.user.id], whisper: [game.user.id],
content: `<div id="welcome-message-pegasus"><span class="rdd-roll-part"> content: `<div id="welcome-message-bol"><span class="rdd-roll-part">
<strong>` + game.i18n.localize("BOL.chat.welcome1") + `</strong><p>` + <strong>` + game.i18n.localize("BOL.chat.welcome1") + `</strong><p>` +
game.i18n.localize("BOL.chat.welcome2") + "<p>" + game.i18n.localize("BOL.chat.welcome2") + "<p>" +
game.i18n.localize("BOL.chat.welcome3") + "<p>" + game.i18n.localize("BOL.chat.welcome3") + "<p>" +
game.i18n.localize("BOL.chat.welcome4") + "</p>" + game.i18n.localize("BOL.chat.welcome4") + "</p>" +
game.i18n.localize("BOL.chat.welcome5") + "</p>" game.i18n.localize("BOL.chat.welcome5") + "<br>" +
} ) game.i18n.localize("BOL.chat.welcome6")
})
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
Hooks.once('ready', async function () { Hooks.once('ready', async function () {
BoLUtility.ready()
registerUsageCount('bol')
BoLUtility.ready()
import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter=>{
console.log("ClassCounter loaded", moduleCounter)
moduleCounter.ClassCounter.registerUsageCount()
}).catch(err=>
console.log("No stats available, giving up.")
)
welcomeMessage() welcomeMessage()
// User warning
if (!game.user.isGM && game.user.character == undefined) {
ui.notifications.info(game.i18n.localize("BOL.chat.pcwarning"));
ChatMessage.create({
content: game.i18n.localize("BOL.chat.pcwarningmsg") + game.user.name,
user: game.user._id
});
}
if (!game.user.isGM && game.user.character && !game.user.character.prototypeToken.actorLink) {
ui.notifications.info(game.i18n.localize("BOL.chat.pcnotlinked"));
ChatMessage.create({
content: game.i18n.localize("BOL.chat.pcnotlinkedmsg") + game.user.name,
user: game.user._id
});
}
}) })

View File

@ -7,7 +7,7 @@ export class BoLRoll {
/* -------------------------------------------- */ /* -------------------------------------------- */
static options() { static options() {
return { classes: ["bol", "dialog"], width: 480, height: 540 }; return { classes: ["bol", "dialog"], width: 480, height: 'fit-content' };
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -16,55 +16,130 @@ export class BoLRoll {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static attributeCheck(actor, key) { static updateApplicableEffects(rollData) {
let appEffects = []
for (let effect of rollData.bolEffects) {
if ( (effect.system.properties.identifier == "always") ||
(effect.system.properties.identifier.includes(rollData.attribute.key)) ||
(rollData.aptitude && effect.system.properties.identifier.includes(rollData.aptitude.key)) ){
appEffects.push(effect)
}
}
return appEffects
}
let attribute = eval(`actor.data.data.attributes.${key}`) /* -------------------------------------------- */
let label = (attribute.label) ? game.i18n.localize(attribute.label) : null static buildHoroscopeGroupList() {
let description = game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label) let horoscopes = game.settings.get("bol", "horoscope-group")
let horoList = [{ id: -1, name: "Aucun", type: "malus", nbDice: 0 }]
for (let id in horoscopes) {
let horo = horoscopes[id]
for (let i = 0; i < horo.availableDice; i++) {
horoList.push({ id: id, name: horo.name, type: horo.type, nbDice: i + 1 })
}
}
return horoList
}
/* -------------------------------------------- */
static getCommonRollData(actor, mode, attribute, aptitude = undefined) {
let rollData = { let rollData = {
mode: "attribute", mode: mode,
actorId: actor.id, actorId: actor.id,
tokenId: actor.token?.id,
img: actor.img, img: actor.img,
attribute: attribute, attribute: attribute,
attrValue: attribute.value, attrValue: attribute.value,
aptValue: 0, aptValue: 0,
label: label,
careerBonus: 0, careerBonus: 0,
description: description, horoscopeBonus: 0,
horoscopeMalus: 0,
selectedHoroscope: [],
armorAgiMalus: actor.getArmorAgiMalus(), armorAgiMalus: actor.getArmorAgiMalus(),
armorInitMalus: actor.getArmorInitMalus(), armorInitMalus: actor.getArmorInitMalus(),
mod: 0 horoscopeBonusList: actor.getHoroscopesBonus(),
horoscopeMalusList: actor.getHoroscopesMalus(),
config: game.bol.config,
adv: "0",
mod: 0,
modRanged: 0,
bolEffects: actor.boleffects,
horoscopeGroupList: this.buildHoroscopeGroupList()
} }
if (aptitude) {
rollData.aptitude = aptitude
rollData.aptValue = aptitude.value
}
rollData.bolApplicableEffects = this.updateApplicableEffects(rollData)
return rollData
}
/* -------------------------------------------- */
static attributeCheck(actor, key="vigor", event=undefined, combatData=undefined) {
let attribute = eval(`actor.system.attributes.${key}`)
let rollData = this.getCommonRollData(actor, "attribute", attribute)
rollData.description = game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label)
rollData.label = (attribute.label) ? game.i18n.localize(attribute.label) : null
console.log(">>>>>>>>>>", rollData, actor) console.log(">>>>>>>>>>", rollData, actor)
return this.displayRollDialog(rollData) return this.displayRollDialog(rollData)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static aptitudeCheck(actor, key) { static aptitudeCheck(actor, key="init", event=undefined, combatData=undefined) {
let aptitude = eval(`actor.data.data.aptitudes.${key}`) let aptitude = eval(`actor.system.aptitudes.${key}`)
let attrKey = this.getDefaultAttribute(key) let attrKey = this.getDefaultAttribute(key)
let attribute = eval(`actor.data.data.attributes.${attrKey}`) let attribute = eval(`actor.system.attributes.${attrKey}`)
let label = (aptitude.label) ? game.i18n.localize(aptitude.label) : null; let rollData = this.getCommonRollData(actor, "aptitude", attribute, aptitude)
let description = game.i18n.localize('BOL.ui.aptitudeCheck') + " - " + game.i18n.localize(aptitude.label);
return this.displayRollDialog( rollData.label = (aptitude.label) ? game.i18n.localize(aptitude.label) : null
{ rollData.description = game.i18n.localize('BOL.ui.aptitudeCheck') + " - " + game.i18n.localize(aptitude.label)
mode: "aptitude", rollData.combatData = combatData // For initiative mainly
actorId: actor.id,
img: actor.img, return this.displayRollDialog(rollData)
attribute: attribute, }
aptitude: aptitude,
attrValue: attribute.value, /* -------------------------------------------- */
aptValue: aptitude.value, static async detectDistance(weapon, target) {
armorAgiMalus: actor.getArmorAgiMalus(), let visible, dist
armorInitMalus: actor.getArmorInitMalus(), if (target && (weapon.system.properties.ranged || weapon.system.properties.throwing)) {
label: label, console.log("target", target, weapon)
careerBonus: 0, visible = canvas.effects.visibility.testVisibility(target.center, { object: _token })
description: description, dist = Number(canvas.grid.measureDistances([{ ray: new Ray(_token.center, target.center) }], { gridSpaces: false })).toFixed(2)
mod: 0 let range = Number(weapon.system.properties.range)
let rangeMsg = "BOL.chat.rangeout"
if (dist <= range) {
rangeMsg = "BOL.chat.range0"
} else if (dist < range * 2) {
rangeMsg = "BOL.chat.range1"
} else if (dist < range * 3) {
rangeMsg = "BOL.chat.range2"
} else if (dist < range * 4) {
rangeMsg = "BOL.chat.range3"
} else if (dist < range * 5) {
rangeMsg = "BOL.chat.range4"
} else if (dist < range * 6) {
rangeMsg = "BOL.chat.range5"
} else if (dist < range * 7) {
rangeMsg = "BOL.chat.range6"
}
ChatMessage.create({
content: await renderTemplate('systems/bol/templates/chat/chat-info-range.hbs', {
weapon: weapon,
attackerName: _token.actor.name,
defenderName: target.actor.name,
weaponRange: weapon.system.properties.range,
visible: visible,
distance: dist,
rangeMsg: rangeMsg
})
}) })
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -72,40 +147,34 @@ export class BoLRoll {
let target = BoLUtility.getTarget() let target = BoLUtility.getTarget()
let weaponData = weapon.data let weaponData = weapon.system
let attribute = eval(`actor.data.data.attributes.${weaponData.properties.attackAttribute}`) let attribute = eval(`actor.system.attributes.${weaponData.properties.attackAttribute}`)
let aptitude = eval(`actor.data.data.aptitudes.${weaponData.properties.attackAptitude}`) let aptitude = eval(`actor.system.aptitudes.${weaponData.properties.attackAptitude}`)
let rollData = this.getCommonRollData(actor, "weapon", attribute, aptitude)
// Compute distance
this.detectDistance(weapon, target)
// Manage specific case // Manage specific case
let fightOption = actor.getActiveFightOption() let fightOption = actor.getActiveFightOption()
if (fightOption && fightOption.data.fightoptiontype == "fulldefense") { if (fightOption && fightOption.system.properties.fightoptiontype == "fulldefense") {
ui.notifications.warn(`{{actor.name}} est en Défense Totale ! Il ne peut pas attaquer ce round.`) ui.notifications.warn(`{{actor.name}} est en Défense Totale ! Il ne peut pas attaquer ce round.`)
return return
} }
// Build the roll structure
let rolldata = { // Update the roll structure
mode: "weapon", rollData.weapon = weapon
actorId: actor.id, rollData.isRanged = weaponData.properties.ranged || weaponData.properties.throwing
img: actor.img, rollData.targetId = target?.id
weapon: weapon, rollData.fightOption = fightOption
isRanged: weaponData.properties.ranged || weaponData.properties.throwing, rollData.defenderId = target?.actor.id
targetId: target?.id, rollData.label = (weapon.name) ? weapon.name : game.i18n.localize('BOL.ui.noWeaponName')
fightOption: fightOption, rollData.description = game.i18n.localize('BOL.ui.weaponAttack') + " : " + weapon.name
careerBonus: 0,
defenderId: target?.data?.actorId, return this.displayRollDialog(rollData)
attribute: attribute,
aptitude: aptitude,
attrValue: attribute.value,
aptValue: aptitude.value,
armorAgiMalus: actor.getArmorAgiMalus(),
armorInitMalus: actor.getArmorInitMalus(),
mod: 0,
modRanged: 0,
label: (weapon.name) ? weapon.name : game.i18n.localize('BOL.ui.noWeaponName'),
description: game.i18n.localize('BOL.ui.weaponAttack') + " : " + weapon.name,
}
return this.displayRollDialog(rolldata)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static weaponCheck(actor, event) { static weaponCheck(actor, event) {
const li = $(event.currentTarget).parents(".item") const li = $(event.currentTarget).parents(".item")
@ -114,7 +183,7 @@ export class BoLRoll {
ui.notifications.warn("Unable to find weapon !") ui.notifications.warn("Unable to find weapon !")
return return
} }
weapon = duplicate(weapon) weapon = foundry.utils.duplicate(weapon)
return this.weaponCheckWithWeapon(actor, weapon) return this.weaponCheckWithWeapon(actor, weapon)
} }
@ -126,61 +195,71 @@ export class BoLRoll {
ui.notifications.warn("Unable to find Alchemy !"); ui.notifications.warn("Unable to find Alchemy !");
return; return;
} }
alchemy = duplicate(alchemy) alchemy = foundry.utils.duplicate(alchemy)
let alchemyData = alchemy.data let alchemyData = alchemy.system
if (alchemyData.properties.pccurrent < alchemyData.properties.pccost) { if (alchemyData.properties.pccurrent < alchemyData.properties.pccost) {
ui.notifications.warn("Pas assez de Points de Cration investis dans la Préparation !") ui.notifications.warn("Pas assez de Points de Création investis dans la Préparation !")
return return
} }
let alchemyDef = { let rollData = this.getCommonRollData(actor, "alchemy", actor.system.attributes.mind)
mode: "alchemy",
actorId: actor.id, rollData.alchemy = alchemy
img: actor.img, rollData.careerBonus = actor.getAlchemistBonus()
alchemy: alchemy, rollData.pcCost = Number(alchemyData.properties.pccost)
attribute: actor.data.data.attributes.mind, rollData.pcCostCurrent = Number(alchemyData.properties.pccurrent)
attrValue: actor.data.data.attributes.mind.value, rollData.mod = Number(alchemyData.properties.difficulty)
aptValue: 0, rollData.label = alchemy.name
careerBonus: actor.getAlchemistBonus(), rollData.description = game.i18n.localize('BOL.ui.makeAlchemy') + "+" + alchemy.name
pcCost: Number(alchemyData.properties.pccost),
pcCostCurrent: Number(alchemyData.properties.pccurrent), console.log("ALCHEMY!", rollData);
mod: Number(alchemyData.properties.difficulty), return this.displayRollDialog(rollData);
armorAgiMalus: actor.getArmorAgiMalus(),
armorInitMalus: actor.getArmorInitMalus(),
label: alchemy.name,
description: game.i18n.localize('BOL.ui.makeAlchemy') + "+" + alchemy.name,
}
console.log("ALCHEMY!", alchemyDef);
return this.displayRollDialog(alchemyDef);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static spellCheckWithSpell( actor, spell ) { static horoscopeCheck(actor, event, horoscopeType) {
let spellDef = {
mode: "spell", let target = BoLUtility.getTarget()
actorId: actor.id,
img: actor.img, let cost = (horoscopeType == "minor") ? 1 : 2
spell: spell, if (cost > actor.getAstrologyPoints()) {
attribute: actor.data.data.attributes.mind, ui.notifications.warn(game.i18n.localize("BOL.ui.astrologyNoPoints"))
attrValue: actor.data.data.attributes.mind.value, return
aptValue: 0,
ppCurrent: Number(actor.data.data.resources.power.value),
careerBonus: actor.getSorcererBonus(),
ppCostArmor: actor.getPPCostArmor(),
ppCost: Number(spell.data.properties.ppcost),
mod: Number(spell.data.properties.difficulty),
armorAgiMalus: actor.getArmorAgiMalus(),
armorInitMalus: actor.getArmorInitMalus(),
label: spell.name,
description: game.i18n.localize('BOL.ui.focusSpell') + " : " + spell.name,
} }
let rollData = this.getCommonRollData(actor, "horoscope", actor.system.attributes.mind)
rollData.careerBonus = actor.getAstrologerBonus()
rollData.horoscopeType = horoscopeType
rollData.horoscopeTypeLabel = "BOL.ui." + horoscopeType
rollData.astrologyPointsCost = cost
rollData.label = game.i18n.localize('BOL.ui.makeHoroscope')
rollData.description = game.i18n.localize('BOL.ui.makeHoroscope') + " " + game.i18n.localize(rollData.horoscopeTypeLabel)
rollData.targetId = target?.id
console.log("HOROSCOPE!", rollData);
return this.displayRollDialog(rollData);
}
/* -------------------------------------------- */
static spellCheckWithSpell(actor, spell) {
let rollData = this.getCommonRollData(actor, "spell", actor.system.attributes.mind)
rollData.spell = spell
rollData.ppCurrent = Number(actor.system.resources.power.value),
rollData.careerBonus = actor.getSorcererBonus(),
rollData.ppCostArmor = actor.getPPCostArmor(),
rollData.ppCost = Number(spell.system.properties.ppcost),
rollData.mod = Number(spell.system.properties.difficulty),
rollData.label = spell.name,
rollData.description = game.i18n.localize('BOL.ui.focusSpell') + " : " + spell.name
//console.log("SPELL!", spellDef) //console.log("SPELL!", spellDef)
return this.displayRollDialog(spellDef) return this.displayRollDialog(rollData)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static spellCheck(actor, event) { static spellCheck(actor, event) {
if (actor.data.data.resources.power.value <= 0) { if (actor.system.resources.power.value <= 0) {
ui.notifications.warn("Plus assez de points de Pouvoir !") ui.notifications.warn("Plus assez de points de Pouvoir !")
return return
} }
@ -190,8 +269,8 @@ export class BoLRoll {
ui.notifications.warn("Impossible de trouver ce sort !") ui.notifications.warn("Impossible de trouver ce sort !")
return return
} }
spell = duplicate(spell) spell = foundry.utils.duplicate(spell)
return this.spellCheckWithSpell( actor, spell) return this.spellCheckWithSpell(actor, spell)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -200,8 +279,35 @@ export class BoLRoll {
this.updateArmorMalus(this.rollData) this.updateArmorMalus(this.rollData)
this.updatePPCost(this.rollData) this.updatePPCost(this.rollData)
// get basic dices from boons/flaws
let effectModifier = 0
this.rollData.bmDice = this.rollData.nbBoons - this.rollData.nbFlaws + this.rollData.bDice - this.rollData.mDice this.rollData.bmDice = this.rollData.nbBoons - this.rollData.nbFlaws + this.rollData.bDice - this.rollData.mDice
// add applicable bonus/malus dices effects
for (let effect of this.rollData.bolApplicableEffects) {
if (effect.system.properties.modifier == "1B") {
this.rollData.bmDice++;
} else if (effect.system.properties.modifier == "2B") {
this.rollData.bmDice += 2;
} else if (effect.system.properties.modifier == "1M") {
this.rollData.bmDice--;
} else if (effect.system.properties.modifier == "2M") {
this.rollData.bmDice -= 2;
} else {
effectModifier += Number(effect.system.properties.modifier)
}
}
this.rollData.bmDice += this.rollData.horoscopeBonus
this.rollData.bmDice -= this.rollData.horoscopeMalus
if (this.rollData.selectedGroupHoroscopeIndex && this.rollData.selectedGroupHoroscopeIndex > 0) {
let horo = this.rollData.horoscopeGroupList[this.rollData.selectedGroupHoroscopeIndex]
this.rollData.bmDice += (horo.type == "malus") ? -horo.nbDice : horo.nbDice;
}
// Keep track of the final effect modifier
this.rollData.effectModifier = effectModifier
// Final number of dices
this.rollData.nbDice = 2 + Math.abs(this.rollData.bmDice) this.rollData.nbDice = 2 + Math.abs(this.rollData.bmDice)
// Bonus or Malus ?
if (this.rollData.bmDice == 0) { if (this.rollData.bmDice == 0) {
$('#roll-nbdice').val("2") $('#roll-nbdice').val("2")
} else { } else {
@ -209,12 +315,19 @@ export class BoLRoll {
$('#roll-nbdice').val("2 + " + String(Math.abs(this.rollData.bmDice)) + letter) $('#roll-nbdice').val("2 + " + String(Math.abs(this.rollData.bmDice)) + letter)
} }
let rollbase = this.rollData.attrValue + "+" + this.rollData.aptValue let rollbase = this.rollData.attrValue + "+" + this.rollData.aptValue
if ( this.rollData.weapon && this.rollData.weapon.data.properties.onlymodifier ) { if (this.rollData.weapon && this.rollData.weapon.system.properties.onlymodifier) {
rollbase = "" rollbase = ""
} }
$('#roll-modifier').val(rollbase + "+" + this.rollData.careerBonus + "+" + this.rollData.mod + "+" + $('#roll-modifier').val(rollbase + "+" + this.rollData.careerBonus + "+" + this.rollData.mod + "+" +
this.rollData.modRanged + "+" + this.rollData.weaponModifier + "-" + this.rollData.defence + "-" + this.rollData.modArmorMalus + "-" + this.rollData.modRanged + "+" + this.rollData.weaponModifier + "-" + this.rollData.defence + "-" + this.rollData.modArmorMalus + "-" +
this.rollData.shieldMalus + "+" + this.rollData.attackModifier + "+" + this.rollData.appliedArmorMalus) this.rollData.shieldMalus + "+" + this.rollData.attackModifier + "+" + this.rollData.appliedArmorMalus + "+" + effectModifier)
// Rebuild lits of applicable effects
let selectEffects = ""
for (let effect of this.rollData.bolApplicableEffects) {
selectEffects += `<option value="${effect.id}" selected>${effect.name}</option>`
}
$('#applicable-effects').html(selectEffects)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -226,20 +339,20 @@ export class BoLRoll {
let fgItem = rollData.fightOption let fgItem = rollData.fightOption
if (fgItem) { if (fgItem) {
console.log(fgItem) console.log(fgItem)
if (fgItem.data.properties.fightoptiontype == "armordefault") { if (fgItem.system.properties.fightoptiontype == "armordefault") {
rollData.modArmorMalus = rollData.armorMalus // Activate the armor malus rollData.modArmorMalus = rollData.armorMalus // Activate the armor malus
rollData.damagesIgnoresArmor = true rollData.damagesIgnoresArmor = true
} }
if (fgItem.data.properties.fightoptiontype == "intrepid") { if (fgItem.system.properties.fightoptiontype == "intrepid") {
rollData.attackModifier += 2 rollData.attackModifier += 2
} }
if (fgItem.data.properties.fightoptiontype == "defense") { if (fgItem.system.properties.fightoptiontype == "defense") {
rollData.attackModifier += -1 rollData.attackModifier += -1
} }
if (fgItem.data.properties.fightoptiontype == "attack") { if (fgItem.system.properties.fightoptiontype == "attack") {
rollData.attackModifier += 1 rollData.attackModifier += 1
} }
if (fgItem.data.properties.fightoptiontype == "twoweaponsdef" || fgItem.data.properties.fightoptiontype == "twoweaponsatt") { if (fgItem.system.properties.fightoptiontype == "twoweaponsdef" || fgItem.system.properties.fightoptiontype == "twoweaponsatt") {
rollData.attackModifier += -1 rollData.attackModifier += -1
} }
} }
@ -274,7 +387,7 @@ export class BoLRoll {
html.find('#optcond').change((event) => { // Dynamic change of PP cost of spell html.find('#optcond').change((event) => { // Dynamic change of PP cost of spell
let pp = BoLUtility.computeSpellCost(this.rollData.spell, event.currentTarget.selectedOptions.length) let pp = BoLUtility.computeSpellCost(this.rollData.spell, event.currentTarget.selectedOptions.length)
this.rollData.ppCost = pp this.rollData.ppCost = pp
this.updatePPCost( this.rollData) this.updatePPCost(this.rollData)
}) })
html.find('#mod').change((event) => { html.find('#mod').change((event) => {
@ -288,16 +401,18 @@ export class BoLRoll {
html.find('#attr').change((event) => { html.find('#attr').change((event) => {
let attrKey = event.currentTarget.value let attrKey = event.currentTarget.value
let actor = game.actors.get( this.rollData.actorId) let actor = BoLUtility.getActorFromRollData(this.rollData)
this.rollData.attribute = duplicate(actor.data.data.attributes[attrKey]) this.rollData.attribute = foundry.utils.duplicate(actor.system.attributes[attrKey])
this.rollData.attrValue = actor.data.data.attributes[attrKey].value this.rollData.attrValue = actor.system.attributes[attrKey].value
this.rollData.bolApplicableEffects = this.updateApplicableEffects(this.rollData)
this.updateTotalDice() this.updateTotalDice()
}) })
html.find('#apt').change((event) => { html.find('#apt').change((event) => {
let aptKey = event.currentTarget.value let aptKey = event.currentTarget.value
let actor = game.actors.get( this.rollData.actorId) let actor = BoLUtility.getActorFromRollData(this.rollData)
this.rollData.aptitude = duplicate(actor.data.data.aptitudes[aptKey]) this.rollData.aptitude = foundry.utils.duplicate(actor.system.aptitudes[aptKey])
this.rollData.aptValue = actor.data.data.aptitudes[aptKey].value this.rollData.aptValue = actor.system.aptitudes[aptKey].value
this.rollData.bolApplicableEffects = this.updateApplicableEffects(this.rollData)
this.updateTotalDice() this.updateTotalDice()
}) })
@ -307,6 +422,7 @@ export class BoLRoll {
} else { } else {
this.rollData.shieldMalus = 0 this.rollData.shieldMalus = 0
} }
this.updateTotalDice()
}) })
html.find('#career').change((event) => { html.find('#career').change((event) => {
@ -334,22 +450,52 @@ export class BoLRoll {
this.rollData.mDice = Number(event.currentTarget.value) this.rollData.mDice = Number(event.currentTarget.value)
this.updateTotalDice() this.updateTotalDice()
}) })
html.find('#horoscope-bonus-applied').change((event) => {
this.rollData.selectedHoroscope = []
for (let option of event.currentTarget.selectedOptions) {
this.rollData.selectedHoroscope.push(foundry.utils.duplicate(this.rollData.horoscopeBonusList[Number(option.index)]))
}
let horoscopes = $('#horoscope-bonus-applied').val()
this.rollData.horoscopeBonus = (!horoscopes || horoscopes.length == 0) ? 0 : horoscopes.length
this.updateTotalDice()
})
html.find('#horoscope-malus-applied').change((event) => {
this.rollData.selectedHoroscope = []
for (let option of event.currentTarget.selectedOptions) {
this.rollData.selectedHoroscope.push(foundry.utils.duplicate(this.rollData.horoscopeBonusList[Number(option.index)]))
}
let horoscopes = $('#horoscope-malus-applied').val()
this.rollData.horoscopeMalus = (!horoscopes || horoscopes.length == 0) ? 0 : horoscopes.length
this.updateTotalDice()
})
html.find('#horoscope-group-applied').change((event) => {
this.rollData.selectedGroupHoroscopeIndex = event.currentTarget.value
this.updateTotalDice()
})
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static preProcessWeapon(rollData, defender) { static preProcessWeapon(rollData, defender) {
if (rollData.mode == "weapon") { if (rollData.mode == "weapon") {
rollData.weaponModifier = rollData.weapon.data.properties.attackModifiers ?? 0; rollData.weaponModifier = rollData.weapon.system.properties.attackModifiers ?? 0
rollData.attackBonusDice = rollData.weapon.data.properties.attackBonusDice rollData.attackBonusDice = rollData.weapon.system.properties.attackBonusDice
if (rollData.attackBonusDice) {
rollData.adv = "1B"
rollData.bDice = 1
}
if (defender) { // If target is selected if (defender) { // If target is selected
rollData.defence = defender.defenseValue rollData.defence = defender.defenseValue
rollData.armorMalus = defender.armorMalusValue rollData.armorMalus = defender.armorMalusValue
rollData.defenderHeroPoints = defender.getHeroPoints()
rollData.shieldBlock = 'none' rollData.shieldBlock = 'none'
let shields = defender.shields let shields = defender.shields
//console.log("Defender stats", defender)
for (let shield of shields) { for (let shield of shields) {
rollData.shieldBlock = (shield.data.properties.blocking.blockingAll) ? 'blockall' : 'blockone'; rollData.shieldBlock = (shield.system.properties.blocking.blockingAll) ? 'blockall' : 'blockone';
rollData.shieldAttackMalus = (shield.data.properties.blocking.malus) ? shield.data.properties.blocking.malus : 1; rollData.shieldAttackMalus = (shield.system.properties.blocking.malus) ? shield.system.properties.blocking.malus : 1;
rollData.applyShieldMalus = false
} }
} }
} }
@ -362,9 +508,9 @@ export class BoLRoll {
// initialize default flags/values // initialize default flags/values
const rollOptionTpl = `systems/bol/templates/dialogs/${rollData.mode}-roll-dialog.hbs` const rollOptionTpl = `systems/bol/templates/dialogs/${rollData.mode}-roll-dialog.hbs`
let actor = game.actors.get( rollData.actorId ) let actor = BoLUtility.getActorFromRollData(rollData)
let defender let defender
if ( rollData.targetId) { if (rollData.targetId) {
let token = game.scenes.current.tokens.get(rollData.targetId) let token = game.scenes.current.tokens.get(rollData.targetId)
defender = token.actor defender = token.actor
} }
@ -381,15 +527,11 @@ export class BoLRoll {
rollData.nbBoons = 0 rollData.nbBoons = 0
rollData.nbFlaws = 0 rollData.nbFlaws = 0
rollData.nbDice = 0 rollData.nbDice = 0
if (rollData.shieldBlock == 'blockall') { rollData.isHeroAdversary = actor.isHeroAdversary()
rollData.shieldMalus = rollData.shieldAttackMalus;
} else {
rollData.shieldMalus = 0
}
rollData.careerBonus = rollData.careerBonus ?? 0 rollData.careerBonus = rollData.careerBonus ?? 0
rollData.modRanged = rollData.modRanged ?? 0 rollData.modRanged = rollData.modRanged ?? 0
rollData.mod = rollData.mod ?? 0 rollData.mod = rollData.mod ?? 0
rollData.id = randomID(16) rollData.id = foundry.utils.randomID(16)
rollData.weaponModifier = 0 rollData.weaponModifier = 0
rollData.attackBonusDice = false rollData.attackBonusDice = false
rollData.armorMalus = 0 rollData.armorMalus = 0
@ -398,6 +540,12 @@ export class BoLRoll {
this.preProcessFightOption(rollData) this.preProcessFightOption(rollData)
this.updateArmorMalus(rollData) this.updateArmorMalus(rollData)
this.updatePPCost(rollData) this.updatePPCost(rollData)
// Prepare blocking case
if (rollData.shieldBlock == 'blockall') {
rollData.shieldMalus = rollData.shieldAttackMalus;
} else {
rollData.shieldMalus = 0
}
// Save // Save
this.rollData = rollData this.rollData = rollData
console.log("ROLLDATA", rollData) console.log("ROLLDATA", rollData)
@ -420,24 +568,26 @@ export class BoLRoll {
icon: '<i class="fas fa-check"></i>', icon: '<i class="fas fa-check"></i>',
label: game.i18n.localize("BOL.ui.submit"), label: game.i18n.localize("BOL.ui.submit"),
callback: (html) => { callback: (html) => {
console.log("Submit Roll!!!!");
if (rollData.mode == 'spell' && rollData.ppCurrent < rollData.ppCost) { // Check PP available if (rollData.mode == 'spell' && rollData.ppCurrent < rollData.ppCost) { // Check PP available
ui.notifications.warn("Pas assez de Points de Pouvoir !") ui.notifications.warn("Pas assez de Points de Pouvoir !")
return return
} }
rollData.registerInit = (rollData.aptitude && rollData.aptitude.key == 'init') ? $('#register-init').is(":checked") : false; rollData.registerInit = (rollData.aptitude && rollData.aptitude.key == 'init') ? $('#register-init').is(":checked") : false;
const isMalus = rollData.mDice > 0 const isMalus = (rollData.bmDice < 0)
rollData.nbDice += (rollData.attackBonusDice) ? 1 : 0
let rollbase = rollData.attrValue + rollData.aptValue let rollbase = rollData.attrValue + rollData.aptValue
if ( rollData.weapon && rollData.weapon.data.properties.onlymodifier ) { if (rollData.weapon?.system.properties.onlymodifier) {
rollbase = 0 rollbase = 0
} }
const modifiers = rollbase + rollData.careerBonus + rollData.mod + rollData.weaponModifier - rollData.defence - rollData.modArmorMalus + rollData.shieldMalus + rollData.attackModifier + rollData.appliedArmorMalus let diceData = BoLUtility.getDiceData()
const formula = (isMalus) ? rollData.nbDice + "d6kl2 + " + modifiers : rollData.nbDice + "d6kh2 + " + modifiers let malusInit = rollData.combatData?.malusInit || 0
const modifiers = rollbase + rollData.careerBonus + rollData.mod + rollData.weaponModifier - rollData.defence - rollData.modArmorMalus + rollData.shieldMalus + rollData.attackModifier + rollData.appliedArmorMalus + rollData.effectModifier - malusInit
const formula = (isMalus) ? rollData.nbDice + "d" + diceData.diceFormula + "kl2 + " + modifiers : rollData.nbDice + "d" + diceData.diceFormula + "kh2 + " + modifiers
rollData.formula = formula rollData.formula = formula
rollData.modifiers = modifiers rollData.modifiers = modifiers
console.log("Rolldata before", rollData)
let r = new BoLDefaultRoll(rollData); let r = new BoLDefaultRoll(rollData);
r.roll(); r.roll();
@ -463,61 +613,95 @@ export class BoLDefaultRoll {
this.rollData.isFumble = false; this.rollData.isFumble = false;
} }
if (this.rollData.optionsId) { if (this.rollData.optionsId) {
BoLUtility.cleanupButtons( this.rollData.optionsId) BoLUtility.cleanupButtons(this.rollData.optionsId)
} }
if (this.rollData.applyId) { if (this.rollData.applyId) {
BoLUtility.cleanupButtons( this.rollData.applyId) BoLUtility.cleanupButtons(this.rollData.applyId)
} }
this.rollData.optionsId = randomID(16) this.rollData.optionsId = foundry.utils.randomID(16)
this.rollData.applyId = randomID(16) this.rollData.applyId = foundry.utils.randomID(16)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async roll() { async roll() {
const r = new Roll(this.rollData.formula) const r = new Roll(this.rollData.formula)
// console.log("Roll formula", this.rollData.formula) await r.roll()
await r.roll({ "async": false })
let diceData = BoLUtility.getDiceData()
//console.log("DICEDATA", diceData)
const activeDice = r.terms[0].results.filter(r => r.active) const activeDice = r.terms[0].results.filter(r => r.active)
const diceTotal = activeDice.map(r => r.result).reduce((a, b) => a + b) const diceTotal = activeDice.map(r => r.result).reduce((a, b) => a + b)
this.rollData.roll = r this.rollData.roll = r
this.rollData.isSuccess = (r.total >= 9) this.rollData.isFumble = (diceTotal <= diceData.criticalFailureValue)
this.rollData.isCritical = (diceTotal === 12) if ( this.rollData.isFumble ) {
this.rollData.isRealCritical = (diceTotal === 12) this.rollData.isSuccess = false
this.rollData.isHeroic = (diceTotal === 12) this.rollData.isCritical = false
this.rollData.isRealCritical = false
this.rollData.isHeroic = false
this.rollData.isFailure = true
} else {
this.rollData.isCritical = (diceTotal >= diceData.criticalSuccessValue)
if ( this.rollData.isCritical) {
this.rollData.isSuccess = true
} else {
this.rollData.isSuccess = (r.total >= diceData.successValue)
}
this.rollData.isRealCritical = (diceTotal >= diceData.criticalSuccessValue)
this.rollData.isHeroic = (diceTotal >= diceData.criticalSuccessValue)
this.rollData.isFailure = !this.rollData.isSuccess
}
this.rollData.isLegendary = false this.rollData.isLegendary = false
this.rollData.isFumble = (diceTotal === 2)
this.rollData.isFailure = !this.rollData.isSuccess
let actor = game.actors.get( this.rollData.actorId) let actor = BoLUtility.getActorFromRollData(this.rollData)
if (this.rollData.reroll == undefined) { if (this.rollData.reroll == undefined) {
this.rollData.reroll = actor.heroReroll() this.rollData.reroll = actor.heroReroll()
} }
if (this.rollData.registerInit) { if (this.rollData.registerInit) {
actor.registerInit(r.total, this.rollData.isCritical, this.rollData.isFumble) await actor.registerInit(this.rollData)
this.rollData.initiativeRank = actor.getInitiativeRank(this.rollData)
if (this.rollData.combatData) { // If combatData present
let combat = game.combats.get(this.rollData.combatData.combatId)
//console.log("SET INIT!!!!!", this.rollData.initiativeRank)
combat.setInitiative(this.rollData.combatData.combatantId, this.rollData.initiativeRank)
}
} }
if (this.rollData.isSuccess && this.rollData.mode == "spell") { // PP cost management if (this.rollData.isSuccess && this.rollData.mode == "spell") { // PP cost management
this.rollData.remainingPP = actor.spendPowerPoint(this.rollData.ppCost + this.rollData.ppCostArmor) this.rollData.remainingPP = actor.spendPowerPoint(this.rollData.ppCost + this.rollData.ppCostArmor)
} }
if (this.rollData.mode == "alchemy") { // PP cost management if (this.rollData.mode == "alchemy") { // PP cost management
actor.resetAlchemyStatus(this.rollData.alchemy._id) actor.resetAlchemyStatus(this.rollData.alchemy._id)
} }
if (this.rollData.mode == "bougette" && this.rollData.isFailure) {
actor.decBougette()
}
await this.sendChatMessage() await this.sendChatMessage()
if (this.rollData.mode == "horoscope") { // PP cost management
actor.manageHoroscope(this.rollData)
}
if (this.rollData.selectedHoroscope.length > 0) { // PP cost management
actor.removeHoroscopeMinor(this.rollData)
}
if (this.rollData.selectedGroupHoroscopeIndex && this.rollData.selectedGroupHoroscopeIndex > 0) { // PP cost management
BoLUtility.removeGroupHoroscope(this.rollData)
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async sendChatMessage() { async sendChatMessage() {
let actor = game.actors.get( this.rollData.actorId) let actor = BoLUtility.getActorFromRollData(this.rollData)
this._buildChatMessage(this.rollData).then( async msgFlavor => { this._buildChatMessage(this.rollData).then(async msgFlavor => {
//console.log("MSG", msgFlavor )
let msg = await this.rollData.roll.toMessage({ let msg = await this.rollData.roll.toMessage({
user: game.user.id, user: game.user.id,
rollMode: game.settings.get("core", "rollMode"), rollMode: game.settings.get("core", "rollMode"),
//whisper: BoLUtility.getWhisperRecipientsAndGMs(this.rollData.actor.name),
flavor: msgFlavor, flavor: msgFlavor,
speaker: ChatMessage.getSpeaker({ actor: actor }), speaker: ChatMessage.getSpeaker({ actor: actor }),
}) })
this.rollData.roll = foundry.utils.duplicate(this.rollData.roll) // Remove object, keep data (v111 ready)
msg.setFlag("world", "bol-roll-data", this.rollData) msg.setFlag("world", "bol-roll-data", this.rollData)
}) })
} }
@ -525,12 +709,15 @@ export class BoLDefaultRoll {
/* -------------------------------------------- */ /* -------------------------------------------- */
upgradeToLegendary() { upgradeToLegendary() {
// Force to Critical roll // Force to Critical roll
let diceData = BoLUtility.getDiceData()
let maxValue = Number(diceData.diceFormula) * 2
this.rollData.isCritical = true this.rollData.isCritical = true
this.rollData.isLegendary = true this.rollData.isLegendary = true
this.rollData.isRealCritical = false this.rollData.isRealCritical = false
this.rollData.isSuccess = true this.rollData.isSuccess = true
this.rollData.isFailure = false this.rollData.isFailure = false
this.rollData.roll = new Roll("12+" + this.rollData.modifiers) this.rollData.roll = new Roll(maxValue + "+" + this.rollData.modifiers)
this.rollData.reroll = false this.rollData.reroll = false
this.sendChatMessage() this.sendChatMessage()
} }
@ -538,17 +725,20 @@ export class BoLDefaultRoll {
/* -------------------------------------------- */ /* -------------------------------------------- */
upgradeToHeroic() { upgradeToHeroic() {
// Force to Critical roll // Force to Critical roll
let diceData = BoLUtility.getDiceData()
let maxValue = Number(diceData.diceFormula) * 2
this.rollData.isCritical = true this.rollData.isCritical = true
this.rollData.isHeroic = true this.rollData.isHeroic = true
this.rollData.isLegendary = false this.rollData.isLegendary = false
this.rollData.isRealCritical = false this.rollData.isRealCritical = false
this.rollData.isSuccess = true this.rollData.isSuccess = true
this.rollData.isFailure = false this.rollData.isFailure = false
this.rollData.roll = new Roll("12+" + this.rollData.modifiers) this.rollData.roll = new Roll(maxValue + "+" + this.rollData.modifiers)
this.rollData.reroll = false this.rollData.reroll = false
this.sendChatMessage() this.sendChatMessage()
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
setSuccess(flag) { setSuccess(flag) {
this.rollData.isSuccess = flag this.rollData.isSuccess = flag
@ -556,7 +746,7 @@ export class BoLDefaultRoll {
/* -------------------------------------------- */ /* -------------------------------------------- */
async sendDamageMessage() { async sendDamageMessage() {
let actor = game.actors.get( this.rollData.actorId) let actor = BoLUtility.getActorFromRollData(this.rollData)
this._buildDamageChatMessage(this.rollData).then(async msgFlavor => { this._buildDamageChatMessage(this.rollData).then(async msgFlavor => {
let msg = await this.rollData.damageRoll.toMessage({ let msg = await this.rollData.damageRoll.toMessage({
user: game.user.id, user: game.user.id,
@ -564,6 +754,7 @@ export class BoLDefaultRoll {
speaker: ChatMessage.getSpeaker({ actor: actor }), speaker: ChatMessage.getSpeaker({ actor: actor }),
flags: { msgType: "default" } flags: { msgType: "default" }
}) })
this.rollData.damageRoll = foundry.utils.duplicate(this.rollData.damageRoll)
this.rollData.actor = undefined // Cleanup this.rollData.actor = undefined // Cleanup
msg.setFlag("world", "bol-roll-data", this.rollData) msg.setFlag("world", "bol-roll-data", this.rollData)
}) })
@ -571,16 +762,8 @@ export class BoLDefaultRoll {
/* -------------------------------------------- */ /* -------------------------------------------- */
getDamageAttributeValue(attrDamage, actorId = undefined) { getDamageAttributeValue(attrDamage, actorId = undefined) {
let attrDamageValue = 0 let actor = BoLUtility.getActorFromRollData(this.rollData)
return actor.getDamageAttributeValue(attrDamage)
let actor = game.actors.get( (actorId) ? actorId: this.rollData.actorId)
if (attrDamage.includes("vigor")) {
attrDamageValue = actor.data.data.attributes.vigor.value
if (attrDamage.includes("half")) {
attrDamageValue = Math.floor(attrDamageValue / 2)
}
}
return attrDamageValue
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -595,20 +778,24 @@ export class BoLDefaultRoll {
if (this.rollData.damageMode == 'damage-plus-6') { if (this.rollData.damageMode == 'damage-plus-6') {
bonusDmg = 6 bonusDmg = 6
} }
if (this.rollData.damageMode == 'damage-plus-12') { if (this.rollData.damageMode == 'damage-plus-12' || this.rollData.damageMode == 'damage-plus-12-legend') {
bonusDmg = 12 bonusDmg = 12
if (this.rollData.damageMode == 'damage-plus-12') { // In this case, the hero point is used (ie shortcut)
let actor = BoLUtility.getActorFromRollData(this.rollData)
actor.subHeroPoints(1)
}
} }
let attrDamageValue = this.getDamageAttributeValue(this.rollData.weapon.data.properties.damageAttribute) let attrDamageValue = this.getDamageAttributeValue(this.rollData.weapon.system.properties.damageAttribute)
let weaponFormula = BoLUtility.getDamageFormula(this.rollData.weapon.data, this.rollData.fightOption) let weaponFormula = BoLUtility.getDamageFormula(this.rollData.weapon.system, this.rollData.fightOption)
let damageFormula = weaponFormula + "+" + bonusDmg + "+" + attrDamageValue let damageFormula = weaponFormula + "+" + bonusDmg + "+" + attrDamageValue
console.log("DAMAGE !!!", damageFormula, attrDamageValue, this.rollData)
//console.log("Formula", weaponFormula, damageFormula, this.rollData.weapon.data.data.properties.damage) //console.log("Formula", weaponFormula, damageFormula, this.rollData.weapon.data.data.properties.damage)
this.rollData.damageFormula = damageFormula this.rollData.damageFormula = damageFormula
this.rollData.damageRoll = new Roll(damageFormula) this.rollData.damageRoll = new Roll(damageFormula)
await this.rollData.damageRoll.roll({ "async": false }) await this.rollData.damageRoll.roll()
this.rollData.damageTotal = this.rollData.damageRoll.total this.rollData.damageTotal = this.rollData.damageRoll.total
console.log("DAMAGE !!!", damageFormula, attrDamageValue, this.rollData)
} }
BoLUtility.cleanupButtons(this.rollData.optionsId) BoLUtility.cleanupButtons(this.rollData.optionsId)
this.sendDamageMessage() this.sendDamageMessage()
@ -623,8 +810,8 @@ export class BoLDefaultRoll {
/* -------------------------------------------- */ /* -------------------------------------------- */
_buildChatMessage(rollData) { _buildChatMessage(rollData) {
const rollMessageTpl = 'systems/bol/templates/chat/rolls/default-roll-card.hbs'; const rollMessageTpl = 'systems/bol/templates/chat/rolls/default-roll-card.hbs'
return renderTemplate(rollMessageTpl, rollData); return renderTemplate(rollMessageTpl, rollData)
} }
} }

View File

@ -8,7 +8,7 @@ export class BoLItemSheet extends ItemSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["bol", "sheet", "item"], classes: ["bol", "sheet", "item"],
template: "systems/bol/templates/item/item-sheet.hbs", template: "systems/bol/templates/item/item-sheet.hbs",
width: 650, width: 650,
@ -19,43 +19,45 @@ export class BoLItemSheet extends ItemSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
getData(options) { async getData(options) {
const data = super.getData(options); const data = super.getData(options)
const itemData = data.data; let itemData = foundry.utils.duplicate(data.document)
data.config = game.bol.config; data.config = game.bol.config
data.item = itemData; data.item = itemData
data.data = itemData.data; data.category = itemData.system.category
data.category = itemData.category;
data.itemProperties = this.item.itemProperties;
data.isGM = game.user.isGM; data.isGM = game.user.isGM;
data.itemProperties = this.item.itemProperties;
data.description = await TextEditor.enrichHTML(this.object.system.description, { async: true })
if (data.document.actor) {
data.careers = data.document.actor.careers
}
// Dynamic default data fix/adapt // Dynamic default data fix/adapt
if (itemData.type == "item") { if (itemData.type == "item") {
if (!itemData.data.category) { if (!itemData.system.category) {
itemData.data.category = "equipment" itemData.system.category = "equipment"
} }
if ( itemData.data.category == "equipment" && itemData.data.properties.equipable) { if (itemData.system.category == "equipment" && itemData.system.properties.equipable) {
if (!itemData.data.properties.slot) { if (!itemData.system.properties.slot) {
itemData.data.properties.slot = "-" itemData.system.properties.slot = "-"
} }
} }
if (itemData.data.category == 'spell') { if (itemData.system.category == 'spell') {
if(!itemData.data.properties.mandatoryconditions) { if (!itemData.system.properties.mandatoryconditions) {
itemData.data.properties.mandatoryconditions = [] itemData.system.properties.mandatoryconditions = []
} }
if(!itemData.data.properties.optionnalconditions) { if (!itemData.system.properties.optionnalconditions) {
itemData.data.properties.optionnalconditions = [] itemData.system.properties.optionnalconditions = []
} }
for (let i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
itemData.data.properties.mandatoryconditions[i] = itemData.data.properties.mandatoryconditions[i] ?? "" itemData.system.properties.mandatoryconditions[i] = itemData.system.properties.mandatoryconditions[i] ?? ""
} }
for (let i = 0; i < 8; i++) { for (let i = 0; i < 8; i++) {
itemData.data.properties.optionnalconditions[i] = itemData.data.properties.optionnalconditions[i] ?? "" itemData.system.properties.optionnalconditions[i] = itemData.system.properties.optionnalconditions[i] ?? ""
} }
} }
} else { } else {
if (!itemData.data.subtype) { if (!itemData.system.subtype) {
itemData.data.category = "origin" itemData.system.category = "origin"
} }
} }
@ -64,7 +66,27 @@ export class BoLItemSheet extends ItemSheet {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_getHeaderButtons() {
let buttons = super._getHeaderButtons();
buttons.unshift({
class: "post",
icon: "fas fa-comment",
onclick: ev => this.postItem()
});
return buttons
}
/* -------------------------------------------- */
postItem() {
let chatData = foundry.utils.duplicate(this.item)
if (this.actor) {
chatData.actor = { id: this.actor.id };
}
BoLUtility.postItem(chatData);
}
/* -------------------------------------------- */
/** @override */ /** @override */
setPosition(options = {}) { setPosition(options = {}) {
const position = super.setPosition(options); const position = super.setPosition(options);

View File

@ -7,21 +7,17 @@ export class BoLItem extends Item {
* Augment the basic Item data model with additional dynamic data. * Augment the basic Item data model with additional dynamic data.
*/ */
prepareData() { prepareData() {
super.prepareData(); super.prepareData()
// console.debug("Item prepareData");
// Get the Item's data
const itemData = this.data;
// console.log(itemData);
const actorData = this.actor ? this.actor.data : {};
const data = itemData.data;
}
get properties() { const actorData = this.actor ? this.actor.system : {}
return this.data.properties;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
get properties() {
return this.system.properties
}
/* -------------------------------------------- */
/** /**
* Get the Array of item properties which are used in the small sidebar of the description tab * Get the Array of item properties which are used in the small sidebar of the description tab
* @return {Array} * @return {Array}
@ -29,11 +25,11 @@ export class BoLItem extends Item {
*/ */
get itemProperties() { get itemProperties() {
const props = []; const props = [];
if ( this.data.type === "item" ) { if ( this.type === "item" ) {
const entries = Object.entries(this.data.data.properties); const entries = Object.entries(this.system.properties)
props.push(...entries.filter(e => e[1] === true).map(e => { return game.bol.config.itemProperties2[e[0]] })); props.push(...entries.filter(e => e[1] === true).map(e => { return game.bol.config.itemProperties2[e[0]] }))
} }
return props.filter(p => !!p); return props.filter(p => !!p)
} }

View File

@ -1,620 +0,0 @@
{
"titre1": [
{
"prefix": "la",
"name": "Prophétie"
},
{
"prefix": "les",
"name": "Grottes",
"isLieu": true
},
{
"prefix": "les",
"name": "Collines",
"isLieu": true
},
{
"prefix": "les",
"name": "Voleurs",
"isEnnemi": true,
"isCarriere": true
},
{
"prefix": "les",
"name": "Sorcier(s)",
"isEnnemi": true,
"isCarriere": true
},
{
"prefix": "la",
"name": "Bataille"
},
{
"prefix": "la",
"name": "Légende"
},
{
"prefix": "la",
"name": "Tour",
"isLieu": true
},
{
"prefix": "l'",
"name": "Ile",
"isLieu": true
},
{
"prefix": "les",
"name": "Pirates",
"isEnnemi": true,
"isCarriere": true
},
{
"prefix": "les",
"name": "Druide(s)",
"isEnnemi": true,
"isCarriere": true
},
{
"prefix": "le",
"name": "Navire",
"isCarriere": false
},
{
"prefix": "la",
"name": "Couronne",
"isObjet": true
},
{
"prefix": "la",
"name": "Cité",
"isLieu": true
},
{
"prefix": "le",
"name": "Désert",
"isLieu": true
},
{
"prefix": "les",
"name": "Bête(s)",
"isEnnemi": true,
"isLieu": false
},
{
"prefix": "les",
"name": "Démon(s)",
"isEnnemi": true,
"isLieu": false
},
{
"prefix": "le",
"name": "Trésor",
"isObjet": true
},
{
"prefix": "l'",
"name": "Epée",
"isObjet": true
},
{
"prefix": "l'",
"name": "Arène",
"isLieu": true
},
{
"prefix": "les",
"name": "Marais",
"isLieu": true
},
{
"prefix": "les",
"name": "Seigneur(s)",
"isEnnemi": true,
"isLieu": false
},
{
"prefix": "les",
"name": "Assassin(s)",
"isEnnemi": true,
"isCarriere": true
},
{
"prefix": "le",
"name": "Culte",
"isEnnemi": true,
"isCarriere": false
},
{
"prefix": "le",
"name": "Secret",
"isCarriere": false
},
{
"prefix": "le",
"name": "Palais",
"isLieu": true
},
{
"prefix": "la",
"name": "Mer",
"isLieu": true
},
{
"prefix": "les",
"name": "Barbares",
"isEnnemi": true,
"isCarriere": true
},
{
"prefix": "le",
"name": "Manuscrit",
"isObjet": true
},
{
"prefix": "les",
"name": "Plaines",
"isLieu": true
},
{
"prefix": "le",
"name": "Sang",
"isLieu": false
},
{
"prefix": "la",
"name": "Tombe",
"isLieu": true
},
{
"prefix": "la",
"name": "Forêt",
"isLieu": true
},
{
"prefix": "les",
"name": "Esclaves",
"isEnnemi": true,
"isCarriere": true
},
{
"prefix": "les",
"name": "Mendiant(s)",
"isEnnemi": true,
"isCarriere": true
},
{
"prefix": "les",
"name": "Montagnes",
"isCarriereLieu": true
}
],
"titre2": [
{
"prefix": "du",
"name": "mal"
},
{
"prefix": "et le",
"name": "Roi Maussade",
"isEnnemi": true
},
{
"prefix": "et la",
"name": "pestilence",
"isEnnemi": false
},
{
"prefix": "de",
"name": "Malakut",
"isLieu": true
},
{
"prefix": "d'",
"name": "Halakh",
"isLieu": true
},
{
"prefix": "d'",
"name": "Hyrdral",
"isLieu": true
},
{
"prefix": "des",
"name": "esprits abandonnés",
"isEnnemi": true
},
{
"prefix": "du",
"name": "chaos",
"isEnnemi": true
},
{
"prefix": "de la",
"name": "folie",
"isEnnemi": false
},
{
"prefix": "de",
"name": "Satarla",
"isLieu": true
},
{
"prefix": "d'",
"name": "Urceb",
"isLieu": true
},
{
"prefix": "des",
"name": "Terres Désolées",
"isLieu": true
},
{
"prefix": "de la",
"name": "mort",
"isLieu": false
},
{
"prefix": "des",
"name": "idoles impies",
"isObjet": true
},
{
"prefix": "des",
"name": "ténèbres",
"isObjet": false
},
{
"prefix": "de",
"name": "Parsool",
"isLieu": true
},
{
"prefix": "de",
"name": "Qiddesh",
"isLieu": true
},
{
"prefix": "de",
"name": "Kasht",
"isLieu": true
},
{
"prefix": "de la ",
"name": "falalité",
"isLieu": false
},
{
"prefix": "du",
"name": "Nécromant",
"isEnnemi": true
},
{
"prefix": "du",
"name": "Néant",
"isEnnemi": false
},
{
"prefix": "de",
"name": "Lysor",
"isLieu": true
},
{
"prefix": "d'",
"name": "Oosal",
"isLieu": true
},
{
"prefix": "de",
"name": "Thulé",
"isLieu": true
},
{
"prefix": "du",
"name": "désespoir",
"isLieu": false
},
{
"prefix": "du",
"name": "Dieu Bouffi",
"isEnnemi": true
},
{
"prefix": "du",
"name": "silence",
"isEnnemi": false
},
{
"prefix": "de",
"name": "Tyrus",
"isLieu": true
},
{
"prefix": "d'",
"name": "Ygddar",
"isLieu": true
},
{
"prefix": "de",
"name": "la Côte de Feu",
"isLieu": true
},
{
"prefix": "des",
"name": "ombres cruelles",
"isLieu": false
},
{
"prefix": "de la",
"name": "poussière écarlate",
"isLieu": false
},
{
"prefix": "du",
"name": "destin",
"isLieu": false
},
{
"prefix": "du",
"name": "Valgard",
"isLieu": true
},
{
"prefix": "de",
"name": "Qeb",
"isLieu": true
},
{
"prefix": "de",
"name": "la Mer Inconnue",
"isLieu": true
}
],
"mission": [
{
"name": "dattaquer un lieu."
},
{
"name": "de détruire un certain objet."
},
{
"name": "de kidnapper quelquun."
},
{
"name": "dobtenir une certaine chose."
},
{
"name": "dexplorer un lieu."
},
{
"name": "de sauver une personne."
},
{
"name": "déchapper à quelquun."
},
{
"name": "de fuir un lieu."
},
{
"name": "de trouver une personne."
},
{
"name": "de trouver un lieu."
},
{
"name": "de trouver chose."
},
{
"name": "de protéger une personne."
},
{
"name": "de protéger un lieu."
},
{
"name": "de protéger chose."
},
{
"name": "de dérober une certaine chose."
},
{
"name": "de tuer une personne."
},
{
"name": "de détruire une chose."
},
{
"name": "descorter une personne."
},
{
"name": "de transporter une chose."
}
],
"carriere": [
"Noble",
"Acrobate",
"Sorcier",
"Alchimiste",
"Esclave",
"Courtisane",
"Médecin",
"Marin",
"Érudit",
"Mendiant",
"Scribe",
"Poète",
"Forgeron",
"Prêtre",
"Danseur",
"Marchand",
"Pilote des airs",
"Fermier"
],
"lieux1": [
"Palais",
"Donjon",
"Ruines",
"Sanctuaire",
"Crypte",
"Forteresse",
"Tombeau",
"Grottes",
"Tour",
"Antre",
"Île",
"Montagne"
],
"lieux2": [
"de la mort.",
"de la destruction.",
"du désespoir.",
"des morts-vivants.",
"du sage.",
"de l'or.",
"de la tempête.",
"de la terreur.",
"descannibales.",
"du désespoir.",
"des Rois-Sorciers.",
"des âmes perdues."
],
"objets1": [
"Livre",
"Anneau",
"Coupe",
"Joyau",
"Casque",
"Parchemin",
"Couronne",
"Sceau",
"Cristal",
"Crâne",
"Épée",
"Bâton"
],
"objets2": [
"des sept sceaux.",
"de l'éternelle douleur.",
"du sang bouillonnant.",
"de la mort hideuse.",
"du pouvoir suprême.",
"du serpent sournois.",
"du plaisir infini.",
"de la richesse illusoire.",
"de la cruelle trahison.",
"du froid funeste.",
"des spectres inapaisés.",
"du mystère."
],
"motivation": [
"cest le genre de choses que fait Krongar.",
"sinon il finira en prison.",
"il est victime dun chantage.",
"il a trouvé une carte.",
"il a été maudit.",
"il a eu une vision (peut-être un soir de beuverie).",
"il a été engagé pour le faire.",
"il a surpris une conversation.",
"il a lu quelque chose dans un ancien manuscrit.",
"il est tombé accidentellement dans cette affaire.",
"il cherche à assouvir une vengeance.",
"il a ,été dupé."
],
"rival": [
"un poète obsédé.",
"un prince (esse) guerrier.",
"un ministre corrompu.",
"un sectateur fanatique.",
"un noble arrogant.",
"un étrange alchimiste.",
"un sorcier maléfique.",
"un druide cruel.",
"un marchand cupide.",
"un brigand sans foi ni loi.",
"un démon sanguinaire.",
"un fantôme errant."
],
"dieu": [
"Tharungozoth",
"Yrzlak",
"Dyr",
"Knothakon",
"Hadron",
"Shazzadion",
"Chiomalla",
"SaTel",
"Morgazzon",
"Hurm",
"Afyra",
"Grondil",
"Zaggath",
"Zalkyr",
"Fillana",
"Lilandra",
"Zylidith",
"Quathoomar",
"Iondal",
"Piandra",
"Nemmereth",
"Charkond",
"Karyzon",
"Zarymphyxos",
"Kryphondus"
],
"complique1": [
"cest toujours comme ça avec Krongar !",
"la situation réveille chez Krongar des peurs ancestrales.",
"un usurier et ses hommes de main veulent récupérer leur argent.",
"une grave épidémie ravage la région.",
"Krongar est traqué pour un crime passé.",
"les actions dun groupe de rebelles rendent la région peu sûre.",
"des hordes de guerriers envahissent la région pour la conquérir",
"un(e) ancien(ne) admirateur (trice) éconduit(e) cherche à se venger.",
"la loi locale est très sévère et interdit une chose nécessaire à laccomplissement de la mission.",
"un(e) admirateur (trice) inattendu(e) déclare son amour.",
"un rival qui fut défait autrefois réapparaît et met son grain de sel.",
"la folie de Morgazzon fait des ravages dans la région."
],
"obstacle": [
"dun ancien secret.",
"dun long voyage.",
"dune malédiction.",
"dun voleur rusé.",
"dune forte troupe de soldats.",
"dun énorme monstre.",
"dune horde de monstres.",
"dun manque de temps.",
"de gardes et de pièges magiques.",
"dune catastrophe naturelle sur le point de se produire.",
"dune énigme à résoudre.",
"dune bataille à gagner."
],
"retournement": [
"Lennemi est en fait Krongar lui-même, venu dune autre réalité !",
"Toute cette histoire était un piège machiavélique !",
"Lennemi est en fait un vieil ami ou un allié qui a comploté dans lombre !",
"Krongar est contraint de sassocier à un rival pour accomplir la mission !",
"Tout ce qui semblait ordinaire se révèle en fait surnaturel !",
"Lennemi est en fait le père, la mère, le frère ou la sœur de Krongar !",
"Une toute autre mission attend en fait notre héros !",
"Parfois, il ny a pas de retournement de situation !",
"i la mission est accomplie, cela entraînera de terribles répercussions !",
"Le destin offre à Krongar une chance daméliorer les choses, et il est renvoyé dans le temps au début de laventure. La saga recommence, mais cette fois sans retournement de situation !",
"Un ami ou un allié a trahi Krongar !",
"Les dieux sont furieux et lui imposent d'autres tâches"
],
"recompense": [
"Rien du tout ! On sest joué de lui !",
"Beaucoup moins quescompté.",
"Beaucoup moins quescompté, mais il gagne au moins la reconnaissance dune personne haut placée.",
"Beaucoup moins quescompté, mais il est marqué par les dieux (avantage).",
"La récompense escomptée.",
"La récompense escomptée, et il est marqué par les dieux (avantage).",
"La récompense escomptée, ainsi que la reconnaissance dune personne haut placée.",
"Plus quescompté.",
"Plus quescompté, ainsi que la reconnaissance dune personne haut placée.",
"Plus quescompté, et il est marqué par les dieux (avantage).",
"Plus quescompté, ainsi que la reconnaissance dune personne haut placée, et il est marqué par les dieux (avantage).",
"Une promotion... Longue vie au roi Krongar !"
]
}

View File

@ -1,5 +1,6 @@
/* -------------------------------------------- */ /* -------------------------------------------- */
import { BoLRoll } from "../controllers/bol-rolls.js"; import { BoLRoll } from "../controllers/bol-rolls.js";
import { BoLUtility } from "../system/bol-utility.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class BoLTokenHud { export class BoLTokenHud {
@ -30,10 +31,17 @@ export class BoLTokenHud {
(event) => { (event) => {
let actionIndex = Number(event.currentTarget.attributes['data-action-index'].value) let actionIndex = Number(event.currentTarget.attributes['data-action-index'].value)
let action = hudData.actionsList[actionIndex] let action = hudData.actionsList[actionIndex]
const weapon = actor.items.get( action._id ) const actionItem = actor.items.get(action._id)
BoLRoll.weaponCheckWithWeapon(hudData.actor, duplicate(weapon)) if (actionItem.system.subtype == "weapon") {
//console.log("Clicked", action) BoLRoll.weaponCheckWithWeapon(hudData.actor, foundry.utils.duplicate(actionItem))
} ) } else if (actionItem.system.subtype == "fightoption") {
let chatData = foundry.utils.duplicate(actionItem)
if (actionItem.actor) {
chatData.actor = { id: actionItem.actor._id };
}
BoLUtility.postItem(chatData);
}
})
const controlIconTarget = html.find('.control-icon[data-action=target]'); const controlIconTarget = html.find('.control-icon[data-action=target]');
// att+apt+career // att+apt+career
@ -41,18 +49,18 @@ export class BoLTokenHud {
(event) => { (event) => {
let rollIndex = Number(event.currentTarget.attributes['data-roll-index'].value) let rollIndex = Number(event.currentTarget.attributes['data-roll-index'].value)
let roll = hudData.rollsList[rollIndex] let roll = hudData.rollsList[rollIndex]
if ( roll.type == "aptitude") { if (roll.type == "aptitude") {
BoLRoll.aptitudeCheck(actor, roll.key ) BoLRoll.aptitudeCheck(actor, roll.key)
} else if ( roll.type == "attribute") { } else if (roll.type == "attribute") {
BoLRoll.attributeCheck(actor, roll.key ) BoLRoll.attributeCheck(actor, roll.key)
} }
}) })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async addTokenHudExtensions(app, html, tokenId) { static async addTokenHudExtensions(app, html, tokenId) {
const controlIconCombat = html.find('.control-icon[data-action=combat]') const controlIconCombat = html.find('.control-icon[data-action=combat]')
if (controlIconCombat.length>0 ) { if (controlIconCombat.length > 0) {
BoLTokenHud.addExtensionHud(app, html, tokenId); BoLTokenHud.addExtensionHud(app, html, tokenId);
} }
} }
@ -61,9 +69,9 @@ export class BoLTokenHud {
static async _configureSubMenu(insertionPoint, template, hudData, onMenuItem) { static async _configureSubMenu(insertionPoint, template, hudData, onMenuItem) {
const hud = $(await renderTemplate(template, hudData)) const hud = $(await renderTemplate(template, hudData))
const list = hud.find('div.bol-hud-list') const list = hud.find('div.bol-hud-list')
BoLTokenHud._toggleHudListActive(hud, list); BoLTokenHud._toggleHudListActive(hud, list);
hud.find('img.bol-hud-togglebutton').click(event => BoLTokenHud._toggleHudListActive(hud, list)); hud.find('img.bol-hud-togglebutton').click(event => BoLTokenHud._toggleHudListActive(hud, list));
list.find('.bol-hud-menu').click(onMenuItem); list.find('.bol-hud-menu').click(onMenuItem);

View File

@ -1,86 +0,0 @@
/* -------------------------------------------- */
import { BoLUtility } from "./bol-utility.js";
/* -------------------------------------------- */
export class BoLAdventureGenerator {
/* -------------------------------------------- */
static async init() {
this.adventureData = await fetchJsonWithTimeout("systems/bol/module/system/adventure_data.json")
}
/* -------------------------------------------- */
static async createAdventure() {
let roll1 = new Roll("1d" + this.adventureData.titre1.length).evaluate({ async: false })
let roll2 = new Roll("1d" + this.adventureData.titre2.length).evaluate({ async: false })
let p1 = this.adventureData.titre1[roll1.result - 1]
let p2 = this.adventureData.titre2[roll2.result - 1]
let story = {}
story.title = "Krongar et " + p1.prefix + " " + p1.name + " " + p2.prefix + " " + p2.name
let rollM = new Roll("1d" + this.adventureData.mission.length).evaluate({ async: false })
story.mission = "La mission de Krongar est de " + this.adventureData.mission[rollM.result - 1].name
if (!p1.isCarriere && !p2.isCarriere) {
let rollC = new Roll("1d" + this.adventureData.carriere.length).evaluate({ async: false })
story.carriere = "Une carrière : " + this.adventureData.carriere[rollC.result - 1]
}
if (!p1.isLieu && !p2.isLieu) {
let rollL1 = new Roll("1d" + this.adventureData.lieux1.length).evaluate({ async: false })
let rollL2 = new Roll("1d" + this.adventureData.lieux2.length).evaluate({ async: false })
story.lieu = "Un lieu : " + this.adventureData.lieux1[rollL1.result - 1] + " " + this.adventureData.lieux2[rollL2.result - 1]
}
if (!p1.isObjet && !p2.isObjet) {
let rollO1 = new Roll("1d" + this.adventureData.objets1.length).evaluate({ async: false })
let rollO2 = new Roll("1d" + this.adventureData.objets2.length).evaluate({ async: false })
story.objet = "Un objet : " + this.adventureData.objets1[rollO1.result - 1] + " " + this.adventureData.objets2[rollO2.result - 1]
}
let rollMOT = new Roll("1d" + this.adventureData.motivation.length).evaluate({ async: false })
story.motivation = "Krongar entreprend cette mission parce que " + this.adventureData.motivation[rollMOT.result - 1]
if (!p1.isEnnemi && !p2.isEnnemi) {
let rollE = new Roll("1d" + this.adventureData.rival.length).evaluate({ async: false })
story.rival = "Un rival : " + this.adventureData.rival[rollE.result - 1]
}
let rollDieu = new Roll("1d6").evaluate({ async: false })
if (rollDieu.result == 6) {
rollDieu = new Roll("1d" + this.adventureData.dieu.length).evaluate({ async: false })
story.dieu = "Un Dieu est impliqué : " + this.adventureData.dieu[rollDieu.result - 1]
}
let rollComp = new Roll("1d6").evaluate({ async: false })
if (rollComp.result >= 5) {
rollComp = new Roll("1d" + this.adventureData.complique1.length).evaluate({ async: false })
story.complication = "Une complication : " + this.adventureData.complique1[rollComp.result - 1]
}
let rollObs = new Roll("1d6").evaluate({ async: false })
if (rollObs.result >= 5) {
rollObs = new Roll("1d" + this.adventureData.obstacle.length).evaluate({ async: false })
story.obstacle = "Un obstacle : " + this.adventureData.obstacle[rollObs.result - 1]
}
let rollRet = new Roll("1d6").evaluate({ async: false })
if (rollRet.result == 6) {
rollRet = new Roll("1d" + this.adventureData.retournement.length).evaluate({ async: false })
story.retournement = "Un retournement : " + this.adventureData.retournement[rollRet.result - 1]
}
let rollRec = new Roll("1d" + this.adventureData.recompense.length).evaluate({ async: false })
story.recompense = "Pour sa peine, Krongar reçoit " + this.adventureData.recompense[rollRec.result - 1]
ChatMessage.create({
alias: this.name,
whisper: BoLUtility.getUsers(user => user.isGM),
content: await renderTemplate('systems/bol/templates/chat/chat-adventure-result.hbs',
{ name: "Aventure !", img: "icons/commodities/gems/gem-cluster-red.webp", story : story})
})
}
}

View File

@ -40,14 +40,14 @@ export class BoLCalendar extends Application {
constructor() { constructor() {
super(); super();
// position // position
this.calendarPos = duplicate(game.settings.get(SYSTEM_RDD, "calendar-pos")); this.calendarPos = foundry.utils.duplicate(game.settings.get("bol", "calendar-pos"));
if (this.calendarPos == undefined || this.calendarPos.top == undefined) { if (this.calendarPos == undefined || this.calendarPos.top == undefined) {
this.calendrierPos = BoLCalendar.createCalendarPos() this.calendrierPos = BoLCalendar.createCalendarPos()
game.settings.set("bol", "calendar-pos", this.calendarPos) game.settings.set("bol", "calendar-pos", this.calendarPos)
} }
// Calendar // Calendar
this.calendar = duplicate(game.settings.get("bol", "calendar") ?? BoLCalendar.getCalendar(0)); this.calendar = foundry.utils.duplicate(game.settings.get("bol", "calendar") ?? BoLCalendar.getCalendar(0));
this.calendar.year = this.calendar.year || 900 this.calendar.year = this.calendar.year || 900
this.calendar.month = 0 this.calendar.month = 0
@ -58,7 +58,7 @@ export class BoLCalendar extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
template: "systems/bol/templates/calendar-template.html", template: "systems/bol/templates/calendar-template.html",
popOut: false, popOut: false,
resizable: false resizable: false
@ -95,11 +95,11 @@ export class BoLCalendar extends Application {
this.calendar.hour -= 24 this.calendar.hour -= 24
await this.incrementDay() await this.incrementDay()
} }
game.settings.set("bol", "calendar", duplicate(this.calendar)); game.settings.set("bol", "calendar", foundry.utils.duplicate(this.calendar));
// Notification aux joueurs // TODO: replace with Hook on game settings update // Notification aux joueurs // TODO: replace with Hook on game settings update
game.socket.emit(SYSTEM_SOCKET_ID, { game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_sync_time", msg: "msg_sync_time",
data: duplicate(this.calendrier) data: foundry.utils.duplicate(this.calendrier)
}); });
} }
@ -112,7 +112,7 @@ export class BoLCalendar extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
syncPlayerTime(calendrier) { syncPlayerTime(calendrier) {
this.calendrier = duplicate(calendrier); // Local copy update this.calendrier = foundry.utils.duplicate(calendrier); // Local copy update
this.updateDisplay(); this.updateDisplay();
} }
@ -123,7 +123,7 @@ export class BoLCalendar extends Application {
} }
this.calendrier.heureRdD = indexHeure; this.calendrier.heureRdD = indexHeure;
this.calendrier.minutesRelative = 0; this.calendrier.minutesRelative = 0;
game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier)); game.settings.set(SYSTEM_RDD, "calendrier", foundry.utils.duplicate(this.calendrier));
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -312,13 +312,13 @@ export class BoLCalendar extends Application {
this.calendrier.jour = Number(calendrierData.jourMois) - 1; this.calendrier.jour = Number(calendrierData.jourMois) - 1;
this.calendrier.moisRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.moisKey); this.calendrier.moisRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.moisKey);
this.calendrier.heureRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.heureKey); this.calendrier.heureRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.heureKey);
game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier)); game.settings.set(SYSTEM_RDD, "calendrier", foundry.utils.duplicate(this.calendrier));
await this.rebuildListeNombreAstral(); await this.rebuildListeNombreAstral();
game.socket.emit(SYSTEM_SOCKET_ID, { game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_sync_time", msg: "msg_sync_time",
data: duplicate(this.calendrier) data: foundry.utils.duplicate(this.calendrier)
}); });
this.updateDisplay(); this.updateDisplay();
@ -326,7 +326,7 @@ export class BoLCalendar extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
async showCalendarEditor() { async showCalendarEditor() {
let calendrierData = duplicate(this.fillCalendrierData()); let calendrierData = foundry.utils.duplicate(this.fillCalendrierData());
if (this.editeur == undefined) { if (this.editeur == undefined) {
calendrierData.jourMoisOptions = RdDCalendrier.buildJoursMois(); calendrierData.jourMoisOptions = RdDCalendrier.buildJoursMois();
calendrierData.heuresOptions = [0, 1]; calendrierData.heuresOptions = [0, 1];
@ -344,7 +344,7 @@ export class BoLCalendar extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
async showAstrologieEditor() { async showAstrologieEditor() {
let calendrierData = duplicate(this.fillCalendrierData()); let calendrierData = foundry.utils.duplicate(this.fillCalendrierData());
let astrologieArray = []; let astrologieArray = [];
this.listeNombreAstral = this.listeNombreAstral || []; this.listeNombreAstral = this.listeNombreAstral || [];
for (let astralData of this.listeNombreAstral) { for (let astralData of this.listeNombreAstral) {
@ -353,7 +353,7 @@ export class BoLCalendar extends Application {
let actor = game.actors.get(vf.actorId); let actor = game.actors.get(vf.actorId);
vf.actorName = (actor) ? actor.name : "Inconnu"; vf.actorName = (actor) ? actor.name : "Inconnu";
} }
astrologieArray.push(duplicate(astralData)); astrologieArray.push(foundry.utils.duplicate(astralData));
} }
let heuresParActeur = {}; let heuresParActeur = {};
for (let actor of game.actors) { for (let actor of game.actors) {
@ -448,7 +448,7 @@ export class BoLCalendar extends Application {
game.system.rdd.calendrier.calendrierPos.top = yPos; game.system.rdd.calendrier.calendrierPos.top = yPos;
game.system.rdd.calendrier.calendrierPos.left = xPos; game.system.rdd.calendrier.calendrierPos.left = xPos;
if (game.user.isGM) { if (game.user.isGM) {
game.settings.set(SYSTEM_RDD, "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos)); game.settings.set(SYSTEM_RDD, "calendrier-pos", foundry.utils.duplicate(game.system.rdd.calendrier.calendrierPos));
} }
} }
} }
@ -456,7 +456,7 @@ export class BoLCalendar extends Application {
game.system.rdd.calendrier.calendrierPos.top = 200; game.system.rdd.calendrier.calendrierPos.top = 200;
game.system.rdd.calendrier.calendrierPos.left = 200; game.system.rdd.calendrier.calendrierPos.left = 200;
if (game.user.isGM) { if (game.user.isGM) {
game.settings.set(SYSTEM_RDD, "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos)); game.settings.set(SYSTEM_RDD, "calendrier-pos", foundry.utils.duplicate(game.system.rdd.calendrier.calendrierPos));
} }
this.setPos(game.system.rdd.calendrier.calendrierPos); this.setPos(game.system.rdd.calendrier.calendrierPos);
} }

View File

@ -10,41 +10,25 @@ Init order =
3 - Echec critique 3 - Echec critique
*/ */
import { BoLUtility } from "../system/bol-utility.js";
export class BoLCombatManager extends Combat { export class BoLCombatManager extends Combat {
/************************************************************************************/ /************************************************************************************/
async rollInitiative(ids, formula = undefined, messageOptions = {}) { async rollInitiative(ids, formula = undefined, messageOptions = {}) {
console.log(`${game.data.system.data.title} | Combat.rollInitiative()`, ids, formula, messageOptions); console.log(`${game.system.title} | Combat.rollInitiative()`, ids, formula, messageOptions);
// Structure input data // Structure input data
ids = typeof ids === "string" ? [ids] : ids; ids = typeof ids === "string" ? [ids] : ids;
const currentId = this.combatant._id; // Get initiative malus from tough/adversary
let malusInit = 0
for (let combatant of this.combatants) {
malusInit = Math.max(malusInit, combatant.actor.getInitiativeMalus())
}
// calculate initiative // calculate initiative
for (let cId = 0; cId < ids.length; cId++) { for (let cId = 0; cId < ids.length; cId++) {
const combatant = this.combatants.get(ids[cId]); const combatant = this.combatants.get(ids[cId])
let fvttInit = 5 let fvttInit = combatant.actor.getInitiativeRank(false, true, { combatId: this.id, combatantId: combatant.id, malusInit })
if (combatant.actor.type == 'character') {
let initData = combatant.actor.getLastInitData()
console.log("Init data !!!", initData)
if (initData.isLegendary) {
fvttInit = 10
} else if (initData.isCritical) {
fvttInit = 9
} else if (initData.lastinit >= 9) {
fvttInit = 8
} else if (initData.isFumble) {
fvttInit = 3
}
} else {
fvttInit = 4 // Pietaille par defaut
if ( combatant.actor.getSubtype == 'adversary') {
fvttInit = 7
}
if ( combatant.actor.getSubtype == 'tough') {
fvttInit = 6
}
}
fvttInit += (cId / 100) fvttInit += (cId / 100)
await this.updateEmbeddedDocuments("Combatant", [{ _id: ids[cId], initiative: fvttInit }]); await this.updateEmbeddedDocuments("Combatant", [{ _id: ids[cId], initiative: fvttInit }]);
} }
@ -52,14 +36,65 @@ export class BoLCombatManager extends Combat {
/************************************************************************************/ /************************************************************************************/
nextRound() { nextRound() {
let combatants = this.combatants.contents if (game.user.isGM) {
for (let c of combatants) { let combatants = this.combatants.contents
let actor = game.actors.get( c.data.actorId ) let autoRemoveDead = game.settings.get("bol", "auto-remove-dead") // Optionnal auto-removal of dead char.
actor.clearRoundModifiers() let updates = []
for (let c of combatants) {
if (c.actor.type == "horde") {
let actor = game.actors.get(c.actorId)
updates.push({ _id: c.id, name: actor.name + " (" + actor.system.hordesize + ")" })
}
c.actor.clearRoundModifiers()
let toRemove = []
if (autoRemoveDead && c.actor.type == "encounter" &&
(c.actor.system.chartype == "tough" || c.actor.system.chartype == "creature" || c.actor.system.chartype == "base") && c.actor.system.resources.hp.value <= 0) {
toRemove.push(c.id || c._id)
}
//console.log("REM", autoRemoveDead, toRemove, c.actor)
if (toRemove.length > 0) {
this.deleteEmbeddedDocuments('Combatant', toRemove)
}
if (updates.length > 0) {
this.updateEmbeddedDocuments('Combatant', updates)
}
}
} }
super.nextRound() super.nextRound()
} }
/************************************************************************************/
startCombat() {
if (game.user.isGM) {
let updates = []
let combatants = this.combatants.contents
for (let c of combatants) {
let actor = game.actors.get(c.actorId)
actor.storeVitaliteCombat()
if (c.actor.type == "horde") {
let actor = game.actors.get(c.actorId)
updates.push({ _id: c.id, name: actor.name + " (" + actor.system.hordesize + ")" })
}
}
if (updates.length > 0) {
this.updateEmbeddedDocuments('Combatant', updates)
}
}
return super.startCombat()
}
/*-***********************************************************************************/
_onDelete() {
if (game.user.isGM) {
let combatants = this.combatants.contents
for (let c of combatants) {
let actor = game.actors.get(c.actorId)
actor.clearInitiative()
actor.displayRecuperation()
}
}
super._onDelete()
}
} }

View File

@ -1,5 +1,3 @@
/* -------------------------------------------- */
import { BoLAdventureGenerator } from "./bol-adventure-generator.js"
/* -------------------------------------------- */ /* -------------------------------------------- */
export class BoLCommands { export class BoLCommands {
@ -7,7 +5,6 @@ export class BoLCommands {
static init() { static init() {
if (!game.bol.commands) { if (!game.bol.commands) {
const bolCommands = new BoLCommands() const bolCommands = new BoLCommands()
bolCommands.registerCommand({ path: ["/adventure"], func: (content, msg, params) => BoLAdventureGenerator.createAdventure(), descr: "Nouvelle idée d'aventure!" });
game.bol.commands = bolCommands game.bol.commands = bolCommands
} }
@ -86,7 +83,7 @@ export class BoLCommands {
console.log("===> Processing command") console.log("===> Processing command")
let command = commandsTable[name]; let command = commandsTable[name];
path = path + name + " "; path = path + name + " ";
if (command && command.subTable) { if (command?.subTable) {
if (params[0]) { if (params[0]) {
return this._processCommand(command.subTable, params[0], params.slice(1), content, msg, path) return this._processCommand(command.subTable, params[0], params.slice(1), content, msg, path)
} }
@ -95,9 +92,9 @@ export class BoLCommands {
return true; return true;
} }
} }
if (command && command.func) { if (command?.func) {
const result = command.func(content, msg, params); const result = command.func(content, msg, params);
if (result == false) { if (!result) {
BoLCommands._chatAnswer(msg, command.descr); BoLCommands._chatAnswer(msg, command.descr);
} }
return true; return true;

View File

@ -2,6 +2,21 @@ import { BoLRoll } from "../controllers/bol-rolls.js";
export class BoLHotbar { export class BoLHotbar {
static async assignToHotBar( item, slot) {
let command = `game.bol.BoLHotbar.rollMacro("${item.name}", "${item.type}");`
let macro = game.macros.contents.find(m => (m.name === item.name) && (m.command === command))
if (!macro) {
macro = await Macro.create({
name: item.name,
type: "script",
img: item.img,
command: command
}, { displaySheet: false })
}
await game.user.assignHotbarMacro(macro, slot);
}
/** /**
* Create a macro when dropping an entity on the hotbar * Create a macro when dropping an entity on the hotbar
* Item - open roll dialog for item * Item - open roll dialog for item
@ -10,55 +25,20 @@ export class BoLHotbar {
*/ */
static init( ) { static init( ) {
Hooks.on("hotbarDrop", async (bar, documentData, slot) => { Hooks.on("hotbarDrop", (bar, documentData, slot) => {
// Create item macro if rollable item - weapon, spell, prayer, trait, or skill // Create item macro if rollable item - weapon, spell, prayer, trait, or skill
if (documentData.type == "Item") { if (documentData.type == "Item") {
console.log("Drop done !!!", bar, documentData, slot) let item = fromUuidSync(documentData.uuid)
let item = documentData.data if (item == undefined) {
let command = `game.bol.BoLHotbar.rollMacro("${item.name}", "${item.type}");` item = this.actor.items.get(documentData.uuid)
let macro = game.macros.contents.find(m => (m.name === item.name) && (m.command === command))
if (!macro) {
macro = await Macro.create({
name: item.name,
type: "script",
img: item.img,
command: command
}, { displaySheet: false })
} }
game.user.assignHotbarMacro(macro, slot); if (item && (item.system.subtype === "weapon" || item.system.category === "spell")) {
} this.assignToHotBar( item, slot )
// Create a macro to open the actor sheet of the actor dropped on the hotbar return false
else if (documentData.type == "Actor") {
let actor = game.actors.get(documentData.id);
let command = `game.actors.get("${documentData.id}").sheet.render(true)`
let macro = game.macros.contents.find(m => (m.name === actor.name) && (m.command === command));
if (!macro) {
macro = await Macro.create({
name: actor.data.name,
type: "script",
img: actor.data.img,
command: command
}, { displaySheet: false })
game.user.assignHotbarMacro(macro, slot);
} }
} }
// Create a macro to open the journal sheet of the journal dropped on the hotbar return true
else if (documentData.type == "JournalEntry") { })
let journal = game.journal.get(documentData.id);
let command = `game.journal.get("${documentData.id}").sheet.render(true)`
let macro = game.macros.contents.find(m => (m.name === journal.name) && (m.command === command));
if (!macro) {
macro = await Macro.create({
name: journal.data.name,
type: "script",
img: "systems/bol/icons/images/icone_parchement_vierge.webp",
command: command
}, { displaySheet: false })
game.user.assignHotbarMacro(macro, slot);
}
}
return false;
});
} }
/** Roll macro */ /** Roll macro */
@ -68,18 +48,18 @@ export class BoLHotbar {
if (speaker.token) actor = game.actors.tokens[speaker.token] if (speaker.token) actor = game.actors.tokens[speaker.token]
if (!actor) actor = game.actors.get(speaker.actor) if (!actor) actor = game.actors.get(speaker.actor)
if (!actor) { if (!actor) {
return ui.notifications.warn(`Selectionnez votre personnage pour utiliser la macro`) return ui.notifications.warn( game.i18n.localize("BOL.ui.selectactor") )
} }
let item = actor.items.find(it => it.name === itemName && it.type == itemType) let item = actor.items.find(it => it.name === itemName && it.type == itemType)
if (!item ) { if (!item ) {
return ui.notifications.warn(`Impossible de trouver l'objet de cette macro`) return ui.notifications.warn( game.i18n.localize("BOL.ui.itemnotfound") )
} }
// Trigger the item roll // Trigger the item roll
if (item.data.data.category === "equipment" && item.data.data.subtype === "weapon") { if (item.system.category === "equipment" && item.system.subtype === "weapon") {
return BoLRoll.weaponCheckWithWeapon( actor, item) return BoLRoll.weaponCheckWithWeapon( actor, item)
} }
if (item.data.data.category === "spell") { if (item.system.category === "spell") {
return BoLRoll.spellCheckWithSpell( actor, item) return BoLRoll.spellCheckWithSpell( actor, item)
} }
} }

View File

@ -1,18 +1,16 @@
import { BoLDefaultRoll } from "../controllers/bol-rolls.js"; import { BoLRoll, BoLDefaultRoll } from "../controllers/bol-rolls.js";
// Spell circle to min PP cost // Spell circle to min PP cost
const __circle2minpp = { 0: 0, 1: 2, 2: 6, 3: 11 } const __circle2minpp = { 0: 0, 1: 2, 2: 6, 3: 11 }
const __validDices = { "6": 1, "8": 1, "10": 1, "12": 1 }
export class BoLUtility { export class BoLUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static init() { static init() {
this.attackStore = {}
game.settings.register("bol", "rollArmor", { game.settings.register("bol", "rollArmor", {
name: "Effectuer des jets pour les armures", name: game.i18n.localize("BOL.settings.rollArmor"),
hint: "Effectue un jet de dés pour les armures (valeur fixe si désactivé)", hint: game.i18n.localize("BOL.settings.rollArmorTooltip"),
scope: "world", scope: "world",
config: true, config: true,
default: true, default: true,
@ -20,17 +18,92 @@ export class BoLUtility {
onChange: lang => window.location.reload() onChange: lang => window.location.reload()
}) })
game.settings.register("bol", "useBougette", { game.settings.register("bol", "useBougette", {
name: "Utiliser la Bougette (règle fan-made)", name: game.i18n.localize("BOL.settings.useBougette"),
hint: "Utilise un indicateur de Bougette, comme décrit dans l'aide de jeu Gold&Glory du RatierBretonnien (https://www.lahiette.com/leratierbretonnien/)", hint: game.i18n.localize("BOL.settings.useBougetteTooltip"),
scope: "world", scope: "world",
config: true, config: true,
default: false, default: false,
type: Boolean, type: Boolean,
onChange: lang => window.location.reload() onChange: lang => window.location.reload()
}) })
game.settings.register("bol", "auto-remove-dead", {
name: game.i18n.localize("BOL.settings.removeDead"),
hint: game.i18n.localize("BOL.settings.removeDeadTooltip"),
scope: "world",
config: true,
default: false,
type: Boolean
})
game.settings.register("bol", "dice-formula", {
name: game.i18n.localize("BOL.settings.diceFormula"),
hint: game.i18n.localize("BOL.settings.diceFormulaTooltip"),
scope: "world",
config: true,
default: "6",
type: String,
choices: { "6": "2d6", "8": "2d8", "10": "2d10", "12": "2d12", "20": "2d20" },
onChange: value => {
BoLUtility.setDiceFormula(value)
}
})
game.settings.register("bol", "dice-success-value", {
name: game.i18n.localize("BOL.settings.diceSuccessValue"),
hint: game.i18n.localize("BOL.settings.diceSuccessValueTooltip"),
scope: "world",
config: true,
default: 9,
range: {
min: 2,
max: 40,
step: 1
},
type: Number,
onChange: value => {
BoLUtility.setSuccessValue(value)
}
})
game.settings.register("bol", "dice-critical-success-value", {
name: game.i18n.localize("BOL.settings.diceCriticalValue"),
hint: game.i18n.localize("BOL.settings.diceCriticalValueTooltip"),
scope: "world",
config: true,
default: 12,
range: {
min: 2,
max: 40,
step: 1
},
type: Number,
onChange: value => {
BoLUtility.setCriticalSuccessValue(value)
}
})
game.settings.register("bol", "dice-critical-failure-value", {
name: game.i18n.localize("BOL.settings.diceCriticalFailure"),
hint: game.i18n.localize("BOL.settings.diceCriticalFailureTooltip"),
scope: "world",
config: true,
default: 2,
range: {
min: 2,
max: 40,
step: 1
},
type: Number,
onChange: value => {
BoLUtility.setCriticalFailureValue(value)
}
})
game.settings.register("world", "character-summary-data", {
name: "character-summary-data",
scope: "world",
config: false,
default: { npcList: [], x: 200, y: 200 },
type: Object
})
game.settings.register("bol", "logoActorSheet", { game.settings.register("bol", "logoActorSheet", {
name: "Chemin du logo des fiches de perso", name: game.i18n.localize("BOL.settings.defaultLogoActorSheetPath"),
hint: "Vous pouvez changer le logo BoL des fiches de perso, pour jouer dans un autre univers (idéalement 346 x 200, défaut : /systems/bol/ui/logo.webp)", hint: game.i18n.localize("BOL.settings.defaultLogoPathActorSheetTooltip"),
scope: "world", scope: "world",
config: true, config: true,
default: "/systems/bol/ui/logo.webp", default: "/systems/bol/ui/logo.webp",
@ -38,21 +111,62 @@ export class BoLUtility {
onChange: lang => window.location.reload() onChange: lang => window.location.reload()
}) })
game.settings.register("bol", "logoTopLeft", { game.settings.register("bol", "logoTopLeft", {
name: "Chemin du logo haut gauche", name: game.i18n.localize("BOL.settings.defaultLogoTopLeftPath"),
hint: "Vous pouvez changer le logo BoL en haut à gauche de chaque écran (idéalement 718 x 416, défaut : /systems/bol/ui/logo2.webp)", hint: game.i18n.localize("BOL.settings.defaultLogoTopLeftPathTooltip"),
scope: "world", scope: "world",
config: true, config: true,
default: "/systems/bol/ui/logo2.webp", default: "/systems/bol/ui/logo2.webp",
type: String, type: String,
onChange: lang => window.location.reload() onChange: lang => window.location.reload()
}) })
game.settings.register("bol", "horoscope-group", {
name: "horoscope-group",
scope: "world",
config: false,
default: {},
type: Object
})
this.rollArmor = game.settings.get("bol", "rollArmor") // Roll armor or not this.rollArmor = game.settings.get("bol", "rollArmor") // Roll armor or not
this.useBougette = game.settings.get("bol", "useBougette") // Use optionnal bougette rules this.useBougette = game.settings.get("bol", "useBougette") // Use optionnal bougette rules
this.actorSheetLogo = game.settings.get("bol", "logoActorSheet") || "/systems/bol/ui/logo.webp" this.actorSheetLogo = game.settings.get("bol", "logoActorSheet") || "/systems/bol/ui/logo.webp"
this.logoTopLeft = game.settings.get("bol", "logoTopLeft") || "/systems/bol/ui/logo2.webp" this.logoTopLeft = game.settings.get("bol", "logoTopLeft") || "/systems/bol/ui/logo2.webp"
this.diceFormula = game.settings.get("bol", "dice-formula")
this.successValue = Number(game.settings.get("bol", "dice-success-value"))
this.criticalSuccessValue = Number(game.settings.get("bol", "dice-critical-success-value"))
this.criticalFailureValue = Number(game.settings.get("bol", "dice-critical-failure-value"))
// Update the effect modifiers
game.bol.config.effectIdentifiers = foundry.utils.mergeObject(game.bol.config.effectIdentifiers, game.bol.config.attackAttributes)
game.bol.config.effectIdentifiers = foundry.utils.mergeObject(game.bol.config.effectIdentifiers, game.bol.config.aptitudes)
} }
/* -------------------------------------------- */
static setDiceFormula(value) {
this.diceFormula = value
}
static setSuccessValue(value) {
this.successValue = Number(value)
}
static setCriticalSuccessValue(value) {
this.criticalSuccessValue = Number(value)
}
static setCriticalFailureValue(value) {
this.criticalFailureValue = Number(value)
}
static getDiceData() {
let df = this.diceFormula
if (!__validDices[String(this.diceFormula)]) {
df = "6"
}
return {
diceFormula: df,
successValue: this.successValue,
criticalSuccessValue: this.criticalSuccessValue,
criticalFailureValue: this.criticalFailureValue
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static getRollArmor() { static getRollArmor() {
return this.rollArmor return this.rollArmor
@ -69,36 +183,64 @@ export class BoLUtility {
static getLogoTopLeft() { static getLogoTopLeft() {
return this.logoTopLeft return this.logoTopLeft
} }
/* -------------------------------------------- */
static getActorFromRollData(rollData) {
let actor = game.actors.get(rollData.actorId)
if (rollData.tokenId) {
let token = canvas.tokens.placeables.find(t => t.id == rollData.tokenId)
if (token) {
actor = token.actor
}
}
return actor
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async ready() { static async ready() {
//$("#logo").attr("src", this.getLogoTopLeft() ) //$("#logo").attr("src", this.getLogoTopLeft() )
$("#logo").css("content",`url(${this.getLogoTopLeft()})`) $("#logo").css("content", `url(${this.getLogoTopLeft()})`)
CONFIG.statusEffects = foundry.utils.duplicate(game.bol.config.statusEffects)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static templateData(it) { static chatDataSetup(content, modeOverride, isRoll = false, forceWhisper) {
return BoLUtility.data(it)?.data ?? {} let chatData = {
} user: game.user.id,
rollMode: modeOverride || game.settings.get("core", "rollMode"),
content: content
};
/* -------------------------------------------- */ if (["gmroll", "blindroll"].includes(chatData.rollMode)) chatData["whisper"] = ChatMessage.getWhisperRecipients("GM").map(u => u.id);
static data(it) { if (chatData.rollMode === "blindroll") chatData["blind"] = true;
if (it instanceof Actor || it instanceof Item || it instanceof Combatant) { else if (chatData.rollMode === "selfroll") chatData["whisper"] = [game.user];
return it.data;
if (forceWhisper) { // Final force !
chatData["speaker"] = ChatMessage.getSpeaker();
chatData["whisper"] = ChatMessage.getWhisperRecipients(forceWhisper);
} }
return it;
return chatData;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static storeRoll(roll) { static postItem(chatData) {
this.rollTab[roll.id] = roll // Don't post any image for the item (which would leave a large gap) if the default image is used
} if (chatData.img.includes("/blank.png")) {
chatData.img = null;
}
// JSON object for easy creation
chatData.jsondata = JSON.stringify(
{
compendium: "postedItem",
payload: chatData,
});
/* -------------------------------------------- */ renderTemplate('systems/bol/templates/item/post-item.hbs', chatData).then(html => {
static getRoll(rollId) { let chatOptions = BoLUtility.chatDataSetup(html);
return this.rollTab[roll.id] ChatMessage.create(chatOptions)
});
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static createDirectOptionList(min, max) { static createDirectOptionList(min, max) {
let options = {}; let options = {};
@ -143,7 +285,7 @@ export class BoLUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getUsers(filter) { static getUsers(filter) {
return game.users.filter(filter).map(user => user.data._id); return game.users.filter(filter).map(user => user.id);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getWhisperRecipients(rollMode, name) { static getWhisperRecipients(rollMode, name) {
@ -159,7 +301,7 @@ export class BoLUtility {
let users = [] let users = []
for (let user of game.users) { for (let user of game.users) {
if (!user.isGM && user.name != name) { if (!user.isGM && user.name != name) {
users.push(user.data._id) users.push(user.id)
} }
} }
return users return users
@ -173,7 +315,7 @@ export class BoLUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static blindMessageToGM(chatOptions) { static blindMessageToGM(chatOptions) {
let chatGM = duplicate(chatOptions); let chatGM = foundry.utils.duplicate(chatOptions);
chatGM.whisper = this.getUsers(user => user.isGM); chatGM.whisper = this.getUsers(user => user.isGM);
chatGM.content = "Blind message of " + game.user.name + "<br>" + chatOptions.content; chatGM.content = "Blind message of " + game.user.name + "<br>" + chatOptions.content;
console.log("blindMessageToGM", chatGM); console.log("blindMessageToGM", chatGM);
@ -181,13 +323,13 @@ export class BoLUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static sendAttackSuccess(attackDef) { static sendAttackSuccess(rollData) {
if (attackDef.targetId) { if (rollData.targetId) {
// Broadcast to GM or process it directly in case of GM defense // Broadcast to GM or process it directly in case of GM defense
if (!game.user.isGM) { if (!game.user.isGM) {
game.socket.emit("system.bol", { name: "msg_attack_success", data: duplicate(attackDef) }) game.socket.emit("system.bol", { name: "msg_attack_success", data: foundry.utils.duplicate(rollData) })
} else { } else {
BoLUtility.processAttackSuccess(attackDef) BoLUtility.processAttackSuccess(rollData)
} }
} }
} }
@ -199,7 +341,7 @@ export class BoLUtility {
// If the user is the message author or the actor owner, proceed // If the user is the message author or the actor owner, proceed
const actor = game.actors.get(data.message.speaker.actor) const actor = game.actors.get(data.message.speaker.actor)
//console.log("FOUND 1!!! ", actor) //console.log("FOUND 1!!! ", actor)
if (actor && actor.isOwner) return if (actor?.isOwner) return
else if (game.user.isGM || data.author.id === game.user.id) return else if (game.user.isGM || data.author.id === game.user.id) return
const divButtons = chatCard.find('.actions-section') const divButtons = chatCard.find('.actions-section')
@ -213,6 +355,14 @@ export class BoLUtility {
let message = game.messages.get(messageId) let message = game.messages.get(messageId)
return message.getFlag("world", "bol-roll-data") return message.getFlag("world", "bol-roll-data")
} }
/* -------------------------------------------- */
static requestInitRoll(actorId, combatData) {
let actor = game.actors.get(actorId)
if (actor?.isOwner) {
ui.notifications.info(game.i18n.localize("BOL.ui.warninitiative"))
BoLRoll.aptitudeCheck(actor, "init", undefined, combatData)
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static cleanupButtons(id) { static cleanupButtons(id) {
@ -268,10 +418,15 @@ export class BoLUtility {
html.on("click", '.damage-handling', event => { html.on("click", '.damage-handling', event => {
event.preventDefault() event.preventDefault()
let attr = event.currentTarget.attributes['data-attack-id']
if ( !attr) {
ui.notifications.warn("Impossible de trouver l'attaque correspondante, erreur de suivi de combat.")
return
}
let attackId = event.currentTarget.attributes['data-attack-id'].value let attackId = event.currentTarget.attributes['data-attack-id'].value
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
let weaponId = (event.currentTarget.attributes['data-weapon-id']) ? event.currentTarget.attributes['data-weapon-id'].value : -1 let weaponId = (event.currentTarget.attributes['data-weapon-id']) ? event.currentTarget.attributes['data-weapon-id'].value : -1
// Remove message for all // Remove message for all
let msgId = BoLUtility.findChatMessageId(event.currentTarget) let msgId = BoLUtility.findChatMessageId(event.currentTarget)
if (game.user.isGM) { if (game.user.isGM) {
@ -280,75 +435,94 @@ export class BoLUtility {
game.socket.emit("system.bol", { name: "msg_damage_handling", data: { msgId: msgId, attackId: attackId, defenseMode: defenseMode, weaponId: weaponId } }) game.socket.emit("system.bol", { name: "msg_damage_handling", data: { msgId: msgId, attackId: attackId, defenseMode: defenseMode, weaponId: weaponId } })
} }
}) })
html.on("click", '.recup-vitalite', event => {
event.preventDefault()
let actorId = event.currentTarget.attributes['data-actor-id'].value
let recupHP = event.currentTarget.attributes['data-recup-hp'].value
let actor = game.actors.get(actorId)
let messageId = BoLUtility.findChatMessageId(event.currentTarget)
BoLUtility.removeChatMessageId(messageId)
actor.applyRecuperation(recupHP)
})
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async processDamageHandling(attackId, defenseMode, weaponId = -1, msgId) { static async processDamageHandling(attackId, defenseMode, weaponId, msgId) {
if (!game.user.isGM) { if (!game.user.isGM) {
return return
} }
BoLUtility.removeChatMessageId( msgId ) let message = game.messages.get(msgId)
let rollData = message.getFlag("world", "bol-roll-data")
BoLUtility.removeChatMessageId(msgId)
console.log("Damage Handling", attackId, defenseMode, weaponId) console.log("Damage Handling", attackId, defenseMode, weaponId)
// Only GM process this // Only GM process this
let attackDef = this.attackStore[attackId] if (rollData?.defenderId) {
if (attackDef && attackDef.defenderId) { if (rollData.defenseDone || defenseMode == 'damage-not-applied') {
if (attackDef.defenseDone) {
return return
} // ?? Why ??? } // ?? Why ???
attackDef.defenseDone = true rollData.defenseDone = true
attackDef.defenseMode = defenseMode rollData.defenseMode = defenseMode
let token = game.scenes.current.tokens.get(attackDef.targetId) let token = game.scenes.current.tokens.get(rollData.targetId)
let defender = token.actor let defender = token.actor
if (defenseMode == 'damage-with-armor') { if (defenseMode == 'damage-with-armor') {
let armorFormula = defender.getArmorFormula() let armorFormula = defender.getArmorFormula()
attackDef.rollArmor = new Roll(armorFormula) rollData.rollArmor = new Roll(armorFormula)
attackDef.rollArmor.roll({ async: false }) await rollData.rollArmor.roll()
attackDef.armorProtect = (attackDef.rollArmor.total < 0) ? 0 : attackDef.rollArmor.total let msg = await rollData.rollArmor.toMessage({ flavor: "BOL.chat.armorRoll : " + armorFormula });
attackDef.finalDamage = attackDef.damageTotal - attackDef.armorProtect if ( game.dice3d) { // wait animation end when DsN is there
attackDef.finalDamage = (attackDef.finalDamage < 0) ? 0 : attackDef.finalDamage await game.dice3d.waitFor3DAnimationByMessageID(msg.id);
defender.sufferDamage(attackDef.finalDamage) }
console.log("Armor roll -> result ", attackDef) rollData.armorProtect = (rollData.rollArmor.total < 0) ? 0 : rollData.rollArmor.total
rollData.finalDamage = rollData.damageTotal - rollData.armorProtect
rollData.finalDamage = (rollData.finalDamage < 0) ? 0 : rollData.finalDamage
await defender.sufferDamage(rollData.finalDamage)
console.log("Armor roll -> result ", rollData)
} }
if (defenseMode == 'damage-without-armor') { if (defenseMode == 'damage-without-armor') {
attackDef.finalDamage = attackDef.damageTotal rollData.finalDamage = rollData.damageTotal
defender.sufferDamage(attackDef.finalDamage) defender.sufferDamage(rollData.finalDamage)
} }
if (defenseMode == 'hero-reduce-damage') { if (defenseMode == 'hero-reduce-damage') {
let armorFormula = defender.getArmorFormula() let armorFormula = defender.getArmorFormula()
attackDef.rollArmor = new Roll(armorFormula) rollData.rollArmor = new Roll(armorFormula)
attackDef.rollArmor.roll({ async: false }) await rollData.rollArmor.roll()
attackDef.armorProtect = (attackDef.rollArmor.total < 0) ? 0 : attackDef.rollArmor.total rollData.armorProtect = (rollData.rollArmor.total < 0) ? 0 : rollData.rollArmor.total
attackDef.rollHero = new Roll("1d6") rollData.rollHero = new Roll("1d6")
attackDef.rollHero.roll({ async: false }) await rollData.rollHero.roll()
attackDef.finalDamage = attackDef.damageTotal - attackDef.rollHero.total - attackDef.armorProtect rollData.finalDamage = rollData.damageTotal - rollData.rollHero.total - rollData.armorProtect
attackDef.finalDamage = (attackDef.finalDamage < 0) ? 0 : attackDef.finalDamage rollData.finalDamage = (rollData.finalDamage < 0) ? 0 : rollData.finalDamage
defender.sufferDamage(attackDef.finalDamage) await defender.sufferDamage(rollData.finalDamage)
defender.subHeroPoints(1) defender.subHeroPoints(1)
} }
if (defenseMode == 'hero-in-extremis') { if (defenseMode == 'hero-in-extremis') {
attackDef.finalDamage = 0; rollData.finalDamage = 0;
attackDef.weaponHero = defender.weapons.find(item => item._id == weaponId); rollData.weaponHero = defender.weapons.find(item => item._id == weaponId);
defender.deleteEmbeddedDocuments("Item", [weaponId]); await defender.deleteEmbeddedDocuments("Item", [weaponId]);
} }
let defenderUser let defenderUser
for (let user of game.users) { for (let user of game.users) {
if ( user.character && user.character.id == defender.id ) { if (user.character && user.character.id == defender.id) {
defenderUser = user defenderUser = user
} }
} }
let damageResults = { let damageResults = {
attackId: attackDef.id, attackId: rollData.id,
attacker: attackDef.attacker, attacker: rollData.attacker,
rollArmor: attackDef.rollArmor, rollArmor: rollData.rollArmor,
rollHero: attackDef.rollHero, rollHero: rollData.rollHero,
weaponHero: attackDef.weaponHero, weaponHero: rollData.weaponHero,
armorProtect: attackDef.armorProtect, armorProtect: rollData.armorProtect,
name: defender.name, name: defender.name,
defender: defender, defender: defender,
defenseMode: attackDef.defenseMode, defenseMode: rollData.defenseMode,
finalDamage: attackDef.finalDamage finalDamage: rollData.finalDamage
} }
ChatMessage.create({ ChatMessage.create({
alias: defender.name, alias: defender.name,
@ -392,7 +566,7 @@ export class BoLUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static isRangedWeapon(weapon) { static isRangedWeapon(weapon) {
return weapon.data.type == 'ranged' || weapon.data.thrown; return weapon.system.type == 'ranged' || weapon.system.thrown;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -435,28 +609,29 @@ export class BoLUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async processAttackSuccess(attackDef) { static async processAttackSuccess(rollData) {
console.log("Attack success processing", attackDef) console.log("Attack success processing", rollData)
if (!game.user.isGM || !attackDef.defenderId) { // Only GM process this if (!game.user.isGM || !rollData.defenderId) { // Only GM process this
return return
} }
// Build and send the defense message to the relevant people (ie GM + defender) // Build and send the defense message to the relevant people (ie GM + defender)
let defender = game.actors.get(attackDef.defenderId) let defender = game.actors.get(rollData.defenderId)
let defenderWeapons = defender.weapons let defenderWeapons = defender.weapons || []
console.log("DEF WEP", attackDef) let msg = await ChatMessage.create({
this.attackStore[attackDef.id] = attackDef // Store !
ChatMessage.create({
alias: defender.name, alias: defender.name,
whisper: BoLUtility.getWhisperRecipientsAndGMs(defender.name), whisper: BoLUtility.getWhisperRecipientsAndGMs(defender.name),
content: await renderTemplate('systems/bol/templates/chat/rolls/defense-request-card.hbs', { content: await renderTemplate('systems/bol/templates/chat/rolls/defense-request-card.hbs', {
attackId: attackDef.id, attackId: rollData.id,
attacker: attackDef.attacker, attacker: rollData.attacker,
defender: defender, defender: defender,
defenderHeroPoints:defender.getHeroPoints(),
defenderWeapons: defenderWeapons, defenderWeapons: defenderWeapons,
damageTotal: attackDef.damageRoll.total, damageTotal: rollData.damageTotal,
damagesIgnoresArmor: attackDef.damagesIgnoresArmor, damagesIgnoresArmor: rollData.damagesIgnoresArmor,
}) })
}) })
msg.setFlag("world", "bol-roll-data", rollData)
console.log("DEF WEP", rollData, defender)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -467,6 +642,9 @@ export class BoLUtility {
if (sockmsg.name == "msg_cleanup_buttons") { if (sockmsg.name == "msg_cleanup_buttons") {
$(`#${sockmsg.data.id}`).hide() // Hide the options roll buttons $(`#${sockmsg.data.id}`).hide() // Hide the options roll buttons
} }
if (sockmsg.name == "msg_request_init_roll") {
this.requestInitRoll(sockmsg.data.actorId, sockmsg.data.combatData)
}
if (sockmsg.name == "msg_damage_handling") { if (sockmsg.name == "msg_damage_handling") {
BoLUtility.processDamageHandling(sockmsg.data.attackId, sockmsg.data.defenseMode, sockmsg.data.weaponId, sockmsg.data.msgId) BoLUtility.processDamageHandling(sockmsg.data.attackId, sockmsg.data.defenseMode, sockmsg.data.weaponId, sockmsg.data.msgId)
} }
@ -474,15 +652,15 @@ export class BoLUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeSpellCost(spell, nbOptCond = 0) { static computeSpellCost(spell, nbOptCond = 0) {
let pp = spell.data.properties.ppcost let pp = spell.system.properties.ppcost
let minpp = __circle2minpp[spell.data.properties.circle] let minpp = __circle2minpp[spell.system.properties.circle]
pp = (pp - nbOptCond < minpp) ? minpp : pp - nbOptCond pp = (pp - nbOptCond < minpp) ? minpp : pp - nbOptCond
return pp return pp
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getDamageFormula(weaponData, fightOption) { static getDamageFormula(weaponData, fightOption) {
let upgradeDamage = (fightOption && fightOption.data.properties.fightoptiontype == "twoweaponsatt") let upgradeDamage = (fightOption && fightOption.system.properties.fightoptiontype == "twoweaponsatt")
let damageString = weaponData.properties.damage let damageString = weaponData.properties.damage
let modifier = weaponData.properties.damageModifiers ?? 0 let modifier = weaponData.properties.damageModifiers ?? 0
let multiplier = weaponData.properties.damageMultiplier ?? 1 let multiplier = weaponData.properties.damageMultiplier ?? 1
@ -494,11 +672,10 @@ export class BoLUtility {
let formula = damageString let formula = damageString
if (damageString.includes("d") || damageString.includes("D")) { if (damageString.includes("d") || damageString.includes("D")) {
var myReg = new RegExp('(\\d+)[dD]([\\d]+)([MB]*)?([\\+\\d]*)?', 'g') let myReg = new RegExp('(\\d+)[dD]([\\d]+)([MB]*)?([\\+\\d]*)?', 'g')
let res = myReg.exec(damageString) let res = myReg.exec(damageString)
let nbDice = parseInt(res[1]) let nbDice = parseInt(res[1])
let postForm = 'kh' + nbDice let postForm = 'kh' + nbDice
let modIndex = 3
// Upgrade damage if needed // Upgrade damage if needed
if (upgradeDamage && (!res[3] || res[3] == "")) { if (upgradeDamage && (!res[3] || res[3] == "")) {
res[3] = "B" // Upgrade to bonus res[3] = "B" // Upgrade to bonus
@ -510,22 +687,18 @@ export class BoLUtility {
if (res[3] == 'M') { if (res[3] == 'M') {
postForm = 'kl' + nbDice postForm = 'kl' + nbDice
nbDice++ nbDice++
modIndex = 4
} }
if (res[3] == 'MM') { if (res[3] == 'MM') {
postForm = 'kl' + nbDice postForm = 'kl' + nbDice
nbDice += 2 nbDice += 2
modIndex = 4
} }
if (res[3] == 'B') { if (res[3] == 'B') {
postForm = 'kh' + nbDice postForm = 'kh' + nbDice
nbDice++ nbDice++
modIndex = 4
} }
if (res[3] == 'BB') { if (res[3] == 'BB') {
postForm = 'kh' + nbDice postForm = 'kh' + nbDice
nbDice += 2 nbDice += 2
modIndex = 4
} }
} }
formula = "(" + nbDice + "d" + res[2] + reroll + postForm + "+" + modifier + ") *" + multiplier formula = "(" + nbDice + "d" + res[2] + reroll + postForm + "+" + modifier + ") *" + multiplier
@ -534,31 +707,53 @@ export class BoLUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async confirmDelete(actorSheet, li) { static async loadCompendiumData(compendium) {
let itemId = li.data("item-id"); const pack = game.packs.get(compendium);
let msgTxt = "<p>Are you sure to remove this Item ?"; return await pack?.getDocuments() ?? [];
let buttons = {
delete: {
icon: '<i class="fas fa-check"></i>',
label: "Yes, remove it",
callback: () => {
actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]);
li.slideUp(200, () => actorSheet.render(false));
}
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel"
}
}
msgTxt += "</p>";
let d = new Dialog({
title: "Confirm removal",
content: msgTxt,
buttons: buttons,
default: "cancel"
});
d.render(true);
} }
/* -------------------------------------------- */
static async loadCompendium(compendium, filter = item => true) {
let compendiumData = await this.loadCompendiumData(compendium);
return compendiumData.filter(filter);
}
/* -------------------------------------------- */
static async searchItem(dataItem) {
let item
if (dataItem.pack) {
let id = dataItem.id || dataItem._id
let items = await this.loadCompendium(dataItem.pack, item => item.id == id)
item = items[0] || undefined
} else {
item = game.items.get(dataItem.id)
}
return item
}
/* -------------------------------------------- */
static updateSheets() {
// Then force opened actor refresh if needed
for (let actor of game.actors) {
if (actor.sheet.rendered) {
actor.sheet.render()
}
}
game.bol.charSummary.updatePCSummary() // Refresh if needed
}
/* -------------------------------------------- */
static removeGroupHoroscope(rollData) {
let horo = rollData.horoscopeGroupList[rollData.selectedGroupHoroscopeIndex]
let horoscopes = foundry.utils.duplicate(game.settings.get("bol", "horoscope-group"))
let toChange = foundry.utils.duplicate(horoscopes[horo.id])
toChange.availableDice -= horo.nbDice // Remove the dice
if (toChange.availableDice <= 0) {
horoscopes[horo.id] = undefined
} else {
horoscopes[horo.id] = toChange
}
game.settings.set("bol", "horoscope-group", horoscopes)
this.updateSheets()
}
} }

View File

@ -10,14 +10,15 @@ System.debugMode = true;
export const BOL = {}; export const BOL = {};
BOL.damageValues = { BOL.damageValues = {
"1": "1", "0": "0",
"2": "2", "1": "1",
"3": "3", "2": "2",
"d3" : "d3", "3": "3",
"d6M" : "d6M (Malus)", "d3": "d3",
"d6" : "d6", "d6M": "d6M (Malus)",
"d6B" : "d6B (Bonus)", "d6": "d6",
"d6BB" : "d6B + dé bonus", "d6B": "d6B (Bonus)",
"d6BB": "d6B + dé bonus",
} }
BOL.damageMultiplier = { BOL.damageMultiplier = {
@ -25,6 +26,19 @@ BOL.damageMultiplier = {
"2": "x2", "2": "x2",
"3": "x3", "3": "x3",
"4": "x4", "4": "x4",
"5": "x5",
"6": "x6",
"7": "7",
"8": "x8"
}
BOL.listTypes = {
"attribute": "BOL.ui.attribute",
"aptitude": "BOL.ui.aptitude",
"career": "BOL.ui.career",
"boon": "BOL.ui.boon",
"flaw": "BOL.ui.flaw",
"other": "BOL.ui.other"
} }
BOL.spellType = { BOL.spellType = {
@ -42,116 +56,125 @@ BOL.alchemyType = {
} }
BOL.equipmentSlots = { BOL.equipmentSlots = {
"none" : "BOL.equipmentSlots.none", "none": "BOL.equipmentSlots.none",
"head" : "BOL.equipmentSlots.head", "head": "BOL.equipmentSlots.head",
"neck" : "BOL.equipmentSlots.neck", "neck": "BOL.equipmentSlots.neck",
"shoulders" : "BOL.equipmentSlots.shoulders", "shoulders": "BOL.equipmentSlots.shoulders",
"body" : "BOL.equipmentSlots.body", "body": "BOL.equipmentSlots.body",
"rhand" : "BOL.equipmentSlots.rhand", "rhand": "BOL.equipmentSlots.rhand",
"lhand" : "BOL.equipmentSlots.lhand", "lhand": "BOL.equipmentSlots.lhand",
"2hands" : "BOL.equipmentSlots.2hands", "2hands": "BOL.equipmentSlots.2hands",
"rarm" : "BOL.equipmentSlots.rarm", "rarm": "BOL.equipmentSlots.rarm",
"larm" : "BOL.equipmentSlots.larm", "larm": "BOL.equipmentSlots.larm",
"chest" : "BOL.equipmentSlots.chest", "chest": "BOL.equipmentSlots.chest",
"belt" : "BOL.equipmentSlots.belt", "belt": "BOL.equipmentSlots.belt",
"legs" : "BOL.equipmentSlots.legs", "legs": "BOL.equipmentSlots.legs",
"feet" : "BOL.equipmentSlots.feet", "feet": "BOL.equipmentSlots.feet",
"finder" : "BOL.equipmentSlots.finder", "finder": "BOL.equipmentSlots.finder",
"ear" : "BOL.equipmentSlots.ear" "ear": "BOL.equipmentSlots.ear"
} }
BOL.armorQualities = { BOL.armorQualities = {
"none" : "BOL.armorQuality.none", "none": "BOL.armorQuality.none",
"light" : "BOL.armorQuality.light", "light": "BOL.armorQuality.light",
"lightQ" : "BOL.armorQuality.lightQ", "lightQ": "BOL.armorQuality.lightQ",
"lightSup" : "BOL.armorQuality.lightSup", "lightSup": "BOL.armorQuality.lightSup",
"lightLeg" : "BOL.armorQuality.lightLeg", "lightLeg": "BOL.armorQuality.lightLeg",
"medium" : "BOL.armorQuality.medium", "medium": "BOL.armorQuality.medium",
"mediumQ" : "BOL.armorQuality.mediumQ", "mediumQ": "BOL.armorQuality.mediumQ",
"mediumSup" : "BOL.armorQuality.mediumSup", "mediumSup": "BOL.armorQuality.mediumSup",
"mediumLeg" : "BOL.armorQuality.mediumLeg", "mediumLeg": "BOL.armorQuality.mediumLeg",
"heavy" : "BOL.armorQuality.heavy", "heavy": "BOL.armorQuality.heavy",
"heavyQ" : "BOL.armorQuality.heavyQ", "heavyQ": "BOL.armorQuality.heavyQ",
"heavySup" : "BOL.armorQuality.heavySup", "heavySup": "BOL.armorQuality.heavySup",
"heavyLeg" : "BOL.armorQuality.heavyLeg" "heavyLeg": "BOL.armorQuality.heavyLeg"
} }
BOL.soakFormulas = { BOL.soakFormulas = {
"none" : "0", "none": "0",
"light" : "1d6-3", "light": "1d6-3",
"lightQ" : "1d6r1-3", "lightQ": "1d6r1-3",
"lightSup" : "1d6-2", "lightSup": "1d6-2",
"lightLeg" : "2d6kh1-2", "lightLeg": "2d6kh1-2",
"medium" : "1d6-2", "medium": "1d6-2",
"mediumQ" : "1d6r1-2", "mediumQ": "1d6r1-2",
"mediumSup" : "1d6-1", "mediumSup": "1d6-1",
"mediumLeg" : "2d6kh1-1", "mediumLeg": "2d6kh1-1",
"heavy" : "1d6-1", "heavy": "1d6-1",
"heavyQ" : "1d6r1-1", "heavyQ": "1d6r1-1",
"heavySup" : "1d6", "heavySup": "1d6",
"heavyLeg" : "2d6kh1" "heavyLeg": "2d6kh1"
} }
BOL.attackAttributes = { BOL.attackAttributes = {
"vigor" : "BOL.attributes.vigor", "vigor": "BOL.attributes.vigor",
"agility" : "BOL.attributes.agility", "agility": "BOL.attributes.agility",
"mind" : "BOL.attributes.mind", "mind": "BOL.attributes.mind",
"appeal" : "BOL.attributes.appeal" "appeal": "BOL.attributes.appeal"
} }
BOL.attackAptitudes = { BOL.attackAptitudes = {
"melee" : "BOL.aptitudes.melee", "melee": "BOL.aptitudes.melee",
"ranged" : "BOL.aptitudes.ranged" "ranged": "BOL.aptitudes.ranged"
} }
BOL.aptitudes = { BOL.aptitudes = {
"melee" : "BOL.aptitudes.melee", "melee": "BOL.aptitudes.melee",
"ranged" : "BOL.aptitudes.ranged", "ranged": "BOL.aptitudes.ranged",
"init" : "BOL.aptitudes.init", "init": "BOL.aptitudes.init",
"def" : "BOL.aptitudes.def" "def": "BOL.aptitudes.def"
}
BOL.resources = {
"hp": "BOL.resources.hp",
"hero": "BOL.resources.hero",
"faith": "BOL.resources.faith",
"power": "BOL.resources.power",
"alchemypoints": "BOL.resources.alchemypoints"
} }
BOL.weaponSizes = { BOL.weaponSizes = {
"unarmed" : "BOL.weaponSize.unarmed", "unarmed": "BOL.weaponSize.unarmed",
"improvised" : "BOL.weaponSize.improvised", "improvised": "BOL.weaponSize.improvised",
"light" : "BOL.weaponSize.light", "light": "BOL.weaponSize.light",
"medium" : "BOL.weaponSize.medium", "medium": "BOL.weaponSize.medium",
"heavy" : "BOL.weaponSize.heavy" "heavy": "BOL.weaponSize.heavy"
} }
BOL.damageAttributes = { BOL.damageAttributes = {
"zero" : "0", "zero": "0",
"vigor" : "BOL.attributes.vigor", "vigor": "BOL.attributes.vigor",
"half-vigor" : "BOL.attributes.halfvigor" "half-vigor": "BOL.attributes.halfvigor"
} }
BOL.itemCategories = { BOL.itemCategories = {
"equipment" : "BOL.itemCategory.equipment", "equipment": "BOL.itemCategory.equipment",
"capacity" : "BOL.itemCategory.capacity", "capacity": "BOL.itemCategory.capacity",
"spell" : "BOL.itemCategory.spell", "spell": "BOL.itemCategory.spell",
"alchemy" : "BOL.itemCategory.alchemy", "alchemy": "BOL.itemCategory.alchemy",
"vehicle" : "BOL.itemCategory.vehicle", "vehicle": "BOL.itemCategory.vehicle",
"other" : "BOL.itemCategory.other" "vehicleweapon": "BOL.itemCategory.vehicleweapon",
"other": "BOL.itemCategory.other"
} }
BOL.itemSubtypes = { BOL.itemSubtypes = {
"armor" : "BOL.equipmentCategory.armor", "armor": "BOL.equipmentCategory.armor",
"weapon" : "BOL.equipmentCategory.weapon", "weapon": "BOL.equipmentCategory.weapon",
"shield" : "BOL.equipmentCategory.shield", "shield": "BOL.equipmentCategory.shield",
"helm" : "BOL.equipmentCategory.helm", "helm": "BOL.equipmentCategory.helm",
"jewel" : "BOL.equipmentCategory.jewel", "jewel": "BOL.equipmentCategory.jewel",
"scroll" : "BOL.equipmentCategory.scroll", "scroll": "BOL.equipmentCategory.scroll",
"container" : "BOL.equipmentCategory.container", "container": "BOL.equipmentCategory.container",
"ammunition" : "BOL.equipmentCategory.ammunition", "ammunition": "BOL.equipmentCategory.ammunition",
"currency" : "BOL.equipmentCategory.currency", "currency": "BOL.equipmentCategory.currency",
"other" : "BOL.equipmentCategory.other" "other": "BOL.equipmentCategory.other"
} }
BOL.vehicleSubtypes = { BOL.vehicleSubtypes = {
"mount" : "BOL.vehicleCategory.mount", "mount": "BOL.vehicleCategory.mount",
"flying" : "BOL.vehicleCategory.flying", "flying": "BOL.vehicleCategory.flying",
"boat" : "BOL.vehicleCategory.boat", "boat": "BOL.vehicleCategory.boat",
"other" : "BOL.vehicleCategory.other" "other": "BOL.vehicleCategory.other"
} }
// BOL.equipmentCategories = { // BOL.equipmentCategories = {
@ -167,95 +190,153 @@ BOL.vehicleSubtypes = {
// "other" : "BOL.equipmentCategory.other" // "other" : "BOL.equipmentCategory.other"
// } // }
BOL.rangeModifiers = {
"1": "BOL.dialog.pointblank",
"0": "BOL.dialog.close",
"-1": "BOL.dialog.medium",
"-2": "BOL.dialog.long",
"-4": "BOL.dialog.distant",
"-6": "BOL.dialog.extreme",
"-8": "BOL.dialog.utmost"
}
BOL.difficultyModifiers = {
"4": "BOL.dialog.soeasy",
"2": "BOL.dialog.veryeasy",
"1": "BOL.dialog.easy",
"0": "BOL.dialog.moderate",
"-1": "BOL.dialog.hard",
"-2": "BOL.dialog.tough",
"-4": "BOL.dialog.demanding",
"-6": "BOL.dialog.formidable",
"-8": "BOL.dialog.heroic",
"-10": "BOL.dialog.mythic",
"-12": "BOL.dialog.divine"
}
BOL.alchemyModifiers = {
"2": "BOL.dialog.veryeasy",
"1": "BOL.dialog.easy",
"0": "BOL.dialog.moderate",
"-1": "BOL.dialog.hard",
"-2": "BOL.dialog.tough",
"-4": "BOL.dialog.demanding",
"-6": "BOL.dialog.formidable",
"-8": "BOL.dialog.heroic",
}
BOL.spellModifiers = BOL.alchemyModifiers
BOL.spellMandatoryConditions = {
"1": "1",
"2": "2",
"3": "3",
"4": "4"
}
BOL.spellOptionnalConditions = {
"1": "1",
"2": "2",
"3": "3",
"4": "4",
"5": "5",
"6": "6",
"7": "7",
"8": "8"
}
BOL.effectIdentifiers = {
"always": "BOL.ui.always",
}
BOL.protectionCategories = { BOL.protectionCategories = {
"armor" : "BOL.protectionCategory.armor", "armor": "BOL.protectionCategory.armor",
"shield" : "BOL.protectionCategory.shield", "shield": "BOL.protectionCategory.shield",
"helm" : "BOL.protectionCategory.helm", "helm": "BOL.protectionCategory.helm",
"other" : "BOL.protectionCategory.other" "other": "BOL.protectionCategory.other"
} }
BOL.weaponCategories = { BOL.weaponCategories = {
"melee" : "BOL.weaponCategory.melee", "melee": "BOL.weaponCategory.melee",
"ranged" : "BOL.weaponCategory.ranged", "ranged": "BOL.weaponCategory.ranged",
"other" : "BOL.weaponCategory.other" "other": "BOL.weaponCategory.other"
} }
BOL.itemProperties1 = { BOL.itemProperties1 = {
"equipable" : "BOL.itemProperty.equipable", "equipable": "BOL.itemProperty.equipable",
"protection" : "BOL.itemProperty.protection", "protection": "BOL.itemProperty.protection",
"magical" : "BOL.itemProperty.magical", "magical": "BOL.itemProperty.magical",
"worn" : "BOL.itemProperty.worn", "worn": "BOL.itemProperty.worn",
} }
BOL.itemProperties2 = { BOL.itemProperties2 = {
"equipable" : "BOL.itemProperty.equipable", "equipable": "BOL.itemProperty.equipable",
"protection" : "BOL.itemProperty.protection", "protection": "BOL.itemProperty.protection",
"blocking" : "BOL.itemProperty.blocking", "blocking": "BOL.itemProperty.blocking",
"magical" : "BOL.itemProperty.magical", "magical": "BOL.itemProperty.magical",
"concealable" : "BOL.itemProperty.concealable", "concealable": "BOL.itemProperty.concealable",
"2H" : "BOL.itemProperty.2H", "2H": "BOL.itemProperty.2H",
"helm" : "BOL.itemProperty.helm", "helm": "BOL.itemProperty.helm",
"improvised" : "BOL.itemProperty.improvised", "improvised": "BOL.itemProperty.improvised",
"shield" : "BOL.itemProperty.shield", "shield": "BOL.itemProperty.shield",
"melee" : "BOL.itemProperty.melee", "melee": "BOL.itemProperty.melee",
"throwable" : "BOL.itemProperty.throwable", "throwable": "BOL.itemProperty.throwable",
"ignoreshield" : "BOL.itemProperty.ignoreshield", "ignoreshield": "BOL.itemProperty.ignoreshield",
"bashing" : "BOL.itemProperty.bashing", "bashing": "BOL.itemProperty.bashing",
"stackable" : "BOL.itemProperty.stackable", "stackable": "BOL.itemProperty.stackable",
"ranged" : "BOL.itemProperty.ranged", "ranged": "BOL.itemProperty.ranged",
"weapon" : "BOL.itemProperty.weapon", "weapon": "BOL.itemProperty.weapon",
"reloadable" : "BOL.itemProperty.reloadable", "reloadable": "BOL.itemProperty.reloadable",
"worn" : "BOL.itemProperty.worn", "worn": "BOL.itemProperty.worn",
"spell" : "BOL.itemProperty.spell", "spell": "BOL.itemProperty.spell",
"armor" : "BOL.itemProperty.armor", "armor": "BOL.itemProperty.armor",
"consumable" : "BOL.itemProperty.consumable", "consumable": "BOL.itemProperty.consumable",
"bow" : "BOL.itemProperty.bow", "bow": "BOL.itemProperty.bow",
"crossbow" : "BOL.itemProperty.crossbow", "crossbow": "BOL.itemProperty.crossbow",
"throwing" : "BOL.itemProperty.throwing", "throwing": "BOL.itemProperty.throwing",
"activable" : "BOL.itemProperty.activable", "activable": "BOL.itemProperty.activable",
"powder" : "BOL.itemProperty.powder", "powder": "BOL.itemProperty.powder",
"damage" : "BOL.itemProperty.damage", "damage": "BOL.itemProperty.damage",
"difficulty": "BOL.itemProperty.difficulty" "difficulty": "BOL.itemProperty.difficulty"
} }
BOL.itemStats = { BOL.itemStats = {
"quantity" : "BOL.itemStat.quantity", "quantity": "BOL.itemStat.quantity",
"weight" : "BOL.itemStat.weight", "weight": "BOL.itemStat.weight",
"price" : "BOL.itemStat.price", "price": "BOL.itemStat.price",
"range" : "BOL.itemStat.range", "range": "BOL.itemStat.range",
"damage" : "BOL.itemStat.damage", "damage": "BOL.itemStat.damage",
"reload" : "BOL.itemStat.reload", "reload": "BOL.itemStat.reload",
"soak" : "BOL.itemStat.soak", "soak": "BOL.itemStat.soak",
"blocking" : "BOL.itemStat.blocking", "blocking": "BOL.itemStat.blocking",
"modifiers" : "BOL.itemStat.modifiers" "modifiers": "BOL.itemStat.modifiers"
} }
BOL.itemModifiers = { BOL.itemModifiers = {
"init" : "BOL.itemModifiers.init", "init": "BOL.itemModifiers.init",
"social" : "BOL.itemModifiers.social", "social": "BOL.itemModifiers.social",
"agility" : "BOL.itemModifiers.agility", "agility": "BOL.itemModifiers.agility",
"powercost" : "BOL.itemModifiers.powercost" "powercost": "BOL.itemModifiers.powercost"
} }
BOL.itemBlocking = { BOL.itemBlocking = {
"malus" : "BOL.itemBlocking.malus", "malus": "BOL.itemBlocking.malus",
"nbAttacksPerRound" : "BOL.itemBlocking.nbAttacksPerRound" "nbAttacksPerRound": "BOL.itemBlocking.nbAttacksPerRound"
} }
BOL.itemSoak = { BOL.itemSoak = {
"formula" : "BOL.itemSoak.formula", "formula": "BOL.itemSoak.formula",
"value" : "BOL.itemSoak.value" "value": "BOL.itemSoak.value"
} }
BOL.featureSubtypes = { BOL.featureSubtypes = {
"origin" : "BOL.featureSubtypes.origin", "origin": "BOL.featureSubtypes.origin",
"race" : "BOL.featureSubtypes.race", "race": "BOL.featureSubtypes.race",
"career" : "BOL.featureSubtypes.career", "career": "BOL.featureSubtypes.career",
"boon" : "BOL.featureSubtypes.boon", "boon": "BOL.featureSubtypes.boon",
"flaw" : "BOL.featureSubtypes.flaw", "flaw": "BOL.featureSubtypes.flaw",
"language" : "BOL.featureSubtypes.language", "language": "BOL.featureSubtypes.language",
"godsfaith" : "BOL.featureSubtypes.gods", "godsfaith": "BOL.featureSubtypes.gods",
"fightoption" : "BOL.featureSubtypes.fightOption" "fightoption": "BOL.featureSubtypes.fightOption",
"boleffect": "BOL.featureSubtypes.effect",
"horoscope": "BOL.featureSubtypes.horoscope",
"xplog": "BOL.featureSubtypes.xplog",
} }
BOL.fightOptionTypes = { BOL.fightOptionTypes = {
@ -266,43 +347,322 @@ BOL.fightOptionTypes = {
"fulldefense": "BOL.fightOptionTypes.fulldefense", "fulldefense": "BOL.fightOptionTypes.fulldefense",
"defense": "BOL.fightOptionTypes.defense", "defense": "BOL.fightOptionTypes.defense",
"attack": "BOL.fightOptionTypes.attack", "attack": "BOL.fightOptionTypes.attack",
"other": "BOL.fightOptionTypes.other"
} }
BOL.itemIcons = { BOL.itemIcons = {
"item": "icons/containers/chest/chest-worn-oak-tan.webp", "item": "icons/containers/chest/chest-worn-oak-tan.webp",
"capacity": "icons/sundries/scrolls/scroll-plain-tan-red.webp", "feature": "icons/sundries/scrolls/scroll-plain-tan-red.webp",
"species": "icons/environment/people/group.webp", "species": "icons/environment/people/group.webp",
"profile": "icons/sundries/documents/blueprint-axe.webp", "profile": "icons/sundries/documents/blueprint-axe.webp",
"path": "icons/sundries/books/book-embossed-gold-red.webp" "path": "icons/sundries/books/book-embossed-gold-red.webp"
} }
BOL.actorIcons = { BOL.actorIcons = {
"npc": "icons/environment/people/commoner.webp", "npc": "icons/environment/people/commoner.webp",
"encounter": "icons/svg/mystery-man-black.svg", "encounter": "icons/svg/mystery-man-black.svg",
"loot": "icons/containers/bags/sack-simple-leather-brown.webp" "loot": "icons/containers/bags/sack-simple-leather-brown.webp"
} }
BOL.bougetteState = { BOL.bougetteState = {
"nomoney": "BOL.bougette.nomoney", "0": "BOL.bougette.nomoney",
"tolive": "BOL.bougette.tolive", "1": "BOL.bougette.tolive",
"easylife": "BOL.bougette.easylife", "2": "BOL.bougette.easylife",
"luxury": "BOL.bougette.luxury", "3": "BOL.bougette.luxury",
"rich": "BOL.bougette.rich" "4": "BOL.bougette.rich"
}
BOL.bougetteDice = {
"0": "0",
"1": "2d6-1",
"2": "2d6",
"3": "2d6+1",
"4": "2d6+2"
} }
BOL.creatureSize = { BOL.creatureSize = {
"tiny": "BOL.size.tiny", "tiny": { order: 1, label: "BOL.size.tiny" },
"verysmall": "BOL.size.verysmall", "verysmall": { order: 2, label: "BOL.size.verysmall" },
"small": "BOL.size.small", "small": { order: 3, label: "BOL.size.small" },
"medium": "BOL.size.medium", "medium": { order: 4, label: "BOL.size.medium" },
"large": "BOL.size.large", "large": { order: 5, label: "BOL.size.large" },
"verylarge": "BOL.size.verylarge", "verylarge": { order: 6, label: "BOL.size.verylarge" },
"huge": "BOL.size.huge", "huge": { order: 7, label: "BOL.size.huge" },
"massive": "BOL.size.massive", "massive": { order: 8, label: "BOL.size.massive" },
"enormous": "BOL.size.enormous", "enormous": { order: 9, label: "BOL.size.enormous" },
"gigantic": "BOL.size.gigantic", "gigantic": { order: 10, label: "BOL.size.gigantic" },
"immense": "BOL.size.immense", "immense": { order: 11, label: "BOL.size.immense" },
"colossal": "BOL.size.colossal" "colossal": { order: 12, label: "BOL.size.colossal" }
}
BOL.horoscopeAnswer = {
"favorable": "BOL.ui.horoscopefavorable",
"unfavorable": "BOL.ui.horoscopeunfavorable",
}
BOL.bolEffectModifier = {
"-8": "-8",
"-6": "-6",
"-4": "-4",
"-2": "-2",
"-1": "-1",
"1B": "1B",
"2B": "2B",
"1M": "1M",
"2M": "2M",
"+1": "+1",
"+2": "+2",
"+4": "+4",
"+6": "+6",
"+8": "+8",
}
BOL.statusEffects = [
{
"id": "dead",
"label": "EFFECT.StatusDead",
"icon": "icons/svg/skull.svg"
},
{
"id": "unconscious",
"label": "EFFECT.StatusUnconscious",
"icon": "icons/svg/unconscious.svg"
},
{
"id": "sleep",
"label": "EFFECT.StatusAsleep",
"icon": "icons/svg/sleep.svg"
},
{
"id": "stun",
"label": "EFFECT.StatusStunned",
"icon": "icons/svg/daze.svg"
},
{
"id": "prone",
"label": "EFFECT.StatusProne",
"icon": "icons/svg/falling.svg"
},
{
"id": "restrain",
"label": "EFFECT.StatusRestrained",
"icon": "icons/svg/net.svg"
},
{
"id": "paralysis",
"label": "EFFECT.StatusParalysis",
"icon": "icons/svg/paralysis.svg"
},
{
"id": "fly",
"label": "EFFECT.StatusFlying",
"icon": "icons/svg/wing.svg"
},
{
"id": "blind",
"label": "EFFECT.StatusBlind",
"icon": "icons/svg/blind.svg"
},
{
"id": "deaf",
"label": "EFFECT.StatusDeaf",
"icon": "icons/svg/deaf.svg"
},
{
"id": "silence",
"label": "EFFECT.StatusSilenced",
"icon": "icons/svg/silenced.svg"
},
{
"id": "fear",
"label": "EFFECT.StatusFear",
"icon": "icons/svg/terror.svg"
},
{
"id": "burning",
"label": "EFFECT.StatusBurning",
"icon": "icons/svg/fire.svg"
},
{
"id": "frozen",
"label": "EFFECT.StatusFrozen",
"icon": "icons/svg/frozen.svg"
},
{
"id": "shock",
"label": "EFFECT.StatusShocked",
"icon": "icons/svg/lightning.svg"
},
{
"id": "disease",
"label": "EFFECT.StatusDisease",
"icon": "icons/svg/biohazard.svg"
},
{
"id": "poison",
"label": "EFFECT.StatusPoison",
"icon": "icons/svg/poison.svg"
},
{
"id": "curse",
"label": "EFFECT.StatusCursed",
"icon": "icons/svg/sun.svg"
},
{
"id": "invisible",
"label": "EFFECT.StatusInvisible",
"icon": "icons/svg/invisible.svg"
},
{
"id": "target",
"label": "EFFECT.StatusTarget",
"icon": "icons/svg/target.svg"
},
{
"id": "eye",
"label": "EFFECT.StatusMarked",
"icon": "icons/svg/eye.svg"
}
]
BOL.defaultNaturalWeapon = {
"category": "equipment",
"subtype": "weapon",
"description": "",
"properties": {
"ranged": false,
"melee": false,
"spell": false,
"protection": false,
"weapon": true,
"armor": false,
"helm": false,
"shield": false,
"equipable": false,
"consumable": false,
"magical": false,
"2H": false,
"reloadable": false,
"bow": false,
"crossbow": false,
"throwing": false,
"stackable": false,
"natural": true,
"concealable": false,
"ignoreshield": false,
"attackBonusDice": false,
"onlymodifier": true,
"attackAttribute": "vigor",
"attackAptitude": "melee",
"attackModifiers": 1,
"weaponSize": "unarmed",
"damage": "d6B",
"damageAttribute": "",
"damageModifiers": null,
"damageMultiplier": "1",
"damageReroll1": false
},
"quantity": 1,
"weight": 0,
"price": 0,
"worn": false
}
BOL.defaultHordeAttack = {
"category": "equipment",
"subtype": "weapon",
"description": "",
"properties": {
"ranged": false,
"melee": true,
"spell": false,
"protection": false,
"weapon": true,
"armor": false,
"helm": false,
"shield": false,
"equipable": false,
"consumable": false,
"magical": false,
"2H": false,
"reloadable": false,
"bow": false,
"crossbow": false,
"throwing": false,
"stackable": false,
"natural": true,
"concealable": false,
"ignoreshield": false,
"attackBonusDice": false,
"onlymodifier": true,
"attackAttribute": "vigor",
"attackAptitude": "melee",
"attackModifiers": 1,
"weaponSize": "unarmed",
"damage": "d6M",
"damageAttribute": "",
"damageModifiers": null,
"damageMultiplier": "1",
"damageReroll1": false
},
"quantity": 1,
"weight": 0,
"price": 0,
"worn": false
}
BOL.defaultNaturalProtection = {
"category": "equipment",
"subtype": "armor",
"description": "",
"properties": {
"ranged": false,
"melee": false,
"spell": false,
"protection": true,
"weapon": false,
"armor": true,
"helm": false,
"shield": false,
"equipable": true,
"consumable": false,
"magical": false,
"2H": false,
"reloadable": false,
"bow": false,
"crossbow": false,
"throwing": false,
"stackable": false,
"natural": true,
"concealable": false,
"ignoreshield": false,
"attackBonusDice": false,
"onlymodifier": true,
"attackAttribute": "vigor",
"attackAptitude": "melee",
"attackModifiers": 1,
"weaponSize": "unarmed",
"damage": "d6B",
"damageAttribute": "vigor",
"damageModifiers": null,
"damageMultiplier": "1",
"damageReroll1": false,
"modifiers": {
"init": null,
"agility": null,
"powercost": null,
"social": false
},
"armorQuality": "none",
"soak": {
"formula": "",
"value": 1
},
"slot": "none"
},
"quantity": 1,
"weight": 0,
"price": 0,
"worn": true
} }
BOL.debug = false; BOL.debug = false;

View File

@ -10,7 +10,7 @@ export const registerHandlebarsHelpers = function () {
Handlebars.registerHelper('isEmpty', function (list) { Handlebars.registerHelper('isEmpty', function (list) {
if (list) return list.length == 0; if (list) return list.length == 0;
else return 0; else return false;
}); });
Handlebars.registerHelper('notEmpty', function (list) { Handlebars.registerHelper('notEmpty', function (list) {
@ -64,8 +64,8 @@ export const registerHandlebarsHelpers = function () {
}) })
Handlebars.registerHelper('for', function (from, to, incr, block) { Handlebars.registerHelper('for', function (from, to, incr, block) {
var accum = ''; let accum = '';
for (var i = from; i < to; i += incr) for (let i = from; i < to; i += incr)
accum += block.fn(i); accum += block.fn(i);
return accum; return accum;
}) })
@ -76,6 +76,10 @@ export const registerHandlebarsHelpers = function () {
Handlebars.registerHelper('count', function (list) { Handlebars.registerHelper('count', function (list) {
return list.length; return list.length;
}) })
Handlebars.registerHelper('countKeys', function (obj) {
return Object.keys(obj).length;
})
Handlebars.registerHelper('isEnabled', function (configKey) { Handlebars.registerHelper('isEnabled', function (configKey) {
return game.settings.get("bol", configKey); return game.settings.get("bol", configKey);
}) })
@ -85,8 +89,8 @@ export const registerHandlebarsHelpers = function () {
// If you need to add Handlebars helpers, here are a few useful examples: // If you need to add Handlebars helpers, here are a few useful examples:
Handlebars.registerHelper('concat', function () { Handlebars.registerHelper('concat', function () {
var outStr = ''; let outStr = '';
for (var arg in arguments) { for (let arg in arguments) {
if (typeof arguments[arg] != 'object') { if (typeof arguments[arg] != 'object') {
outStr += arguments[arg]; outStr += arguments[arg];
} }
@ -103,12 +107,17 @@ export const registerHandlebarsHelpers = function () {
Handlebars.registerHelper('sub', function (a, b) { Handlebars.registerHelper('sub', function (a, b) {
return parseInt(a) - parseInt(b); return parseInt(a) - parseInt(b);
}) })
Handlebars.registerHelper('abbrev2', function (a) {
return a.substring(0, 2);
})
Handlebars.registerHelper('abbrev3', function (a) {
return a.substring(0, 3);
})
Handlebars.registerHelper('valueAtIndex', function (arr, idx) { Handlebars.registerHelper('valueAtIndex', function (arr, idx) {
return arr[idx]; return arr[idx];
}) })
Handlebars.registerHelper('includesKey', function (items, type, key) { Handlebars.registerHelper('includesKey', function (items, type, key) {
// console.log(items); return items.filter(i => i.type === type).map(i => i.system.key).includes(key);
return items.filter(i => i.type === type).map(i => i.data.key).includes(key);
}) })
Handlebars.registerHelper('includes', function (array, val) { Handlebars.registerHelper('includes', function (array, val) {
return array.includes(val); return array.includes(val);
@ -118,12 +127,26 @@ export const registerHandlebarsHelpers = function () {
}) })
Handlebars.registerHelper('isOwnerOrGM', function (actor) { Handlebars.registerHelper('isOwnerOrGM', function (actor) {
console.log("Testing actor", actor.isOwner, game.userId) console.log("Testing actor", actor.isOwner, game.userId)
if (actor.isOwner || game.isGM) { return actor.isOwner || game.isGM;
return true })
} Handlebars.registerHelper('upperFirst', function (text) {
return false if (typeof text !== 'string') return text
return text.charAt(0).toUpperCase() + text.slice(1)
})
Handlebars.registerHelper('upperFirstOnly', function (text) {
if (typeof text !== 'string') return text
return text.charAt(0).toUpperCase()
})
Handlebars.registerHelper('isCreature', function (key) {
return key == "creature" || key == "daemon";
}) })
// Handle v12 removal of this helper
Handlebars.registerHelper('select', function (selected, options) {
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
const rgx = new RegExp(' value=[\"\']' + escapedValue + '[\"\']');
const html = options.fn(this);
return html.replace(rgx, "$& selected");
});
} }

View File

@ -29,18 +29,6 @@ export default function registerHooks() {
if (data.type == "Item") { if (data.type == "Item") {
let item = data.data; let item = data.data;
console.log(item); console.log(item);
// let command = `let onlyDamage = false;\nlet customLabel = "";\nlet skillDescription = "";\nlet dmgDescription = "";\n\nif (event) {\n if (event.shiftKey) onlyDamage = true;\n}\n\ngame.cof.macros.rollItemMacro("${item._id}", "${item.name}", "${item.type}", 0, 0, 0, onlyDamage, customLabel, skillDescription, dmgDescription);`;
// let macro = game.macros.entities.find(m => (m.name === item.name) && (m.command === command));
// if (!macro) {
// macro = await Macro.create({
// name: item.name,
// type : "script",
// img: item.img,
// command : command
// }, {displaySheet: false})
// }
// game.user.assignHotbarMacro(macro, slot);
} }
// Create a macro to open the actor sheet of the actor dropped on the hotbar // Create a macro to open the actor sheet of the actor dropped on the hotbar
else if (data.type == "Actor") { else if (data.type == "Actor") {
@ -49,7 +37,7 @@ export default function registerHooks() {
let macro = game.macros.entities.find(m => (m.name === actor.name) && (m.command === command)); let macro = game.macros.entities.find(m => (m.name === actor.name) && (m.command === command));
if (!macro) { if (!macro) {
macro = await Macro.create({ macro = await Macro.create({
name: actor.data.name, name: actor.name,
type: "script", type: "script",
img: "icons/svg/dice-target.svg", img: "icons/svg/dice-target.svg",
command: command command: command
@ -65,9 +53,9 @@ export default function registerHooks() {
let macro = game.macros.entities.find(m => (m.name === journal.name) && (m.command === command)); let macro = game.macros.entities.find(m => (m.name === journal.name) && (m.command === command));
if (!macro) { if (!macro) {
macro = await Macro.create({ macro = await Macro.create({
name: journal.data.name, name: journal.name,
type: "script", type: "script",
img: (journal.data.img) ? journal.data.img : "icons/svg/book.svg", img: (journal.img) ? journal.img : "icons/svg/book.svg",
command: command command: command
}, {displaySheet: false}) }, {displaySheet: false})
game.user.assignHotbarMacro(macro, slot); game.user.assignHotbarMacro(macro, slot);
@ -75,4 +63,18 @@ export default function registerHooks() {
} }
return false; return false;
}); });
/********************************************************************************** */
Hooks.on("renderActorDirectory", (app, html, data) => {
if (game.user.isGM) {
const button = document.createElement('button');
button.style.width = '95%';
button.innerHTML = game.i18n.localize("BOL.ui.pclistbutton")
button.addEventListener('click', () => {
game.bol.charSummary.render(true)
})
html.find('.header-actions').after(button)
}
})
} }

View File

@ -37,13 +37,13 @@ export class Macros {
}; };
if(rollType === "attribute") { if(rollType === "attribute") {
let attribute = eval(`actor.data.data.attributes.${key}`); let attribute = eval(`actor.system.attributes.${key}`);
let rollLabel = (attribute.label) ? game.i18n.localize(attribute.label) : null; let rollLabel = (attribute.label) ? game.i18n.localize(attribute.label) : null;
let description = actor.name + " - " + game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label) ; let description = actor.name + " - " + game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label) ;
BoLRoll.attributeRollDialog(actor, actorData, attribute, rollLabel, description, adv, mod); BoLRoll.attributeRollDialog(actor, actorData, attribute, rollLabel, description, adv, mod);
} }
else if(rollType === "aptitude") { else if(rollType === "aptitude") {
let aptitude = eval(`actor.data.data.aptitudes.${key}`); let aptitude = eval(`actor.system.aptitudes.${key}`);
let rollLabel = (aptitude.label) ? game.i18n.localize(aptitude.label) : null; let rollLabel = (aptitude.label) ? game.i18n.localize(aptitude.label) : null;
let description = actor.name + " - " + game.i18n.localize('BOL.ui.aptitudeCheck') + " - " + game.i18n.localize(aptitude.label) ; let description = actor.name + " - " + game.i18n.localize('BOL.ui.aptitudeCheck') + " - " + game.i18n.localize(aptitude.label) ;
BoLRoll.aptitudeRollDialog(actor, actorData, aptitude, rollLabel, description, adv, mod); BoLRoll.aptitudeRollDialog(actor, actorData, aptitude, rollLabel, description, adv, mod);

View File

@ -16,8 +16,13 @@ export const preloadHandlebarsTemplates = async function () {
"systems/bol/templates/actor/parts/tabs/actor-equipment.hbs", "systems/bol/templates/actor/parts/tabs/actor-equipment.hbs",
"systems/bol/templates/actor/parts/tabs/actor-spellalchemy.hbs", "systems/bol/templates/actor/parts/tabs/actor-spellalchemy.hbs",
"systems/bol/templates/actor/parts/tabs/actor-biodata.hbs", "systems/bol/templates/actor/parts/tabs/actor-biodata.hbs",
"systems/bol/templates/actor/parts/tabs/actor-horoscope-group.hbs",
"systems/bol/templates/actor/parts/tabs/creature-stats.hbs", "systems/bol/templates/actor/parts/tabs/creature-stats.hbs",
"systems/bol/templates/actor/parts/tabs/creature-actions.hbs", "systems/bol/templates/actor/parts/tabs/creature-actions.hbs",
"systems/bol/templates/actor/parts/tabs/vehicle-stats.hbs",
"systems/bol/templates/actor/parts/tabs/vehicle-description.hbs",
"systems/bol/templates/actor/parts/tabs/vehicle-weapons.hbs",
"systems/bol/templates/actor/parts/tabs/horde-description.hbs",
// ITEMS // ITEMS
"systems/bol/templates/item/parts/item-header.hbs", "systems/bol/templates/item/parts/item-header.hbs",
"systems/bol/templates/item/parts/properties/feature-properties.hbs", "systems/bol/templates/item/parts/properties/feature-properties.hbs",
@ -33,23 +38,31 @@ export const preloadHandlebarsTemplates = async function () {
"systems/bol/templates/item/parts/properties/feature/career-properties.hbs", "systems/bol/templates/item/parts/properties/feature/career-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/boon-properties.hbs", "systems/bol/templates/item/parts/properties/feature/boon-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/flaw-properties.hbs", "systems/bol/templates/item/parts/properties/feature/flaw-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/effect-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/origin-properties.hbs", "systems/bol/templates/item/parts/properties/feature/origin-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/race-properties.hbs", "systems/bol/templates/item/parts/properties/feature/race-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/fightoption-properties.hbs", "systems/bol/templates/item/parts/properties/feature/fightoption-properties.hbs",
"systems/bol/templates/item/parts/properties/item/weapon-vehicle-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/horoscope-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/xplog-properties.hbs",
// DIALOGS // DIALOGS
"systems/bol/templates/chat/rolls/attack-damage-card.hbs", "systems/bol/templates/chat/rolls/attack-damage-card.hbs",
"systems/bol/templates/chat/rolls/spell-roll-card.hbs", "systems/bol/templates/chat/rolls/spell-roll-card.hbs",
"systems/bol/templates/chat/rolls/alchemy-roll-card.hbs", "systems/bol/templates/chat/rolls/alchemy-roll-card.hbs",
"systems/bol/templates/chat/rolls/selected-horoscope-roll-card.hbs",
"systems/bol/templates/chat/rolls/horoscope-roll-card.hbs",
"systems/bol/templates/dialogs/aptitude-roll-part.hbs", "systems/bol/templates/dialogs/aptitude-roll-part.hbs",
"systems/bol/templates/dialogs/attribute-roll-part.hbs", "systems/bol/templates/dialogs/attribute-roll-part.hbs",
"systems/bol/templates/dialogs/mod-roll-part.hbs", "systems/bol/templates/dialogs/mod-roll-part.hbs",
"systems/bol/templates/dialogs/adv-roll-part.hbs", "systems/bol/templates/dialogs/adv-roll-part.hbs",
"systems/bol/templates/dialogs/career-roll-part.hbs", "systems/bol/templates/dialogs/career-roll-part.hbs",
"systems/bol/templates/dialogs/effect-roll-part.hbs",
"systems/bol/templates/dialogs/boons-roll-part.hbs", "systems/bol/templates/dialogs/boons-roll-part.hbs",
"systems/bol/templates/dialogs/flaws-roll-part.hbs", "systems/bol/templates/dialogs/flaws-roll-part.hbs",
"systems/bol/templates/dialogs/total-roll-part.hbs", "systems/bol/templates/dialogs/total-roll-part.hbs",
"systems/bol/templates/dialogs/fightoptions-roll-part.hbs", "systems/bol/templates/dialogs/fightoptions-roll-part.hbs",
"systems/bol/templates/dialogs/horoscope-roll-part.hbs"
]; ];
// Load the template parts // Load the template parts

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1 @@
MANIFEST-000407

0
packs/aides-de-jeu/LOCK Normal file
View File

8
packs/aides-de-jeu/LOG Normal file
View File

@ -0,0 +1,8 @@
2024/09/12-22:38:53.970077 7f25eea006c0 Recovering log #405
2024/09/12-22:38:53.982296 7f25eea006c0 Delete type=3 #403
2024/09/12-22:38:53.982396 7f25eea006c0 Delete type=0 #405
2024/09/12-22:42:42.719126 7f25eda006c0 Level-0 table #410: started
2024/09/12-22:42:42.719171 7f25eda006c0 Level-0 table #410: 0 bytes OK
2024/09/12-22:42:42.725570 7f25eda006c0 Delete type=0 #408
2024/09/12-22:42:42.725738 7f25eda006c0 Manual compaction at level-0 from '!journal!3xJg1rCxnWvEmoxS' @ 72057594037927935 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at (end)
2024/09/12-22:42:42.725784 7f25eda006c0 Manual compaction at level-1 from '!journal!3xJg1rCxnWvEmoxS' @ 72057594037927935 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at (end)

View File

@ -0,0 +1,8 @@
2024/09/12-09:45:32.427852 7f25eea006c0 Recovering log #401
2024/09/12-09:45:32.437849 7f25eea006c0 Delete type=3 #399
2024/09/12-09:45:32.437908 7f25eea006c0 Delete type=0 #401
2024/09/12-09:50:36.103159 7f25eda006c0 Level-0 table #406: started
2024/09/12-09:50:36.103188 7f25eda006c0 Level-0 table #406: 0 bytes OK
2024/09/12-09:50:36.110495 7f25eda006c0 Delete type=0 #404
2024/09/12-09:50:36.110872 7f25eda006c0 Manual compaction at level-0 from '!journal!3xJg1rCxnWvEmoxS' @ 72057594037927935 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at (end)
2024/09/12-09:50:36.110976 7f25eda006c0 Manual compaction at level-1 from '!journal!3xJg1rCxnWvEmoxS' @ 72057594037927935 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at (end)

Binary file not shown.

BIN
packs/armors/000200.ldb Normal file

Binary file not shown.

0
packs/armors/000315.log Normal file
View File

1
packs/armors/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000313

0
packs/armors/LOCK Normal file
View File

8
packs/armors/LOG Normal file
View File

@ -0,0 +1,8 @@
2024/09/12-22:38:53.934728 7f25f4c006c0 Recovering log #311
2024/09/12-22:38:53.947433 7f25f4c006c0 Delete type=3 #309
2024/09/12-22:38:53.947544 7f25f4c006c0 Delete type=0 #311
2024/09/12-22:42:42.699365 7f25eda006c0 Level-0 table #316: started
2024/09/12-22:42:42.699403 7f25eda006c0 Level-0 table #316: 0 bytes OK
2024/09/12-22:42:42.705522 7f25eda006c0 Delete type=0 #314
2024/09/12-22:42:42.725703 7f25eda006c0 Manual compaction at level-0 from '!items!G3dZTHIabA3LA1hY' @ 72057594037927935 : 1 .. '!items!xhEcsi3WHjbt2ro9' @ 0 : 0; will stop at (end)
2024/09/12-22:42:42.725745 7f25eda006c0 Manual compaction at level-1 from '!items!G3dZTHIabA3LA1hY' @ 72057594037927935 : 1 .. '!items!xhEcsi3WHjbt2ro9' @ 0 : 0; will stop at (end)

8
packs/armors/LOG.old Normal file
View File

@ -0,0 +1,8 @@
2024/09/12-09:45:32.401300 7f25efe006c0 Recovering log #307
2024/09/12-09:45:32.411529 7f25efe006c0 Delete type=3 #305
2024/09/12-09:45:32.411608 7f25efe006c0 Delete type=0 #307
2024/09/12-09:50:36.082865 7f25eda006c0 Level-0 table #312: started
2024/09/12-09:50:36.082893 7f25eda006c0 Level-0 table #312: 0 bytes OK
2024/09/12-09:50:36.090233 7f25eda006c0 Delete type=0 #310
2024/09/12-09:50:36.110780 7f25eda006c0 Manual compaction at level-0 from '!items!G3dZTHIabA3LA1hY' @ 72057594037927935 : 1 .. '!items!xhEcsi3WHjbt2ro9' @ 0 : 0; will stop at (end)
2024/09/12-09:50:36.110897 7f25eda006c0 Manual compaction at level-1 from '!items!G3dZTHIabA3LA1hY' @ 72057594037927935 : 1 .. '!items!xhEcsi3WHjbt2ro9' @ 0 : 0; will stop at (end)

Binary file not shown.

View File

@ -1,59 +0,0 @@
{"_id":"039ZF3E3MtAGwbiX","name":"Intrépide","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Intrépide</h1><p>votre personnage est insensible à la peur. Même une peur magiquement induite na aucune prise sur lui.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"2bSL4HJMu8Zh8UKq","name":"Attirant","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Attirant</h1><p>vous êtes particulièrement beau ou séduisant. Vous bénéficiez dun dé de bonus dans les situations où lapparence peut jouer un rôle.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"3fRMKd0xX0NL0kxO","name":"Vigueur céruléenne","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Vigueur céruléenne</h1><p>vous êtes grand et fort. Ajoutez 1 à votre vigueur. Votre score maximum en vigueur passe à 6 au lieu de 5, et votre score de départ maximum en vigueur peut être de 4 (au lieu de 3).</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"3jxkJo7vakII1kw0","name":"Renard du désert","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Renard du désert</h1><p>lorsque vous vous trouvez dans un désert, vous bénéficiez dun dé de bonus pour pister, piéger ou chasser, ainsi que pour dautres activités similaires de survie (mais pas pour combattre).</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"44bJY4xBP9ICdxrR","name":"Vue perçante","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Vue perçante</h1><p>à chaque fois que vous effectuez un jet daction sous esprit pour percevoir quelque chose grâce à votre vue, vous bénéficiez dun dé de bonus.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"4eCfIflrqYcQMQEE","name":"Laboratoire fourni","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Laboratoire fourni</h1><p>vous disposez dun laboratoire de qualité pour mener vos expériences. Vous bénéficiez dun dé de bonus aux jets pour créer des préparations alchimiques ou des instruments mécaniques lorsque vous vous trouvez dans votre laboratoire. Celui-ci doit toutefois être réapprovisionné de temps à autre, ce qui vous conduit à partir à laventure pour trouver les moyens financiers et matériels de refaire vos stocks.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"4j27jk1sauYKXUUY","name":"Magie des Rois-Sorciers","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Magie des Rois-Sorciers</h1><p>vous avez atteint une certaine compréhension des antiques secrets des Rois-Sorciers. Vous bénéficiez dun dé de bonus pour lancer des sortilèges. Si vous choisissez cet avantage, vous devez prendre un désavantage supplémentaire.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"76IT7lAHNjPHvoxu","name":"Savant","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Savant</h1><p>ajoutez 1 à votre esprit. Votre score maximum en esprit passe à 6 au lieu de 5, et votre score de départ maximum en esprit peut être de 4 (au lieu de 3).</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"7iHc6ZbgRDTcWx1x","name":"Poings dacier","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Poings dacier</h1><p>vous avez les poings durs comme la pierre après des années dentraînement ou à force de vous bagarrer dans toutes les tavernes de la ville. Vous ajoutez votre vigueur aux dégâts quand vous combattez à mains nues.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"88DKwHbEHNr2zkb4","name":"Gamin des rues","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Gamin des rues</h1><p>vous êtes un enfant des rues. Vous bénéficiez dun dé de bonus quand vous interagissez avec les gens des bas-fonds de la cité, ou pour des activités comme filer quelquun ou remarquer un détail dans la rue (mais pas pour combattre).</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"8LbWRVmpo2byaOae","name":"Colosse","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Colosse</h1><p>vous savez mobiliser votre vigueur pour accomplir de véritables tours de force. Vous bénéficiez dun dé de bonus pour briser, lever, tirer ou pousser des objets.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"8TKFwebDXkT4r3TW","name":"Dur à cuire","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Dur à cuire</h1><p>vous avez la robustesse dun bronyx. Ajoutez 2 points à votre vitalité.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"969U7SVd2JSBkHDq","name":"Artiste","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Artiste</h1><p>vous avez une sensibilité dartiste. Vous bénéficiez dun dé de bonus pour créer ou estimer des objets dart.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"DTZhsPUxseKuahCa","name":"Amis dans la pègre","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Amis dans la pègre</h1><p>vous comptez des amis peu recommandables parmi les différentes pègres qui gangrènent la Lémurie. Ils peuvent vous aider à trouver un receleur, vous fournir une planque, etc.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"DpO9z1NEg9C8MHGY","name":"Amis haut placés","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Amis haut placés</h1><p>vous jouissez de contacts au sein des plus hauts échelons de la société. Même sils ne seront pas en général disposés à risquer leur tête pour vous, ils pourront vous apporter de laide (comme vous obtenir une audience auprès dun autre personnage important, vous fournir des informations, jouer de leur influence auprès de la noblesse locale, etc.). Bien sûr, ces amis attendront parfois en retour une faveur de votre part...</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"DxCf9WsPm4tGRGri","name":"Athlète","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Athlète</h1><p>vous bénéficiez dun dé de bonus quand vous entreprenez des activités athlétiques (autres que le combat) comme courir, nager, grimper ou sauter.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"FaACBPxznjBInrNN","name":"Doigts de fée","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Doigts de fée</h1><p>vous bénéficiez dun dé de bonus pour toutes les tâches exigeant une grande dextérité, comme le vol à la tire, la fabrication dobjets, le jonglage ou la triche aux cartes et aux dés.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"GyNOCPaFw7bfjDUE","name":"Tireur puissant","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Tireur puissant</h1><p>avec un type darme à distance choisi (arc, fronde, javelot, etc.), vous ajoutez votre vigueur aux dégâts.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"HiD90AY8nD7OXXmr","name":"Bien né","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Bien né</h1><p>vous avez grandi dans les palais et les cours, parmi la noblesse et la haute société. Vous bénéficiez dun dé de bonus pour agir selon les règles de létiquette et de la courtoisie.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"HkJU2TaccPnBtZPh","name":"Montagnard","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Montagnard</h1><p>vous avez grandi dans les montagnes. Lorsque vous vous trouvez dans un paysage montagneux, vous bénéficiez dun dé de bonus pour pister, piéger ou chasser, ainsi que pour dautres activités similaires de survie (mais pas pour combattre).</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"IQdY6CJwUpXofsbM","name":"Ami des céruléens","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Ami des céruléens</h1><p>vous avez grandi à proximité des géants bleus, ou bien des circonstances particulières vous ont valu leur amitié, et ils vous considèrent comme un des leurs. Vous bénéficiez dun dé de bonus quand vous interagissez avec les nomades bleus.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"J08pVCsXzQYKijOF","name":"Résistant à la magie","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Résistant à la magie</h1><p>si vous êtes visé par un sortilège, lancez un d6. Sur un 6, le sortilège na aucun effet sur vous.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"JrxFjMUc9emmaiJe","name":"Ouïe fine","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Ouïe fine</h1><p>à chaque fois que vous effectuez un jet daction sous esprit pour percevoir quelque chose grâce à votre ouïe, vous bénéficiez dun dé de bonus.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"JxFxp2CS8dluwC16","name":"Bagarreur","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Bagarreur</h1><p>vous êtes un boxeur et un lutteur compétent. Vous bénéficiez dun dé de bonus à lattaque quand vous combattez à mains nues.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"LNP6F8z4j15HuuNC","name":"Fêtard","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Fêtard</h1><p>vous connaissez bien les auberges et les tavernes, et vous nêtes pas le dernier quand il sagit de lever le coude. Vous bénéficiez dun dé de bonus pour recueillir des informations, trouver des contacts ou obtenir des biens et des services quand vous vous trouvez dans une taverne. De plus, vous tenez très bien lalcool et bénéficiez également dun dé de bonus pour résister aux effets de la boisson.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"Ota12xlPiqDfM3te","name":"Maître du déguisement","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Maître du déguisement</h1><p>vous bénéficiez dun dé de bonus quand vous tentez de dissimuler votre identité. De plus, si vous souhaitez intervenir promptement dans une scène où votre personnage nétait pas présent, vous pouvez dépenser 1 point dhéroïsme pour faire partie du décor, par exemple déguisé en garde de la patrouille ou en bourgeois passant dans la rue. En fait, vous étiez là depuis le début, mais incognito!</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"Td0r46VMDXd5Z65z","name":"Tigre des neiges","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Tigre des neiges</h1><p>vous avez grandi dans la toundra gelée. Lorsque vous vous trouvez dans un paysage neigeux, vous bénéficiez dun dé de bonus pour pister, piéger ou chasser, ainsi que pour dautres activités similaires de survie (mais pas pour combattre).</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"VXVu8CTas4nhfUST","name":"Sentir la magie","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Sentir la magie</h1><p>vous bénéficiez dun dé de bonus quand vous essayez de reconnaître (ou de traquer) un sorcier, un effet ou un artefact magique.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"W4onU67kbMUL3WVa","name":"Résistant aux poisons","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Résistant aux poisons</h1><p>vous bénéficiez dun dé de bonus pour résister aux effets des drogues, des venins, des toxines, ainsi que de lalcool.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"WSXuMtTEvjC2qOH7","name":"Pied marin","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Pied marin</h1><p>vous avez grandi dans un environnement de navires et de bateaux. Vous bénéficiez dun dé de bonus pour manœuvrer une embarcation ou entreprendre des activités physiques à bord dun navire (mais pas pour combattre).</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"WTl5A8SbC6o2bRna","name":"Fortuné","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Fortuné</h1><p>vous disposez dune source de revenus ou dun héritage. Vous bénéficiez dun dé de bonus quand vous cherchez à acquérir des biens ou des services dans votre cité dorigine.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"XXaAGtAadv5Ltlht","name":"Santé de fer","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Santé de fer</h1><p>vous êtes immunisé à toutes les maladies, y compris celles dorigine magique.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"XfGnKJU87Tv9AKtL","name":"Bibliothèque savante","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Bibliothèque savante</h1><p>vous disposez dune bibliothèque de qualité pour mener vos recherches. Vous bénéficiez dun dé de bonus pour recueillir des informations lorsque vous vous trouvez dans votre bibliothèque. Vous devez toutefois enrichir régulièrement vos collections, ce qui vous conduit à partir à laventure pour trouver les moyens dacquérir de nouveaux manuscrits.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"XiUi4LnrOswsEpXR","name":"Vigilant","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Vigilant</h1><p>vous jouissez dune excellente capacité de réaction face au danger. Vous bénéficiez dun dé de bonus à vos jets de réaction.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"aYv5FEDWzYRwIwRm","name":"Né en selle","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Né en selle</h1><p>vous bénéficiez dun dé de bonus pour chevaucher des montures et agir en selle (mais pas pour combattre).</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"cDe8mZ7vjpI1o1lZ","name":"Mains guérisseuses","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Mains guérisseuses</h1><p>vous bénéficiez dun dé de bonus sur les tests destinés à aider un blessé à récupérer de ses blessures, dun empoisonnement, etc. Vous devez posséder la carrière médecin pour prendre cet avantage.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"dpS4VXHUGddCq7FY","name":"Intimidant","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Intimidant</h1><p>vous bénéficiez dun dé de bonus à chaque fois que vous essayez de forcer quelquun à vous donner une information ou à faire une chose à laquelle il répugne.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"dslHEmEqSZN8IsPa","name":"Fils des plaines","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Fils des plaines</h1><p>vous avez grandi dans les plaines. Lorsque vous vous trouvez dans un paysage de plaine, vous bénéficiez dun dé de bonus pour pister, piéger ou chasser, ainsi que pour dautres activités similaires de survie (mais pas pour combattre).</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"eH6ER2AVPrhzZGn1","name":"Combat à laveugle","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Combat à laveugle</h1><p>pas de lumière ? Aucun problème. En vous basant sur les odeurs, les bruits, les déplacements dair, vous ne faites plus quun avec le monde qui vous entoure. Votre personnage ignore les malus imposés par le MJ pour combattre dans lobscurité.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"ft3lNO5aDd9eK40k","name":"Roi de la jungle","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Roi de la jungle</h1><p>vous avez grandi dans la jungle. Lorsque vous vous trouvez dans un paysage de jungle, vous bénéficiez dun dé de bonus pour pister, piéger ou chasser, ainsi que pour dautres activités similaires de survie (mais pas pour combattre).</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"fzsDuaqZtvt4wue4","name":"Arme favorite","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Arme favorite</h1><p>vous disposez dune arme de qualité (une grande épée valgardienne, un arc long de Tyrus, une fronde dAxos, un kriss halakhi, un khastok de Malakut, une hache dabordage de Parsool, une rapière de Satarla, ou une arme spécialement fabriquée pour vous ou dont vous avez hérité) et vous vous êtes entraîné à son maniement depuis lenfance. Vous bénéficiez dun dé de bonus lorsque vous utilisez cette arme (ou, si elle est perdue, volée ou détruite, une arme de substitution qui devra reproduire ses qualités uniques, ce qui risque dêtre particulièrement onéreux).</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"giB7dYrcKv12m13K","name":"Peau dure","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Peau dure</h1><p>vous avez une peau particulièrement résistante et épaisse qui vous confère +1 en protection, même quand vous ne portez pas darmure.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"glCazKBiZ4TA5Tnt","name":"Inspirateur","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Inspirateur</h1><p>vous savez motiver vos amis et vos partisans. Cela peut se faire au moyen dune invocation aux dieux, dun discours enflammé ou dune musique inspirante, à moins que cela ne vienne simplement de votre présence charismatique. Pour le round qui suit lutilisation de cet avantage, vos compagnons bénéficient dun dé de bonus à tous leurs jets dattaque (à condition dêtre à portée de voix). Cet avantage ne peut être utilisé gratuitement quune fois par jour ; toute utilisation supplémentaire exigera la dépense de 1 point dhéroïsme.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"jkgnvC8cAK7K5Ck9","name":"Récupération rapide","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Récupération rapide</h1><p>vous jouissiez dune constitution hors norme. Lorsque vous récupérez après un combat, vous regagnez 1 point de vitalité supplémentaire (qui sajoute à la récupération normale, égale à la moitié des points perdus). De plus, si vous êtes blessé, vous récupérez 1 point de vitalité par jour, peu importe les activités que vous entreprenez.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"lDSYZ54BnXt4VYlE","name":"Cri de guerre","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Cri de guerre</h1><p>le personnage pousse son cri de guerre pour effrayer les ennemis à portée de voix. Ces derniers subissent un dé de malus sur tous leurs jets dattaque durant le round qui suit le cri de guerre. Cet avantage ne peut être utilisé gratuitement quune fois par jour ; toute utilisation supplémentaire exigera la dépense de 1 point dhéroïsme.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"mwK667DIyh2QGqPV","name":"Beau parleur","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Beau parleur</h1><p>vous êtes très persuasif et excellent menteur. Vous bénéficiez dun dé de bonus quand vous voulez mentir, escroquer, baratiner ou tromper quelquun.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"nl7sgrsCy0T0P127","name":"Pouvoir du Néant","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Pouvoir du Néant</h1><p>vous avez porté le regard sur labîme de noirceur du Néant, et recevez deux points de pouvoir supplémentaires. Si vous choisissez cet avantage, vous devez aussi prendre un désavantage supplémentaire.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"oFnXU6VPTG5QypMz","name":"Agilité de lhomme-oiseau","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Agilité de lhomme-oiseau</h1><p>ajoutez 1 à votre agilité. Votre score maximum en agilité passe à 6 au lieu de 5, et votre score de départ maximum en agilité peut être de 4 (au lieu de 3).</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"oiASQBPLrFXYEVuP","name":"Ami des bêtes","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Ami des bêtes</h1><p>vous possédez une affinité naturelle avec les animaux. Vous bénéficiez dun dé de bonus quand vous interagissez avec eux. Si vous êtes dresseur, vous pouvez avoir avec vous deux ou trois compagnons animaux de taille petite, ou un seul de taille moyenne ou grande.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"qGI3aI5xA0mqHXdU","name":"Discret","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Discret</h1>\n<p>vous &ecirc;tes vif et agile. Vous b&eacute;n&eacute;ficiez d&rsquo;un d&eacute; de bonus dans les situations o&ugrave; vous essayez de faire preuve de discr&eacute;tion.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"sggncrizxp9b84sY","name":"Érudit","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Érudit</h1><p>quand vous cherchez à vous souvenir dun fait relevant de votre domaine de compétence, vous bénéficiez dun dé de bonus.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"snSCU6lBKz8nzqeQ","name":"Baudrier de guerre","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Baudrier de guerre</h1><p>cet avantage autorise votre personnage à ne porter quun pagne ou un bikini en cotte de mailles et un simple baudrier (léquivalent dune armure légère au mieux), tout en considérant quil sagit dune armure moyenne en terme de protection, et ce sans subir le moindre malus darmure.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"wZjOWMREZRw1tLO0","name":"Marqué par les dieux","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Marqué par les dieux</h1><p>les dieux vous accordent leur faveur. Vous gagnez 1 point dhéroïsme supplémentaire.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"xAyqso8n6MaJNTJs","name":"Perspicace","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Perspicace</h1><p>vous êtes doué pour percer à jour les menteurs. Quand quelquun tente de vous mentir ou de vous entourlouper, vous bénéficiez dun dé de bonus pour le remarquer. Cela ne veut pas dire que vous connaîtrez forcément la vérité, mais vous saurez au moins quon est en train de vous mentir.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"yEsGuSGUDVYFdzRV","name":"Roi de lévasion","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Roi de lévasion</h1><p>cordes, chaînes, menottes, prison, rien ne vous retient bien longtemps. Que ce soit par vos talents ou par un coup de chance, vous finissez toujours par vous libérer. Vous bénéficiez dun dé de bonus lorsque vous tentez de vous évader ou de vous libérer de vos liens.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"ywZsgCLCszvZWzfB","name":"Odorat développé","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Odorat développé</h1><p>à chaque fois que vous effectuez un jet daction sous esprit pour percevoir quelque chose grâce à votre odorat, vous bénéficiez dun dé de bonus.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"yxkhtcJA6ziEBsHa","name":"Pisteur des marais","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Pisteur des marais</h1><p>vous avez grandi dans les marais. Lorsque vous vous trouvez dans un paysage de marécage, vous bénéficiez dun dé de bonus pour pister, piéger ou chasser, ainsi que pour dautres activités similaires de survie (mais pas pour combattre).</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"yy7b6rYzyXTXAc5K","name":"Outillage","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Outillage</h1><p>vous possédez un jeu doutils adaptés à votre métier ou votre artisanat. Vous bénéficiez dun dé de bonus quand vous entreprenez une action où lemploi de ces outils peut se révéler efficace.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}
{"_id":"zgspy1QKaxdEetEw","name":"Vision nocturne","type":"feature","img":"/systems/bol/ui/icons/boon.webp","data":{"category":null,"subtype":"boon","description":"<h1>Vision nocturne</h1><p>vous bénéficiez dun dé de bonus quand lobscurité impose un malus à la vision.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"EEnCVoPAR7pMjRym":3},"flags":{}}

BIN
packs/boons/000294.ldb Normal file

Binary file not shown.

0
packs/boons/000409.log Normal file
View File

1
packs/boons/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000407

0
packs/boons/LOCK Normal file
View File

8
packs/boons/LOG Normal file
View File

@ -0,0 +1,8 @@
2024/09/12-22:38:53.788249 7f25f4c006c0 Recovering log #405
2024/09/12-22:38:53.800311 7f25f4c006c0 Delete type=3 #403
2024/09/12-22:38:53.800582 7f25f4c006c0 Delete type=0 #405
2024/09/12-22:42:42.640434 7f25eda006c0 Level-0 table #410: started
2024/09/12-22:42:42.640516 7f25eda006c0 Level-0 table #410: 0 bytes OK
2024/09/12-22:42:42.647688 7f25eda006c0 Delete type=0 #408
2024/09/12-22:42:42.668731 7f25eda006c0 Manual compaction at level-0 from '!items!039ZF3E3MtAGwbiX' @ 72057594037927935 : 1 .. '!items!zgspy1QKaxdEetEw' @ 0 : 0; will stop at (end)
2024/09/12-22:42:42.668779 7f25eda006c0 Manual compaction at level-1 from '!items!039ZF3E3MtAGwbiX' @ 72057594037927935 : 1 .. '!items!zgspy1QKaxdEetEw' @ 0 : 0; will stop at (end)

8
packs/boons/LOG.old Normal file
View File

@ -0,0 +1,8 @@
2024/09/12-09:45:32.295259 7f25efe006c0 Recovering log #401
2024/09/12-09:45:32.306146 7f25efe006c0 Delete type=3 #399
2024/09/12-09:45:32.306221 7f25efe006c0 Delete type=0 #401
2024/09/12-09:50:36.045097 7f25eda006c0 Level-0 table #406: started
2024/09/12-09:50:36.045124 7f25eda006c0 Level-0 table #406: 0 bytes OK
2024/09/12-09:50:36.051371 7f25eda006c0 Delete type=0 #404
2024/09/12-09:50:36.057645 7f25eda006c0 Manual compaction at level-0 from '!items!039ZF3E3MtAGwbiX' @ 72057594037927935 : 1 .. '!items!zgspy1QKaxdEetEw' @ 0 : 0; will stop at (end)
2024/09/12-09:50:36.057725 7f25eda006c0 Manual compaction at level-1 from '!items!039ZF3E3MtAGwbiX' @ 72057594037927935 : 1 .. '!items!zgspy1QKaxdEetEw' @ 0 : 0; will stop at (end)

BIN
packs/boons/MANIFEST-000407 Normal file

Binary file not shown.

View File

@ -1,8 +0,0 @@
{"name":"Attaque Timide","type":"feature","img":"icons/svg/item-bag.svg","data":{"category":null,"subtype":"flaw","description":"<p>Attaque timide : la cr&eacute;ature subit un d&eacute; de malus &nbsp;aux jets d&rsquo;attaque.</p>","properties":{"isbonusdice":true,"ismalusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{},"_id":"CoqlfsDV1gL5swbK"}
{"name":"Prédateur","type":"feature","img":"icons/svg/item-bag.svg","data":{"category":null,"subtype":"boon","description":"<p>&nbsp;la cr&eacute;ature lance un d&eacute; de bonus pour tout ce qui concerne le pistage d&rsquo;une proie.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{},"_id":"DFdLY7fkVZDIf7rU"}
{"name":"Camouflage","type":"feature","img":"icons/svg/item-bag.svg","data":{"category":null,"subtype":"boon","description":"<p>Camouflage : la cr&eacute;ature est difficile &agrave; rep&eacute;rer &nbsp;en raison de la coloration ou de la texture de sa&nbsp;peau ou de son pelage (d&eacute; de bonus pour se cacher).</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.b0PsoNEd8a0dN2Wm"}},"_id":"P2pgGD4FVKzOZ4uM"}
{"name":"Attaque féroce","type":"feature","img":"icons/svg/item-bag.svg","data":{"category":null,"subtype":"boon","description":"<p>&nbsp;la cr&eacute;ature b&eacute;n&eacute;ficie d&rsquo;un d&eacute; de&nbsp;bonus aux jets d&rsquo;attaque.</p>","properties":{"isbonusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.b0PsoNEd8a0dN2Wm"}},"_id":"RqEO7ELH72MZBZFV"}
{"name":"Attaque Venimeuse","type":"feature","img":"icons/svg/item-bag.svg","data":{"category":null,"subtype":"boon","description":"<p>Attaque venimeuse : la description de la &nbsp;cr&eacute;ature indique les effets de son venin</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.b0PsoNEd8a0dN2Wm"}},"_id":"U77iMP7V529zbJt9"}
{"name":"Attaque Multiple","type":"feature","img":"icons/svg/item-bag.svg","data":{"category":null,"subtype":"boon","description":"<p>Attaques multiples : la cr&eacute;ature poss&egrave;de <span style=\"font-family: var(--font-primary); font-size: var(--font-size-14);\">&nbsp;deux types d&rsquo;attaque totalement diff&eacute;rents qui&nbsp;</span>n&eacute;cessitent deux jets d&rsquo;attaque s&eacute;par&eacute;s.</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.b0PsoNEd8a0dN2Wm"}},"_id":"USkChPye9J4sZxwC"}
{"name":"Déficience","type":"feature","img":"icons/svg/item-bag.svg","data":{"category":null,"subtype":"flaw","description":"<p>D&eacute;ficience : la cr&eacute;ature est afflig&eacute;e d&rsquo;un odorat,&nbsp;d&rsquo;une audition ou d&rsquo;une vision d&eacute;ficiente et subit&nbsp;un d&eacute; de malus quand elle doit y faire appel.</p>","properties":{"isbonusdice":true,"ismalusdice":true},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.P0r8grkVY7xu5HOS"}},"_id":"htSqR7I7F5GVIelK"}
{"name":"Attaque Spéciale","type":"feature","img":"icons/svg/item-bag.svg","data":{"category":null,"subtype":"boon","description":"<p>Attaque sp&eacute;ciale : la cr&eacute;ature attaque selon une m&eacute;thode inhabituelle. La nature de cette attaque est expliqu&eacute;e dans sa description.</p>\n<p>&nbsp;</p>","properties":{"isbonusdice":false},"rank":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.b0PsoNEd8a0dN2Wm"}},"_id":"yofwG0YrsL902G77"}

Binary file not shown.

View File

View File

@ -0,0 +1 @@
MANIFEST-000407

View File

View File

@ -0,0 +1,8 @@
2024/09/12-22:38:53.805528 7f25ef4006c0 Recovering log #405
2024/09/12-22:38:53.816302 7f25ef4006c0 Delete type=3 #403
2024/09/12-22:38:53.816406 7f25ef4006c0 Delete type=0 #405
2024/09/12-22:42:42.654478 7f25eda006c0 Level-0 table #410: started
2024/09/12-22:42:42.654519 7f25eda006c0 Level-0 table #410: 0 bytes OK
2024/09/12-22:42:42.660807 7f25eda006c0 Delete type=0 #408
2024/09/12-22:42:42.668759 7f25eda006c0 Manual compaction at level-0 from '!items!CoqlfsDV1gL5swbK' @ 72057594037927935 : 1 .. '!items!yofwG0YrsL902G77' @ 0 : 0; will stop at (end)
2024/09/12-22:42:42.668796 7f25eda006c0 Manual compaction at level-1 from '!items!CoqlfsDV1gL5swbK' @ 72057594037927935 : 1 .. '!items!yofwG0YrsL902G77' @ 0 : 0; will stop at (end)

View File

@ -0,0 +1,8 @@
2024/09/12-09:45:32.310129 7f25f4c006c0 Recovering log #401
2024/09/12-09:45:32.320731 7f25f4c006c0 Delete type=3 #399
2024/09/12-09:45:32.320830 7f25f4c006c0 Delete type=0 #401
2024/09/12-09:50:36.033550 7f25eda006c0 Level-0 table #406: started
2024/09/12-09:50:36.033588 7f25eda006c0 Level-0 table #406: 0 bytes OK
2024/09/12-09:50:36.039266 7f25eda006c0 Delete type=0 #404
2024/09/12-09:50:36.057599 7f25eda006c0 Manual compaction at level-0 from '!items!CoqlfsDV1gL5swbK' @ 72057594037927935 : 1 .. '!items!yofwG0YrsL902G77' @ 0 : 0; will stop at (end)
2024/09/12-09:50:36.057695 7f25eda006c0 Manual compaction at level-1 from '!items!CoqlfsDV1gL5swbK' @ 72057594037927935 : 1 .. '!items!yofwG0YrsL902G77' @ 0 : 0; will stop at (end)

Binary file not shown.

File diff suppressed because one or more lines are too long

BIN
packs/careers/000294.ldb Normal file

Binary file not shown.

0
packs/careers/000409.log Normal file
View File

1
packs/careers/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000407

0
packs/careers/LOCK Normal file
View File

8
packs/careers/LOG Normal file
View File

@ -0,0 +1,8 @@
2024/09/12-22:38:53.840310 7f25efe006c0 Recovering log #405
2024/09/12-22:38:53.852677 7f25efe006c0 Delete type=3 #403
2024/09/12-22:38:53.852769 7f25efe006c0 Delete type=0 #405
2024/09/12-22:42:42.660981 7f25eda006c0 Level-0 table #410: started
2024/09/12-22:42:42.661021 7f25eda006c0 Level-0 table #410: 0 bytes OK
2024/09/12-22:42:42.668582 7f25eda006c0 Delete type=0 #408
2024/09/12-22:42:42.668771 7f25eda006c0 Manual compaction at level-0 from '!items!4S4xAfMXGnuU0O1a' @ 72057594037927935 : 1 .. '!items!zxY3sW0iCJBvwjOS' @ 0 : 0; will stop at (end)
2024/09/12-22:42:42.668804 7f25eda006c0 Manual compaction at level-1 from '!items!4S4xAfMXGnuU0O1a' @ 72057594037927935 : 1 .. '!items!zxY3sW0iCJBvwjOS' @ 0 : 0; will stop at (end)

8
packs/careers/LOG.old Normal file
View File

@ -0,0 +1,8 @@
2024/09/12-09:45:32.336593 7f25ef4006c0 Recovering log #401
2024/09/12-09:45:32.347205 7f25ef4006c0 Delete type=3 #399
2024/09/12-09:45:32.347263 7f25ef4006c0 Delete type=0 #401
2024/09/12-09:50:36.039384 7f25eda006c0 Level-0 table #406: started
2024/09/12-09:50:36.039412 7f25eda006c0 Level-0 table #406: 0 bytes OK
2024/09/12-09:50:36.044990 7f25eda006c0 Delete type=0 #404
2024/09/12-09:50:36.057626 7f25eda006c0 Manual compaction at level-0 from '!items!4S4xAfMXGnuU0O1a' @ 72057594037927935 : 1 .. '!items!zxY3sW0iCJBvwjOS' @ 0 : 0; will stop at (end)
2024/09/12-09:50:36.057710 7f25eda006c0 Manual compaction at level-1 from '!items!4S4xAfMXGnuU0O1a' @ 72057594037927935 : 1 .. '!items!zxY3sW0iCJBvwjOS' @ 0 : 0; will stop at (end)

Binary file not shown.

File diff suppressed because one or more lines are too long

BIN
packs/cartes/000122.ldb Normal file

Binary file not shown.

0
packs/cartes/000285.log Normal file
View File

1
packs/cartes/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000283

0
packs/cartes/LOCK Normal file
View File

8
packs/cartes/LOG Normal file
View File

@ -0,0 +1,8 @@
2024/07/08-22:24:33.833224 7fb8320006c0 Recovering log #281
2024/07/08-22:24:33.895807 7fb8320006c0 Delete type=3 #279
2024/07/08-22:24:33.895934 7fb8320006c0 Delete type=0 #281
2024/07/08-22:24:52.466387 7fb82be006c0 Level-0 table #286: started
2024/07/08-22:24:52.466440 7fb82be006c0 Level-0 table #286: 0 bytes OK
2024/07/08-22:24:52.472857 7fb82be006c0 Delete type=0 #284
2024/07/08-22:24:52.480332 7fb82be006c0 Manual compaction at level-0 from '!scenes!1ZDXKpKixS12xzW3' @ 72057594037927935 : 1 .. '!scenes.tiles!78gEyXvSfBJi9iL1.rJglQmZXB0eRIL8y' @ 0 : 0; will stop at (end)
2024/07/08-22:24:52.480427 7fb82be006c0 Manual compaction at level-1 from '!scenes!1ZDXKpKixS12xzW3' @ 72057594037927935 : 1 .. '!scenes.tiles!78gEyXvSfBJi9iL1.rJglQmZXB0eRIL8y' @ 0 : 0; will stop at (end)

8
packs/cartes/LOG.old Normal file
View File

@ -0,0 +1,8 @@
2024/07/08-22:22:58.298438 7fb832a006c0 Recovering log #277
2024/07/08-22:22:58.309146 7fb832a006c0 Delete type=3 #275
2024/07/08-22:22:58.309315 7fb832a006c0 Delete type=0 #277
2024/07/08-22:24:02.597516 7fb82be006c0 Level-0 table #282: started
2024/07/08-22:24:02.597563 7fb82be006c0 Level-0 table #282: 0 bytes OK
2024/07/08-22:24:02.685456 7fb82be006c0 Delete type=0 #280
2024/07/08-22:24:02.775806 7fb82be006c0 Manual compaction at level-0 from '!scenes!1ZDXKpKixS12xzW3' @ 72057594037927935 : 1 .. '!scenes.tiles!78gEyXvSfBJi9iL1.rJglQmZXB0eRIL8y' @ 0 : 0; will stop at (end)
2024/07/08-22:24:02.775850 7fb82be006c0 Manual compaction at level-1 from '!scenes!1ZDXKpKixS12xzW3' @ 72057594037927935 : 1 .. '!scenes.tiles!78gEyXvSfBJi9iL1.rJglQmZXB0eRIL8y' @ 0 : 0; will stop at (end)

Binary file not shown.

File diff suppressed because one or more lines are too long

BIN
packs/creatures/000203.ldb Normal file

Binary file not shown.

View File

1
packs/creatures/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000208

0
packs/creatures/LOCK Normal file
View File

8
packs/creatures/LOG Normal file
View File

@ -0,0 +1,8 @@
2024/02/23-23:05:36.345111 7fe93a0006c0 Recovering log #206
2024/02/23-23:05:36.355350 7fe93a0006c0 Delete type=3 #204
2024/02/23-23:05:36.355397 7fe93a0006c0 Delete type=0 #206
2024/02/23-23:11:16.411887 7fe9336006c0 Level-0 table #211: started
2024/02/23-23:11:16.411923 7fe9336006c0 Level-0 table #211: 0 bytes OK
2024/02/23-23:11:16.418695 7fe9336006c0 Delete type=0 #209
2024/02/23-23:11:16.419070 7fe9336006c0 Manual compaction at level-0 from '!actors!1QGaindSWLCT4QXD' @ 72057594037927935 : 1 .. '!actors.items!yGlDTCiMiaH4vJTH.mvXGkWoCcRGjUpYV' @ 0 : 0; will stop at (end)
2024/02/23-23:11:16.419088 7fe9336006c0 Manual compaction at level-1 from '!actors!1QGaindSWLCT4QXD' @ 72057594037927935 : 1 .. '!actors.items!yGlDTCiMiaH4vJTH.mvXGkWoCcRGjUpYV' @ 0 : 0; will stop at (end)

8
packs/creatures/LOG.old Normal file
View File

@ -0,0 +1,8 @@
2024/02/22-16:41:06.582756 7fe93be006c0 Recovering log #201
2024/02/22-16:41:06.592273 7fe93be006c0 Delete type=3 #199
2024/02/22-16:41:06.592326 7fe93be006c0 Delete type=0 #201
2024/02/22-17:53:02.294923 7fe9336006c0 Level-0 table #207: started
2024/02/22-17:53:02.294959 7fe9336006c0 Level-0 table #207: 0 bytes OK
2024/02/22-17:53:02.313594 7fe9336006c0 Delete type=0 #205
2024/02/22-17:53:02.322132 7fe9336006c0 Manual compaction at level-0 from '!actors!1QGaindSWLCT4QXD' @ 72057594037927935 : 1 .. '!actors.items!yGlDTCiMiaH4vJTH.mvXGkWoCcRGjUpYV' @ 0 : 0; will stop at (end)
2024/02/22-17:53:02.322180 7fe9336006c0 Manual compaction at level-1 from '!actors!1QGaindSWLCT4QXD' @ 72057594037927935 : 1 .. '!actors.items!yGlDTCiMiaH4vJTH.mvXGkWoCcRGjUpYV' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

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