Compare commits
31 Commits
bol-v12.1.
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 7adc1b3f07 | |||
| 6c70dc147c | |||
| 1ffb8b08fc | |||
| 8017bb207d | |||
| 364278527d | |||
| 93d35abde2 | |||
| 0409be64eb | |||
| ed76a49e7d | |||
| 2abd2c881a | |||
| 3fa5ca66d1 | |||
| 6de15eeda7 | |||
| 724c096743 | |||
| 3e3a4b9ec1 | |||
| 425a2a1fc0 | |||
| 203d7add66 | |||
| 8ae193dc34 | |||
| 3904f595b5 | |||
| 1bf21fae7f | |||
| 22579c21bc | |||
| 50c5c31e7b | |||
| a8c05cd4de | |||
| e1cea78059 | |||
| c2f9934f5f | |||
| 313c8a85fa | |||
| 74f6d4d54a | |||
| 2eb153ce14 | |||
| fe513e821a | |||
| 1b72c9c467 | |||
| 3c3a0901da | |||
| 3fc6d3e3df | |||
| 69b34669b0 |
@@ -1,6 +1,6 @@
|
||||
name: Release Creation
|
||||
|
||||
on:
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
@@ -8,47 +8,56 @@ 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'
|
||||
- run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner."
|
||||
|
||||
# get part of the tag after the `v`
|
||||
- name: Extract tag version number
|
||||
id: get_version
|
||||
uses: battila7/get-version-action@v2
|
||||
#- uses: actions/checkout@v3
|
||||
- uses: RouxAntoine/checkout@v3.5.4
|
||||
|
||||
# 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
|
||||
# get part of the tag after the `v`
|
||||
- name: Extract tag version number
|
||||
id: get_version
|
||||
uses: battila7/get-version-action@v2
|
||||
|
||||
- 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}}'
|
||||
# Substitute the Manifest and Download URLs in the system.json
|
||||
- name: Substitute Manifest and Download Links For Versioned Ones
|
||||
id: sub_manifest_link_version
|
||||
uses: microsoft/variable-substitution@v1
|
||||
with:
|
||||
files: "system.json"
|
||||
env:
|
||||
version: ${{steps.get_version.outputs.version-without-v}}
|
||||
url: https://www.uberwald.me/gitea/${{gitea.repository}}
|
||||
manifest: https://www.uberwald.me/gitea/public/bol/releases/download/latest/system.json
|
||||
download: https://www.uberwald.me/gitea/${{gitea.repository}}/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/ compendiums/ 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.ALLOW_PUSH_RELEASE}}"
|
||||
|
||||
- name: Publish to Foundry server
|
||||
uses: https://github.com/djlechuck/foundryvtt-publish-package-action@v1
|
||||
with:
|
||||
token: ${{ secrets.FOUNDRYVTT_RELEASE_TOKEN }}
|
||||
id: "bol"
|
||||
version: ${{github.event.release.tag_name}}
|
||||
manifest: "https://www.uberwald.me/gitea/public/bol/releases/download/latest/system.json"
|
||||
notes: "https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/bol.zip"
|
||||
compatibility-minimum: "13"
|
||||
compatibility-verified: "13"
|
||||
|
||||
286
APPV2_ITEMS_MIGRATION.md
Normal file
286
APPV2_ITEMS_MIGRATION.md
Normal file
@@ -0,0 +1,286 @@
|
||||
# Migration AppV2 - Item Sheets
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
Migration des feuilles d'items de BoL vers l'architecture **ApplicationV2** de Foundry VTT v12+.
|
||||
|
||||
## Fichiers créés
|
||||
|
||||
### Classes AppV2 (module/applications/sheets/)
|
||||
|
||||
1. **base-item-sheet.mjs** - Classe de base pour tous les item sheets
|
||||
- Hérite de `foundry.applications.sheets.ItemSheetV2`
|
||||
- Utilise `HandlebarsApplicationMixin`
|
||||
- Gère les tabs, drag & drop, actions communes
|
||||
- 272 lignes de code
|
||||
|
||||
2. **item-sheet.mjs** - Sheet pour le type "item"
|
||||
- Équipements, armes, protections, sorts, etc.
|
||||
- Hérite de `BoLBaseItemSheet`
|
||||
- Contexte spécifique aux items
|
||||
|
||||
3. **feature-sheet.mjs** - Sheet pour le type "feature"
|
||||
- Boons, flaws, careers, origins, races, etc.
|
||||
- Hérite de `BoLBaseItemSheet`
|
||||
- Contexte spécifique aux features
|
||||
|
||||
4. **_module.mjs** - Export des sheets
|
||||
|
||||
### Templates (templates/item/)
|
||||
|
||||
1. **item-sheet.hbs** - Template pour les items
|
||||
2. **feature-sheet.hbs** - Template pour les features
|
||||
3. **parts/item-header.hbs** - Header mis à jour pour AppV2
|
||||
|
||||
### Backups
|
||||
|
||||
- `templates/item.backup/` - Backup des templates originaux
|
||||
- `module/item.backup/` - Backup de l'ancienne classe ItemSheet
|
||||
- `templates/item/parts/item-header.hbs.backup` - Backup du header
|
||||
|
||||
## Architecture AppV2
|
||||
|
||||
### Différences avec AppV1
|
||||
|
||||
| Aspect | AppV1 (avant) | AppV2 (après) |
|
||||
|--------|---------------|---------------|
|
||||
| Classe de base | `ItemSheet` | `ItemSheetV2` |
|
||||
| Options | `static get defaultOptions()` | `static DEFAULT_OPTIONS` |
|
||||
| getData | `async getData()` | `async _prepareContext()` |
|
||||
| Template | Unique | Peut utiliser PARTS |
|
||||
| Tabs | Automatiques | Gestion manuelle |
|
||||
| Actions | Event listeners | `actions:` dans OPTIONS |
|
||||
| Render | `activateListeners()` | `_onRender()` |
|
||||
|
||||
### Structure de BoLBaseItemSheet
|
||||
|
||||
```javascript
|
||||
class BoLBaseItemSheet extends ItemSheetV2 {
|
||||
// Options statiques
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes, position, form, window,
|
||||
actions, dragDrop, tabs
|
||||
}
|
||||
|
||||
// State
|
||||
tabGroups = { primary: "description" }
|
||||
|
||||
// Méthodes principales
|
||||
async _prepareContext() // Prépare les données
|
||||
_onRender() // Après le render
|
||||
_activateTabs() // Active les tabs
|
||||
_activateListeners() // Event listeners
|
||||
|
||||
// Actions
|
||||
static #onEditImage() // data-action="editImage"
|
||||
static #onPostItem() // data-action="postItem"
|
||||
|
||||
// Drag & Drop
|
||||
#createDragDropHandlers()
|
||||
_canDragStart()
|
||||
_onDragStart()
|
||||
}
|
||||
```
|
||||
|
||||
## Fonctionnalités migrées
|
||||
|
||||
### ✅ Depuis l'ancien BoLItemSheet
|
||||
|
||||
1. **getData** → **_prepareContext**
|
||||
- Enrichissement de la description
|
||||
- Configuration des données dynamiques
|
||||
- Gestion des catégories
|
||||
- Propriétés des items
|
||||
- Careers depuis l'actor
|
||||
|
||||
2. **Tabs**
|
||||
- Navigation entre Description et Properties
|
||||
- State persistant avec `tabGroups`
|
||||
- Activation manuelle des tabs
|
||||
|
||||
3. **Actions**
|
||||
- Edit Image (FilePicker)
|
||||
- Post Item (chat)
|
||||
|
||||
4. **Listeners spécifiques**
|
||||
- Armor quality → soak formula
|
||||
|
||||
5. **Dynamic defaults**
|
||||
- Category par défaut
|
||||
- Spell conditions (mandatory/optional)
|
||||
- Equipment slots
|
||||
|
||||
## Utilisation dans les templates
|
||||
|
||||
### Actions (data-action)
|
||||
|
||||
```handlebars
|
||||
{{!-- Éditer l'image --}}
|
||||
<img data-action="editImage" src="{{item.img}}" />
|
||||
|
||||
{{!-- Poster au chat --}}
|
||||
<button data-action="postItem">
|
||||
<i class="fas fa-comment"></i>
|
||||
</button>
|
||||
```
|
||||
|
||||
### Tabs
|
||||
|
||||
```handlebars
|
||||
{{!-- Navigation --}}
|
||||
<nav class="tabs" data-group="primary">
|
||||
{{#each tabs}}
|
||||
<a data-tab="{{this.id}}" class="{{#if (eq ../activeTab this.id)}}active{{/if}}">
|
||||
{{localize this.label}}
|
||||
</a>
|
||||
{{/each}}
|
||||
</nav>
|
||||
|
||||
{{!-- Contenu --}}
|
||||
<div class="tab {{#if (eq activeTab 'description')}}active{{/if}}"
|
||||
data-tab="description">
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
### Editor
|
||||
|
||||
```handlebars
|
||||
{{!-- AppV2 avec ProseMirror --}}
|
||||
{{editor enrichedDescription
|
||||
target="system.description"
|
||||
button=true
|
||||
editable=isEditable
|
||||
engine="prosemirror"}}
|
||||
```
|
||||
|
||||
## Context disponible dans les templates
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Document & system
|
||||
fields: schema.fields,
|
||||
systemFields: system.schema.fields,
|
||||
item: document,
|
||||
system: document.system,
|
||||
source: document.toObject(),
|
||||
|
||||
// Content
|
||||
enrichedDescription: "HTML enrichi",
|
||||
category: "equipment|weapon|spell|...",
|
||||
itemProperties: ["prop1", "prop2"],
|
||||
|
||||
// Config
|
||||
config: game.bol.config,
|
||||
isGM: boolean,
|
||||
isEditable: boolean,
|
||||
|
||||
// Tabs
|
||||
tabs: [{id, label, icon}],
|
||||
activeTab: "description|properties",
|
||||
|
||||
// Type-specific (item-sheet.mjs)
|
||||
isItem: true,
|
||||
isEquipment: boolean,
|
||||
isWeapon: boolean,
|
||||
isProtection: boolean,
|
||||
isSpell: boolean,
|
||||
|
||||
// Type-specific (feature-sheet.mjs)
|
||||
isFeature: true,
|
||||
isBoon: boolean,
|
||||
isFlaw: boolean,
|
||||
isCareer: boolean,
|
||||
isOrigin: boolean,
|
||||
isRace: boolean,
|
||||
|
||||
// Optional
|
||||
careers: actor.careers // Si item sur actor
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration dans bol.js
|
||||
|
||||
```javascript
|
||||
// Import
|
||||
import * as sheets from "./applications/sheets/_module.mjs"
|
||||
|
||||
// Enregistrement
|
||||
foundry.documents.collections.Items.unregisterSheet("core", ...)
|
||||
foundry.documents.collections.Items.registerSheet("bol",
|
||||
sheets.BoLItemSheet,
|
||||
{ types: ["item"], makeDefault: true }
|
||||
)
|
||||
foundry.documents.collections.Items.registerSheet("bol",
|
||||
sheets.BoLFeatureSheet,
|
||||
{ types: ["feature"], makeDefault: true }
|
||||
)
|
||||
```
|
||||
|
||||
## Avantages de AppV2
|
||||
|
||||
1. **Performance** : Meilleur rendu et gestion des updates
|
||||
2. **Structure** : Code plus organisé et maintenable
|
||||
3. **Actions** : Système d'actions déclaratif
|
||||
4. **Context** : Préparation des données séparée du template
|
||||
5. **Standard** : Aligné sur Foundry VTT v12+
|
||||
6. **Future-proof** : Architecture pérenne
|
||||
|
||||
## Points d'attention
|
||||
|
||||
### Compatibilité
|
||||
|
||||
- Les données restent 100% compatibles
|
||||
- Seule l'interface de sheet change
|
||||
- Pas de migration de données nécessaire
|
||||
|
||||
### Tabs
|
||||
|
||||
Les tabs ne sont plus automatiques dans AppV2 :
|
||||
- Navigation manuelle avec `_activateTabs()`
|
||||
- State persistant avec `tabGroups`
|
||||
- CSS `.active` géré manuellement
|
||||
|
||||
### Editor
|
||||
|
||||
ProseMirror est maintenant le moteur par défaut :
|
||||
```handlebars
|
||||
{{editor content engine="prosemirror"}}
|
||||
```
|
||||
|
||||
### Actions
|
||||
|
||||
Système déclaratif :
|
||||
```javascript
|
||||
actions: {
|
||||
myAction: ClassName.#onMyAction
|
||||
}
|
||||
```
|
||||
|
||||
Dans le template :
|
||||
```handlebars
|
||||
<button data-action="myAction">Click</button>
|
||||
```
|
||||
|
||||
## Prochaines étapes
|
||||
|
||||
### Court terme
|
||||
1. Tester les sheets dans Foundry
|
||||
2. Vérifier toutes les fonctionnalités
|
||||
3. Ajuster les CSS si nécessaire
|
||||
|
||||
### Moyen terme
|
||||
4. Migrer les actor sheets vers AppV2
|
||||
5. Ajouter des features AppV2 (parts, etc.)
|
||||
6. Optimiser les templates
|
||||
|
||||
### Long terme
|
||||
7. Utiliser PARTS pour modularité
|
||||
8. Ajouter des actions avancées
|
||||
9. Améliorer la UX
|
||||
|
||||
## Références
|
||||
|
||||
- [Foundry AppV2 Documentation](https://foundryvtt.com/api/classes/foundry.applications.api.ApplicationV2.html)
|
||||
- [ItemSheetV2 API](https://foundryvtt.com/api/classes/foundry.applications.sheets.ItemSheetV2.html)
|
||||
- Exemples : fvtt-cthulhu-eternal, fvtt-mournblade
|
||||
41
changelog.md
41
changelog.md
@@ -1,25 +1,33 @@
|
||||
Changes :
|
||||
|
||||
# v12.1.0
|
||||
# v13.0.0
|
||||
|
||||
- Foundry v13 only
|
||||
|
||||
# v12.1.7
|
||||
|
||||
- Enhance welcome message
|
||||
|
||||
# v12.1.1
|
||||
|
||||
## 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
|
||||
@@ -39,20 +47,19 @@ Changes :
|
||||
|
||||
# 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
|
||||
|
||||
- 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
|
||||
- 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é
|
||||
|
||||
|
||||
- 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é
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"description": "<h1>Medium Armour</h1><p>Combining some of the mobility of the lighter armour and better protection of heavy armour, this is the armour worn by the typical adventurer expecting to get into combat situations on a regular basis. Medium armour could represent fairly extensive coverage of leather armour, with stiffened leather in some of the more vital areas, or partial coverage of mail with leather in other areas. It could even represent a steel breastplate and minimal/no other armour.</p><p>Someone in medium armour can often remove portions of their armour to reduce it to light armour, as necessary.</p><h2>Medium armour effects</h2><ul><li>Roll a d6-2 (0-4 points of damage reduction).</li><li>If you prefer static numbers, medium armour absorbs 2 points of damage.</li><li>Wearing medium armour restricts magicians and imposes an extra 2 Arcane Points cost on a spell casting.</li></ul>"
|
||||
},
|
||||
"Casque": {
|
||||
"name": "Casque",
|
||||
"name": "Helmet",
|
||||
"description": "<h1>Helmet</h1><p>If you are wearing a helmet, this adds +1 to your protection if already wearing armour. Therefore, if in light armour and helmet, you’d roll d6-2. In medium armour, roll d6-1. In heavy armour, roll d6.</p><p>Helmets give you a penalty in social situations and to your initiative (as it’s harder to notice things whilst wearing a helmet).</p><p>Most Heroes take their helmets off, unless preparing for battle.</p>"
|
||||
},
|
||||
"Grand bouclier": {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"description": ""
|
||||
},
|
||||
"Esprit -1": {
|
||||
"name": "Miond -1",
|
||||
"name": "Mind -1",
|
||||
"description": ""
|
||||
},
|
||||
"Vigueur -1": {
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
},
|
||||
"Traqué": {
|
||||
"name": "Hunted",
|
||||
"description": "<h1>Hunted</h1><p>Your character is ridiculously tight- lipped. It’s a rare day on which he uses a sentence of more than three words, and it’s virtually unheard of for him to initiate conversation. His extreme reluctance to speak unfortunately means he never volunteers information without being asked. Take a penalty die in social situations.</p>"
|
||||
"description": "<h1>Hunted</h1><p>Perhaps you are wanted by the authorities, or have offended some powerful noble or pirate king. Regardless of whom, you constantly have to evade agents intent on capturing or even killing you. Roll a d6 whenever you enter a new city. On a 1, agents of your enemy (or your enemy himself, if you choose) will spot you and make your life unpleasant.</p>"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,8 +74,8 @@
|
||||
"description": "<h1>Shamballah</h1><p>Shamballahns are generally a dark-skinned and dark-haired people with purple, mauve, scarlet, and indigo eye colouring. They are very perceptive and make good hunters.</p>"
|
||||
},
|
||||
"Terres Désolées": {
|
||||
"name": "Terres Désolées",
|
||||
"description": "<h1>Terres Désolées</h1><p>Personne ne sait grand-chose au sujet des Terres Désolées, et moins encore sur les contrées qui s’étendraient au-delà. Des gens vivent assurément dans cette région, s’il faut en croire les récits de chasseurs et d’explorateurs qui ont relevé des traces de présence. Mais à ce jour, personne n’a découvert le moindre village ou hameau, et on ignore tout de l’apparence de leurs habitants.</p><p>Si votre héros est originaire des Terres Désolées, il vous faudra travailler avec le MJ pour déterminer à quoi ressemble votre personnage. Mais attendezvous à ce qu’il soit toujours considéré comme un étranger, où qu’il se rende en Lémurie.</p>"
|
||||
"name": "Empty Lands",
|
||||
"description": "<h1>Empty Lands</h1><p>No one knows what exists in and beyond the Empty Lands. People do live there, because hunters and explorers have seen evidence of them. However, no towns or even villages have been discovered, and no one has any idea of what the people are like. If you come from the Empty Lands, you will need to work with the GM to determine what your character is like. He or she will always be treated as an outsider.</p>"
|
||||
},
|
||||
"Tyrus": {
|
||||
"name": "Tyrus",
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
"description": "<h1>Staff Sling</h1><p>The staff sling is a two-handed version of the sling, with a longer range.</p>"
|
||||
},
|
||||
"Cimeterre": {
|
||||
"name": "Cimeterre",
|
||||
"description": "<h1>Épée</h1><p>l’arme favorite des héros. Elle se décline en différents modèles utilisés un peu partout en Lémurie, comme les sabres d’abordage, les tulwars, les cimeterres ou les épées longues. Inscrivez le nom de l’arme que vous voulez sur la fiche de votre personnage en fonction de l’image que vous vous faites de ce dernier. Mais au final, une épée reste une longue lame utilisée pour tuer l’ennemi.</p>"
|
||||
"name": "Scimitar",
|
||||
"description": "<h1>Scimitar (Sword)</h1><p>This weapon is a favourite amongst Heroes. This is the catch-all description for all manner of long-bladed, one-handed weapons used all over Lemuria, such as cutlasses, tulwars, scimitars, rapiers, broadswords and longswords. Call it what you want on your character sheet, because that will add flavour to your character, but at the end of the day a sword is a long blade used for killing.</p>"
|
||||
},
|
||||
"Dague": {
|
||||
"name": "Dagger",
|
||||
@@ -123,19 +123,19 @@
|
||||
},
|
||||
"Masse d’armes": {
|
||||
"name": "Mace",
|
||||
"description": "<h1>Mace</h1><p>cA mace is similar to a club, but with a metal head, often with spikes or flanges. One-handed maces can be thrown at increments of 5’ as they aren’t very effective used this way.</p>"
|
||||
"description": "<h1>Mace</h1><p>A mace is similar to a club, but with a metal head, often with spikes or flanges. One-handed maces can be thrown at increments of 5’ as they aren’t very effective used this way.</p>"
|
||||
},
|
||||
"Masse d’armes (Lancer)": {
|
||||
"name": "Masse d’armes (Lancer)",
|
||||
"description": "<h1>Masse d’armes</h1><p>cette arme a la même forme qu’un gourdin, mais possède une tête en métal, souvent agrémentée de pointes ou d’ailettes pour plus d’efficacité. Les masses d’armes à une main peuvent se lancer, mais à courte distance, car elles ne sont pas vraiment prévues pour cet usage.</p>"
|
||||
"name": "Mace (Thrown)",
|
||||
"description": "<h1>Mace</h1><p>A mace is similar to a club, but with a metal head, often with spikes or flanges. One-handed maces can be thrown at increments of 5’ as they aren’t very effective used this way.</p>"
|
||||
},
|
||||
"Massue": {
|
||||
"name": "Massue",
|
||||
"description": "<h1>Massue</h1><p>la version lourde du gourdin. Une massue consiste en un solide manche en bois dont l’extrémité, plus volumineuse, sert à fracasser le crâne de ses adversaires, d’où son autre nom de casse-tête.</p>"
|
||||
"name": "Club",
|
||||
"description": "<h1>Club</h1><p>This is a larger version of the cudgel. It is a stout length of wood, used in one hand to bludgeon and batter your opponent. Clubs usually have a wider or knobbed head and can be called war-clubs, knobkerries, or shillelaghs.</p>"
|
||||
},
|
||||
"Massue (Lancer)": {
|
||||
"name": "Massue (Lancer)",
|
||||
"description": "<h1>Massue</h1><p>la version lourde du gourdin. Une massue consiste en un solide manche en bois dont l’extrémité, plus volumineuse, sert à fracasser le crâne de ses adversaires, d’où son autre nom de casse-tête.</p>"
|
||||
"name": "Club (Thrown)",
|
||||
"description": "<h1>Club</h1><p>This is a larger version of the cudgel. It is a stout length of wood, used in one hand to bludgeon and batter your opponent. Clubs usually have a wider or knobbed head and can be called war-clubs, knobkerries, or shillelaghs.</p>"
|
||||
},
|
||||
"Morgenstern": {
|
||||
"name": "Morning Star",
|
||||
|
||||
2001
css/bol.css
2001
css/bol.css
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
||||
[Dolphin]
|
||||
Timestamp=2024,11,2,20,30,2.2800000000000002
|
||||
Version=4
|
||||
ViewMode=1
|
||||
VisibleRoles=Details_text,Details_size,Details_modificationtime,Details_creationtime,CustomizedDetails
|
||||
28
lang/de.json
28
lang/de.json
@@ -111,7 +111,7 @@
|
||||
"BOL.ui.defender": "Verteidiger",
|
||||
"BOL.ui.difficulty": "Schwierigkeit",
|
||||
"BOL.ui.spellProperties": "Zaubereigenschaften",
|
||||
"BOL.ui.duration": "Dauer",
|
||||
"BOL.ui.duration": "Dauer",
|
||||
"BOL.ui.spellkeep": "Aufrechterhalten",
|
||||
"BOL.ui.concentrate": "Konzentrieren",
|
||||
"BOL.ui.registerInit": "Register Init.",
|
||||
@@ -134,7 +134,7 @@
|
||||
"BOL.ui.makeAlchemy": "Alchemika herstellen",
|
||||
"BOL.ui.alchemyCostTotal": "Alchemiepunkte ingesamt",
|
||||
"BOL.ui.alchemyInvest": "Alchemiepunkte investieren",
|
||||
"BOL.ui.alchemyCurrent": "Aktuelle Alchemiepunkte in Objekten",
|
||||
"BOL.ui.alchemyCurrent": "Aktuelle Alchemiepunkte in Objekten",
|
||||
"BOL.ui.advance": "Status",
|
||||
"BOL.ui.isadvantage": "Gibt zusätzlichen Würfel?",
|
||||
"BOL.ui.isbonusdice": "Gibt zusätzlichen Würfel?",
|
||||
@@ -153,8 +153,8 @@
|
||||
"BOL.ui.status": "Status",
|
||||
"BOL.ui.toactivated": "Aktiv (>Deaktivieren)",
|
||||
"BOL.ui.todeactivated": "Inaktiv (>Aktivieren)",
|
||||
"BOL.ui.armorAgiMalus": "Rüschtung+Schild-Malus (Geschick)",
|
||||
"BOL.ui.armorInitMalus": "Rüstungsmalus (Init)",
|
||||
"BOL.ui.armorAgiMalus": "Rüschtung+Schild-Malus (Geschick)",
|
||||
"BOL.ui.armorInitMalus": "Rüstungsmalus (Init)",
|
||||
"BOL.ui.attackValue": "Angriffswert",
|
||||
"BOL.ui.initMalus": "Init malus",
|
||||
"BOL.ui.createEquipment": "Create Equipment",
|
||||
@@ -177,7 +177,7 @@
|
||||
"BOL.featureSubtypes.fightOption": "Kampfoption",
|
||||
|
||||
"BOL.bougette.nomoney": "Mittellos",
|
||||
"BOL.bougette.tolive": "Zum Überleben",
|
||||
"BOL.bougette.tolive": "Zum Überleben",
|
||||
"BOL.bougette.easylife": "Einfaches Leben",
|
||||
"BOL.bougette.luxury" : "Luxuriöses Leben",
|
||||
"BOL.bougette.rich": "Reich!",
|
||||
@@ -224,14 +224,14 @@
|
||||
"BOL.protectionCategory.other": "Verschiedenes",
|
||||
|
||||
"BOL.spellItem.charm": "Zauber",
|
||||
"BOL.spellItem.circle1": "Erster Kreis",
|
||||
"BOL.spellItem.circle2": "Zweiter Kreis",
|
||||
"BOL.spellItem.circle3": "Dritter Kreis",
|
||||
"BOL.spellItem.circle1": "Erster Kreis",
|
||||
"BOL.spellItem.circle2": "Zweiter Kreis",
|
||||
"BOL.spellItem.circle3": "Dritter Kreis",
|
||||
|
||||
"BOL.alchemyItem.common": "Häufig",
|
||||
"BOL.alchemyItem.scarce": "Selten",
|
||||
"BOL.alchemyItem.legend": "Legendär",
|
||||
"BOL.alchemyItem.mythic": "Mystisch",
|
||||
"BOL.alchemyItem.common": "Häufig",
|
||||
"BOL.alchemyItem.scarce": "Selten",
|
||||
"BOL.alchemyItem.legend": "Legendär",
|
||||
"BOL.alchemyItem.mythic": "Mystisch",
|
||||
|
||||
"BOL.weaponCategory.melee": "Nahkampf",
|
||||
"BOL.weaponCategory.ranged": "Fernkampf",
|
||||
@@ -290,6 +290,7 @@
|
||||
"BOL.itemProperty.difficulty": "Schwierigkeit",
|
||||
"BOL.itemProperty.natural": "Natürliche Waffe",
|
||||
"BOL.itemProperty.onlymodifier": "Nur Modifikator (d.h. Angriffe von Kreaturen)",
|
||||
"BOL.itemProperty.attackMalusDice": "Angriffsmalus (Würfel)",
|
||||
|
||||
"BOL.itemStat.quantity": "Anzahl",
|
||||
"BOL.itemStat.weight": "Gewicht",
|
||||
@@ -359,7 +360,7 @@
|
||||
"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.answer": "Réponse",
|
||||
"BOL.ui.horoscopefavorable": "Favorable (1dB)",
|
||||
"BOL.ui.horoscopeunfavorable": "Défavorable (1dM)",
|
||||
"BOL.ui.horoscopes": "Horoscopes",
|
||||
@@ -468,6 +469,7 @@
|
||||
"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.welcome6": "",
|
||||
"BOL.chat.bolRulebookMessage": "Don't miss the full Rulebook module (including Sagas) available at : https://www.ludospherik-editions.com/en_gb/ !",
|
||||
|
||||
"BOL.settings.rollArmor": "Roll for armor",
|
||||
"BOL.settings.rollArmorTooltip": "Roll for armor value, fixed value if unchecked",
|
||||
|
||||
55
lang/en.json
55
lang/en.json
@@ -47,7 +47,7 @@
|
||||
"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.answer": "Réponse",
|
||||
"BOL.ui.horoscopefavorable": "Favorable (1dB)",
|
||||
"BOL.ui.horoscopeunfavorable": "Défavorable (1dM)",
|
||||
"BOL.ui.horoscopes": "Horoscopes",
|
||||
@@ -132,7 +132,7 @@
|
||||
"BOL.ui.defender": "Defender",
|
||||
"BOL.ui.difficulty": "Difficulty",
|
||||
"BOL.ui.spellProperties": "Spell Properties",
|
||||
"BOL.ui.duration": "Duration",
|
||||
"BOL.ui.duration": "Duration",
|
||||
"BOL.ui.spellkeep": "Maintain",
|
||||
"BOL.ui.concentrate": "Concentrate",
|
||||
"BOL.ui.registerInit": "Register Init.",
|
||||
@@ -156,7 +156,7 @@
|
||||
"BOL.ui.makeAlchemy": "Make Alchemy",
|
||||
"BOL.ui.alchemyCostTotal": "Alchemy Points Total Cost",
|
||||
"BOL.ui.alchemyInvest": "Invest Alchemy Points",
|
||||
"BOL.ui.alchemyCurrent": "Current Alchemy Points in Object",
|
||||
"BOL.ui.alchemyCurrent": "Current Alchemy Points in Object",
|
||||
"BOL.ui.advance": "Status",
|
||||
"BOL.ui.isadvantage": "Provides a bonus dice?",
|
||||
"BOL.ui.bonusmalus": "Additional bonus/penalty",
|
||||
@@ -173,8 +173,8 @@
|
||||
"BOL.ui.status": "Status",
|
||||
"BOL.ui.toactivated": "Active (>Deactivated)",
|
||||
"BOL.ui.todeactivated": "Inactive (>Active)",
|
||||
"BOL.ui.armorAgiMalus": "Armor+Shield Modifier (Agi)",
|
||||
"BOL.ui.armorInitMalus": "Armor Modifier (Init)",
|
||||
"BOL.ui.armorAgiMalus": "Armor+Shield Modifier (Agi)",
|
||||
"BOL.ui.armorInitMalus": "Armor Modifier (Init)",
|
||||
"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)",
|
||||
@@ -251,7 +251,7 @@
|
||||
"BOL.featureSubtypes.xplog": "XP Journal",
|
||||
|
||||
"BOL.bougette.nomoney": "Nothing",
|
||||
"BOL.bougette.tolive": "To live",
|
||||
"BOL.bougette.tolive": "To live",
|
||||
"BOL.bougette.easylife": "Easy Life",
|
||||
"BOL.bougette.luxury" : "Luxury life",
|
||||
"BOL.bougette.rich": "Rich!",
|
||||
@@ -299,15 +299,15 @@
|
||||
"BOL.protectionCategory.helm": "Helm",
|
||||
"BOL.protectionCategory.other": "Other",
|
||||
|
||||
"BOL.spellItem.charm": "Charm",
|
||||
"BOL.spellItem.circle1": "First Circle",
|
||||
"BOL.spellItem.circle2": "Second Circle",
|
||||
"BOL.spellItem.circle3": "Third Circle",
|
||||
"BOL.spellItem.charm": "Charm",
|
||||
"BOL.spellItem.circle1": "First Circle",
|
||||
"BOL.spellItem.circle2": "Second Circle",
|
||||
"BOL.spellItem.circle3": "Third Circle",
|
||||
|
||||
"BOL.alchemyItem.common": "Common",
|
||||
"BOL.alchemyItem.scarce": "Scarce",
|
||||
"BOL.alchemyItem.legend": "Legendary",
|
||||
"BOL.alchemyItem.mythic": "Mythic",
|
||||
"BOL.alchemyItem.common": "Common",
|
||||
"BOL.alchemyItem.scarce": "Scarce",
|
||||
"BOL.alchemyItem.legend": "Legendary",
|
||||
"BOL.alchemyItem.mythic": "Mythic",
|
||||
|
||||
"BOL.weaponCategory.melee": "Melee",
|
||||
"BOL.weaponCategory.ranged": "Ranged",
|
||||
@@ -365,6 +365,7 @@
|
||||
"BOL.itemProperty.difficulty": "Difficulty",
|
||||
"BOL.itemProperty.natural": "Natural weapon",
|
||||
"BOL.itemProperty.onlymodifier": "Modifier only (ie creatures attacks)",
|
||||
"BOL.itemProperty.attackMalusDice": "Attack Malus (Dice)",
|
||||
|
||||
"BOL.itemStat.quantity": "Quantity",
|
||||
"BOL.itemStat.weight": "Weight",
|
||||
@@ -458,7 +459,7 @@
|
||||
"BOL.size.colossal": "Colossal",
|
||||
|
||||
"BOL.chat.fightactive": "{name} activates the fight option {foName} for this round !",
|
||||
"BOL.chat.fightunactive": "{name} deactivates the fight option {foName} for this round !",
|
||||
"BOL.chat.fightunactive": "{name} deactivates the fight option {foName} for this round !",
|
||||
"BOL.chat.isdead": "{name} is dead !",
|
||||
"BOL.chat.epitaph": "Keep his name and memory in honor !",
|
||||
"BOL.chat.vitalityzero": "Lifeblood of {name} is now {hp} : he is going to fall unconscious !",
|
||||
@@ -543,17 +544,24 @@
|
||||
"BOL.chat.criticalbuttonjournal": "Legendary/Heroic Success",
|
||||
"BOL.chat.nodamage": "Do not apply damages",
|
||||
"BOL.chat.armorRoll": "Armor roll",
|
||||
"BOL.chat.bolRulebookMessage": "Don't miss the full Rulebook module (including Sagas) available at : https://www.ludospherik-editions.com/en_gb/ !",
|
||||
|
||||
"BOL.dialog.soeasy": "So easy (+4)",
|
||||
"BOL.dialog.soeasy3": "So easy (+3)",
|
||||
"BOL.dialog.veryeasy": "Very easy (+2)",
|
||||
"BOL.dialog.easy": "Easy (+1)",
|
||||
"BOL.dialog.moderate": "Moderate (0)",
|
||||
"BOL.dialog.hard": "Hard (-1)",
|
||||
"BOL.dialog.tough": "Tough (-2)",
|
||||
"BOL.dialog.tough3": "Tough (-3)",
|
||||
"BOL.dialog.demanding": "Demanding (-4)",
|
||||
"BOL.dialog.demanding5": "Demanding (-5)",
|
||||
"BOL.dialog.formidable": "Formidable (-6)",
|
||||
"BOL.dialog.formidable7": "Formidable (-7)",
|
||||
"BOL.dialog.heroic": "Heroic (-8)",
|
||||
"BOL.dialog.heroic9": "Heroic (-9)",
|
||||
"BOL.dialog.mythic": "Mythic (-10)",
|
||||
"BOL.dialog.mythic11": "Mythic (-11)",
|
||||
"BOL.dialog.divine": "Divine (-12)",
|
||||
|
||||
"BOL.dialog.pointblank": "Point blank (+1)",
|
||||
@@ -562,7 +570,7 @@
|
||||
"BOL.dialog.long": "Long (-2)",
|
||||
"BOL.dialog.distant": "Distant (-4)",
|
||||
"BOL.dialog.extreme": "Extreme (-6)",
|
||||
"BOL.dialog.utmost": "Utmost (-8)",
|
||||
"BOL.dialog.utmost": "Utmost (-8)",
|
||||
|
||||
"BOL.ui.name": "Name",
|
||||
"BOL.ui.xp": "Experience",
|
||||
@@ -578,11 +586,11 @@
|
||||
"BOL.ui.bionotes": "Notes",
|
||||
|
||||
"BOL.chat.welcome1": "Welcome to Barbarians of Lemuria (Ludospherik version)",
|
||||
"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.welcome2": "Books are necessary to play, and <a href='http://www.ludospherik.fr/content/14-barbarians-of-lemuria'>can be found here.</a> ",
|
||||
"BOL.chat.welcome3": "The integrated maps are authorized by Emmanuel Roudier 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.welcome5": "Good game in Lemuria !",
|
||||
"BOL.chat.welcome6": "",
|
||||
"BOL.chat.welcome5": "<strong>In order to see compendiums in English, you must install and enable the Babele module.</strong>",
|
||||
"BOL.chat.welcome6": "Good game in Lemuria !",
|
||||
|
||||
"BOL.settings.rollArmor": "Roll for armor",
|
||||
"BOL.settings.rollArmorTooltip": "Roll for armor value, fixed value if unchecked",
|
||||
@@ -601,5 +609,10 @@
|
||||
"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)"
|
||||
"BOL.settings.defaultLogoTopLeftPathTooltip": "Path of the logo in the top left window (718 x 416, default : /systems/bol/ui/logo2.webp)",
|
||||
|
||||
"BOL.ui.charSummaryTitle": "Character Summary",
|
||||
"BOL.ui.colGroupAttributes": "Attributes",
|
||||
"BOL.ui.colGroupAptitudes": "Aptitudes",
|
||||
"BOL.ui.colGroupResources": "Resources"
|
||||
}
|
||||
28
lang/es.json
28
lang/es.json
@@ -132,7 +132,7 @@
|
||||
"BOL.ui.defender": "Defensor",
|
||||
"BOL.ui.difficulty": "Dificultad",
|
||||
"BOL.ui.spellProperties": "Propiedades Conjuro",
|
||||
"BOL.ui.duration": "Duración",
|
||||
"BOL.ui.duration": "Duración",
|
||||
"BOL.ui.spellkeep": "Mantenimiento",
|
||||
"BOL.ui.concentrate": "Concentración",
|
||||
"BOL.ui.registerInit": "Registrar Inic.",
|
||||
@@ -156,7 +156,7 @@
|
||||
"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.alchemyCurrent": "Puntos Alquimia actuales en Objeto",
|
||||
"BOL.ui.advance": "Estado",
|
||||
"BOL.ui.isadvantage": "¿Da un dado ventaja?",
|
||||
"BOL.ui.bonusmalus": "Ventaja/desventaja adicional",
|
||||
@@ -245,7 +245,7 @@
|
||||
"BOL.featureSubtypes.xplog": "Diario PX",
|
||||
|
||||
"BOL.bougette.nomoney": "Nada",
|
||||
"BOL.bougette.tolive": "Vivir justo",
|
||||
"BOL.bougette.tolive": "Vivir justo",
|
||||
"BOL.bougette.easylife": "Vida simple",
|
||||
"BOL.bougette.luxury" : "Vida lujosa",
|
||||
"BOL.bougette.rich": "¡Rico!",
|
||||
@@ -293,15 +293,15 @@
|
||||
"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.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.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",
|
||||
@@ -359,6 +359,7 @@
|
||||
"BOL.itemProperty.difficulty": "Dificultad",
|
||||
"BOL.itemProperty.natural": "Arma natural",
|
||||
"BOL.itemProperty.onlymodifier": "Sólo modificador (ej criatura)",
|
||||
"BOL.itemProperty.attackMalusDice": "Dado Desventaja Ataque",
|
||||
|
||||
"BOL.itemStat.quantity": "Cantidad",
|
||||
"BOL.itemStat.weight": "Peso",
|
||||
@@ -452,7 +453,7 @@
|
||||
"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.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!",
|
||||
@@ -534,6 +535,7 @@
|
||||
"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.chat.bolRulebookMessage": "Don't miss the full Rulebook module (including Sagas) available at : https://www.ludospherik-editions.com/en_gb/ !",
|
||||
|
||||
"BOL.dialog.soeasy": "Demasiado fácil (+4)",
|
||||
"BOL.dialog.veryeasy": "Muy fácil (+2)",
|
||||
@@ -553,7 +555,7 @@
|
||||
"BOL.dialog.long": "Larga (-2)",
|
||||
"BOL.dialog.distant": "Distante (-4)",
|
||||
"BOL.dialog.extreme": "Extrema (-6)",
|
||||
"BOL.dialog.utmost": "Límite (-8)",
|
||||
"BOL.dialog.utmost": "Límite (-8)",
|
||||
|
||||
"BOL.ui.name": "Nombre",
|
||||
"BOL.ui.xp": "Experiencia",
|
||||
|
||||
39
lang/fr.json
39
lang/fr.json
@@ -50,7 +50,7 @@
|
||||
"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.answer": "Réponse",
|
||||
"BOL.ui.horoscopefavorable": "Favorable (1dB)",
|
||||
"BOL.ui.horoscopeunfavorable": "Défavorable (1dM)",
|
||||
"BOL.ui.horoscopes": "Horoscopes",
|
||||
@@ -137,7 +137,7 @@
|
||||
"BOL.ui.duration": "Durée",
|
||||
"BOL.ui.spellkeep": "Prolongation possible ?",
|
||||
"BOL.ui.concentrate": "Concentration à maintenir ?",
|
||||
"BOL.ui.aggressive": "Sort aggressif ?",
|
||||
"BOL.ui.aggressive": "Sort aggressif ?",
|
||||
"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!)",
|
||||
@@ -147,7 +147,7 @@
|
||||
"BOL.ui.flaw":"Désanvatage",
|
||||
"BOL.ui.cost":"Cout XP",
|
||||
"BOL.ui.date":"Date",
|
||||
|
||||
|
||||
"BOL.ui.isSorcerer": "Carrière de Sorcier ?",
|
||||
"BOL.ui.isAlchemist": "Carrière d'Alchimiste ?",
|
||||
"BOL.ui.isPriest": "Carrière de Prêtre/Druide ?",
|
||||
@@ -259,7 +259,7 @@
|
||||
"BOL.bougette.easylife": "A l'aise",
|
||||
"BOL.bougette.luxury": "Luxe&Volupté",
|
||||
"BOL.bougette.rich": "Richissime",
|
||||
|
||||
|
||||
"BOL.featureSubtypes.origin": "Origine",
|
||||
"BOL.featureSubtypes.race": "Race",
|
||||
"BOL.featureSubtypes.career": "Carrière",
|
||||
@@ -393,8 +393,9 @@
|
||||
"BOL.itemProperty.crewDamageMultiplier": "Multiplicateur",
|
||||
"BOL.itemProperty.isboarding": "Abordage",
|
||||
"BOL.itemProperty.isspur": "Eperonnage",
|
||||
"BOL.itemProperty.isbreakrow": "Briser les rames",
|
||||
|
||||
"BOL.itemProperty.isbreakrow": "Briser les rames",
|
||||
"BOL.itemProperty.attackMalusDice": "Malus d'attaque (Dés)",
|
||||
|
||||
"BOL.itemStat.quantity": "Quantité",
|
||||
"BOL.itemStat.weight": "Poids",
|
||||
"BOL.itemStat.price": "Prix",
|
||||
@@ -486,7 +487,7 @@
|
||||
"BOL.size.colossal": "Monstrueuse",
|
||||
|
||||
"BOL.chat.fightactive": "{name} active son option de combat {foName} pour ce round !",
|
||||
"BOL.chat.fightunactive": "{name} désactive son option de combat {foName} pour ce round !",
|
||||
"BOL.chat.fightunactive": "{name} désactive son option de combat {foName} pour ce round !",
|
||||
"BOL.chat.isdead": "{name} est mort !",
|
||||
"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 !",
|
||||
@@ -569,21 +570,29 @@
|
||||
"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.bolRulebookMessage": "N'oubliez pas le module complet du Livre de Règle et des Sagas disponible ici : https://www.ludospherik-editions.com !",
|
||||
"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.chat.defenseReduceDamage2": "Vous pouvez également dépenser 1 Point d'Héroisme/Vilainie pour regagner [[/r 2d6KH(1D6B)]] points de vitalité, cela vous coutera votre prochaine action.",
|
||||
"BOL.chat.armorRoll": "Jet d'armure ",
|
||||
|
||||
"BOL.dialog.soeasy": "Inmanquable (+4)",
|
||||
"BOL.dialog.soeasy3": "Inmanquable (+3)",
|
||||
"BOL.dialog.veryeasy": "Trés Facile (+2)",
|
||||
"BOL.dialog.easy": "Facile (+1)",
|
||||
"BOL.dialog.moderate": "Moyenne (0)",
|
||||
"BOL.dialog.hard": "Ardue (-1)",
|
||||
"BOL.dialog.tough": "Difficile (-2)",
|
||||
"BOL.dialog.tough3": "Difficile (-3)",
|
||||
"BOL.dialog.demanding": "Très Difficile (-4)",
|
||||
"BOL.dialog.demanding5": "Très Difficile (-5)",
|
||||
"BOL.dialog.formidable": "Impossible (-6)",
|
||||
"BOL.dialog.formidable7": "Impossible (-7)",
|
||||
"BOL.dialog.heroic": "Héroïque (-8)",
|
||||
"BOL.dialog.heroic9": "Héroïque (-9)",
|
||||
"BOL.dialog.mythic": "Mythique (-10)",
|
||||
"BOL.dialog.mythic11": "Mythique (-11)",
|
||||
"BOL.dialog.divine": "Divine (-12)",
|
||||
|
||||
"BOL.dialog.pointblank": "Bout portant (+1)",
|
||||
@@ -611,16 +620,15 @@
|
||||
|
||||
"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 <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 d'Emmanuel Roudier et des éditions Ludospherik. Merci à eux !.",
|
||||
"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": "Consulter l'aide en ligne pour plus d'informations : @UUID[Compendium.bol.aides-de-jeu.JournalEntry.8ihDiCxC47fcdKVA]{Aide du Jeu}.",
|
||||
"BOL.chat.welcome5": "Consulter l'aide en ligne pour plus d'informations : @UUID[Compendium.bol.aides-de-jeu.JournalEntry.8ihDiCxC47fcdKVA]{Aide du Jeu}.<br>Si vous souhaitez jouer en anglais, n'oubliez pas d'activer le module Babele.",
|
||||
"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é)",
|
||||
@@ -642,5 +650,10 @@
|
||||
"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"
|
||||
}
|
||||
"EFFECT.StatusDead": "Mort",
|
||||
|
||||
"BOL.ui.charSummaryTitle": "Résumé des Personnages",
|
||||
"BOL.ui.colGroupAttributes": "Attributs",
|
||||
"BOL.ui.colGroupAptitudes": "Aptitudes",
|
||||
"BOL.ui.colGroupResources": "Ressources"
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
import { BoLRoll } from "../controllers/bol-rolls.js";
|
||||
import { BoLUtility } from "../system/bol-utility.js";
|
||||
|
||||
export class BoLActorSheet extends ActorSheet {
|
||||
export class BoLActorSheet extends foundry.appv1.sheets.ActorSheet {
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
@@ -59,7 +59,7 @@ export class BoLActorSheet extends ActorSheet {
|
||||
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) => {
|
||||
const li = $(ev.currentTarget).parents(".item")
|
||||
this.actor.toggleFightOption(li.data("itemId"))
|
||||
@@ -170,8 +170,8 @@ export class BoLActorSheet extends ActorSheet {
|
||||
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.biography = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.details?.biography || "", { async: true })
|
||||
formData.notes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.details.notes || "", { async: true })
|
||||
formData.isSorcerer = this.actor.isSorcerer()
|
||||
formData.isAlchemist = this.actor.isAlchemist()
|
||||
formData.isAstrologer = this.actor.isAstrologer()
|
||||
|
||||
@@ -7,6 +7,8 @@ import { BoLUtility } from "../system/bol-utility.js";
|
||||
*/
|
||||
export class BoLActor extends Actor {
|
||||
|
||||
static _healthLock = new Set()
|
||||
|
||||
static async create(data, options) {
|
||||
|
||||
// Case of compendium global import
|
||||
@@ -22,6 +24,9 @@ export class BoLActor extends Actor {
|
||||
if (data.type == 'encounter') {
|
||||
data.system = { resources: { hero : { max : 0, value: 0 } } }
|
||||
}
|
||||
if (data.type == 'character') {
|
||||
data.system = { resources: { hp : { max : 10, value: 10 } } }
|
||||
}
|
||||
|
||||
if (data.type == 'horde') {
|
||||
let weapon = {
|
||||
@@ -161,12 +166,16 @@ export class BoLActor extends Actor {
|
||||
let newVitality = 10 + this.system.attributes.vigor.value + this.system.resources.hp.bonus
|
||||
if (this.system.resources.hp.max != newVitality) {
|
||||
let actor = this
|
||||
setTimeout(function () { actor.update({ 'system.resources.hp.max': newVitality }) }, 800)
|
||||
let newHP = foundry.utils.duplicate(this.system.resources.hp)
|
||||
newHP.max = newVitality
|
||||
setTimeout(function () { actor.update({ 'system.resources.hp': newHP }) }, 800)
|
||||
}
|
||||
let newPower = 10 + this.system.attributes.mind.value + this.system.resources.power.bonus
|
||||
if (this.system.resources.power.max != newPower) {
|
||||
let maxPower = 10 + this.system.attributes.mind.value + this.system.resources.power.bonus
|
||||
if (this.system.resources.power.max != maxPower) {
|
||||
let actor = this
|
||||
setTimeout(function () { actor.update({ 'system.resources.power.max': newPower }) }, 800)
|
||||
let newPower = foundry.utils.duplicate(this.system.resources.power)
|
||||
newPower.max = maxPower
|
||||
setTimeout(function () { actor.update({ 'system.resources.power': newPower }) }, 800)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -350,7 +359,7 @@ export class BoLActor extends Actor {
|
||||
ChatMessage.create({
|
||||
alias: this.name,
|
||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
|
||||
content: await renderTemplate('systems/bol/templates/chat/chat-activate-fight-option.hbs', { name: this.name, img: fightOption.img, foName: fightOption.name, state: state })
|
||||
content: await foundry.applications.handlebars.foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/chat-activate-fight-option.hbs', { name: this.name, img: fightOption.img, foName: fightOption.name, state: state })
|
||||
})
|
||||
|
||||
}
|
||||
@@ -845,36 +854,42 @@ export class BoLActor extends Actor {
|
||||
|
||||
/*-------------------------------------------- */
|
||||
async manageHealthState() {
|
||||
let hpID = "lastHP" + this.id
|
||||
let lastHP = await this.getFlag("world", hpID)
|
||||
if (lastHP != this.system.resources.hp.value && game.user.isGM) { // Only GM sends this
|
||||
await this.setFlag("world", hpID, this.system.resources.hp.value)
|
||||
let prone = this.effects.find(ef => ef.name == game.i18n.localize("EFFECT.StatusProne"))
|
||||
let dead = this.effects.find(ef => ef.name == game.i18n.localize("EFFECT.StatusDead"))
|
||||
if (this.system.resources.hp.value <= 0) {
|
||||
if (!prone) {
|
||||
await this.createEmbeddedDocuments("ActiveEffect", [
|
||||
{ name: game.i18n.localize('EFFECT.StatusProne'), icon: 'icons/svg/falling.svg', statuses: 'prone' }
|
||||
])
|
||||
}
|
||||
if (this.system.resources.hp.value < -5 && !dead) {
|
||||
await this.createEmbeddedDocuments("ActiveEffect", [
|
||||
{ name: game.i18n.localize('EFFECT.StatusDead'), icon: 'icons/svg/skull.svg', statuses: 'dead' }
|
||||
])
|
||||
}
|
||||
ChatMessage.create({
|
||||
alias: this.name,
|
||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
|
||||
content: await renderTemplate('systems/bol/templates/chat/chat-vitality-zero.hbs', { name: this.name, img: this.img, hp: this.system.resources.hp.value, isHeroAdversary: this.isHeroAdversary() })
|
||||
})
|
||||
} else {
|
||||
if (prone) {
|
||||
await this.deleteEmbeddedDocuments("ActiveEffect", [prone.id])
|
||||
}
|
||||
if (dead) {
|
||||
await this.deleteEmbeddedDocuments("ActiveEffect", [dead.id])
|
||||
if (BoLActor._healthLock.has(this.id)) return
|
||||
BoLActor._healthLock.add(this.id)
|
||||
try {
|
||||
let hpID = "lastHP" + this.id
|
||||
let lastHP = await this.getFlag("world", hpID)
|
||||
if (lastHP != this.system.resources.hp.value && game.user.isGM) { // Only GM sends this
|
||||
await this.setFlag("world", hpID, this.system.resources.hp.value)
|
||||
let prone = this.effects.find(ef => ef.name == game.i18n.localize("EFFECT.StatusProne"))
|
||||
let dead = this.effects.find(ef => ef.name == game.i18n.localize("EFFECT.StatusDead"))
|
||||
if (this.system.resources.hp.value <= 0) {
|
||||
if (!prone) {
|
||||
await this.createEmbeddedDocuments("ActiveEffect", [
|
||||
{ name: game.i18n.localize('EFFECT.StatusProne'), icon: 'icons/svg/falling.svg', statuses: 'prone' }
|
||||
])
|
||||
}
|
||||
if (this.system.resources.hp.value < -5 && !dead) {
|
||||
await this.createEmbeddedDocuments("ActiveEffect", [
|
||||
{ name: game.i18n.localize('EFFECT.StatusDead'), icon: 'icons/svg/skull.svg', statuses: 'dead' }
|
||||
])
|
||||
}
|
||||
ChatMessage.create({
|
||||
alias: this.name,
|
||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
|
||||
content: await foundry.applications.handlebars.foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/chat-vitality-zero.hbs', { name: this.name, img: this.img, hp: this.system.resources.hp.value, isHeroAdversary: this.isHeroAdversary() })
|
||||
})
|
||||
} else {
|
||||
if (prone) {
|
||||
await this.deleteEmbeddedDocuments("ActiveEffect", [prone.id])
|
||||
}
|
||||
if (dead) {
|
||||
await this.deleteEmbeddedDocuments("ActiveEffect", [dead.id])
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
BoLActor._healthLock.delete(this.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -897,7 +912,7 @@ export class BoLActor extends Actor {
|
||||
let msg = await ChatMessage.create({
|
||||
alias: this.name,
|
||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
|
||||
content: await renderTemplate('systems/bol/templates/chat/chat-recup-information.hbs', {
|
||||
content: await foundry.applications.handlebars.foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/chat-recup-information.hbs', {
|
||||
name: this.name,
|
||||
img: this.img,
|
||||
actorId: this.id,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { BoLRoll } from "../controllers/bol-rolls.js";
|
||||
import { BoLUtility } from "../system/bol-utility.js";
|
||||
|
||||
export class BoLHordeSheet extends ActorSheet {
|
||||
export class BoLHordeSheet extends foundry.appv1.sheets.ActorSheet {
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
@@ -116,7 +116,7 @@ export class BoLHordeSheet extends ActorSheet {
|
||||
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.description = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.actor.system.description, {async: true})
|
||||
|
||||
formData.isGM = game.user.isGM
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { BoLRoll } from "../controllers/bol-rolls.js";
|
||||
import { BoLUtility } from "../system/bol-utility.js";
|
||||
|
||||
export class BoLVehicleSheet extends ActorSheet {
|
||||
export class BoLVehicleSheet extends foundry.appv1.sheets.ActorSheet {
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
@@ -127,7 +127,7 @@ export class BoLVehicleSheet extends ActorSheet {
|
||||
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.description = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.actor.system.description, {async: true})
|
||||
|
||||
formData.isGM = game.user.isGM
|
||||
|
||||
|
||||
7
module/applications/sheets/_module.mjs
Normal file
7
module/applications/sheets/_module.mjs
Normal file
@@ -0,0 +1,7 @@
|
||||
export { default as BoLBaseItemSheet } from "./base-item-sheet.mjs"
|
||||
export { default as BoLItemSheet } from "./item-sheet.mjs"
|
||||
export { default as BoLFeatureSheet } from "./feature-sheet.mjs"
|
||||
export { default as BoLBaseActorSheet } from "./base-actor-sheet.mjs"
|
||||
export { default as BoLActorSheet } from "./actor-sheet.mjs"
|
||||
export { default as BoLHordeSheet } from "./horde-sheet.mjs"
|
||||
export { default as BoLVehicleSheet } from "./vehicle-sheet.mjs"
|
||||
144
module/applications/sheets/actor-sheet.mjs
Normal file
144
module/applications/sheets/actor-sheet.mjs
Normal file
@@ -0,0 +1,144 @@
|
||||
import BoLBaseActorSheet from "./base-actor-sheet.mjs"
|
||||
import { BoLUtility } from "../../system/bol-utility.js"
|
||||
|
||||
/**
|
||||
* Actor Sheet for BoL characters and encounters using AppV2
|
||||
*/
|
||||
export default class BoLActorSheet extends BoLBaseActorSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes],
|
||||
actions: {
|
||||
...super.DEFAULT_OPTIONS.actions,
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
sheet: {
|
||||
template: "systems/bol/templates/actor/actor-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = { primary: "stats" }
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
const actor = this.document
|
||||
|
||||
context.data = actor.toObject()
|
||||
context.details = actor.details
|
||||
context.attributes = actor.attributes
|
||||
context.aptitudes = actor.aptitudes
|
||||
context.resources = actor.getResourcesFromType()
|
||||
context.xp = actor.system.xp
|
||||
context.equipment = actor.equipment
|
||||
context.equipmentCreature = actor.equipmentCreature
|
||||
context.weapons = actor.weapons
|
||||
context.protections = actor.protections
|
||||
context.spells = actor.spells
|
||||
context.alchemy = actor.alchemy
|
||||
context.containers = actor.containers
|
||||
context.treasure = actor.treasure
|
||||
context.boleffects = actor.boleffects
|
||||
context.alchemyrecipe = actor.alchemyrecipe
|
||||
context.horoscopes = actor.horoscopes
|
||||
context.vehicles = actor.vehicles
|
||||
context.fightoptions = actor.fightoptions
|
||||
context.ammos = actor.ammos
|
||||
context.misc = actor.misc
|
||||
context.xplog = actor.xplog
|
||||
context.combat = actor.buildCombat()
|
||||
context.initiativeRank = actor.getInitiativeRank()
|
||||
context.features = actor.buildFeatures()
|
||||
context.options = this.options
|
||||
context.editScore = this.options.editScore
|
||||
context.useBougette = (actor.type === "character" && BoLUtility.getUseBougette()) || false
|
||||
context.bougette = actor.getBougette()
|
||||
context.charType = actor.getCharType()
|
||||
context.villainy = actor.getVillainy()
|
||||
context.isUndead = actor.isUndead()
|
||||
context.biography = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||
actor.system.details?.biography || "", { async: true }
|
||||
)
|
||||
context.notes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||
actor.system.details?.notes || "", { async: true }
|
||||
)
|
||||
context.isSorcerer = actor.isSorcerer()
|
||||
context.isAlchemist = actor.isAlchemist()
|
||||
context.isAstrologer = actor.isAstrologer()
|
||||
context.isMysteries = context.isSorcerer || context.isAlchemist || context.isAstrologer
|
||||
context.isPriest = actor.isPriest()
|
||||
context.horoscopeGroupList = game.settings.get("bol", "horoscope-group")
|
||||
|
||||
console.log("ACTORDATA (AppV2)", context)
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_activateListeners() {
|
||||
super._activateListeners()
|
||||
if (!this.isEditable) return
|
||||
|
||||
// Create generic item
|
||||
this.element.querySelectorAll(".create-item").forEach((el) => {
|
||||
el.addEventListener("click", () => {
|
||||
this.actor.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("BOL.ui.newEquipment"), type: "item" }], { renderSheet: true })
|
||||
})
|
||||
})
|
||||
|
||||
// Create natural weapon
|
||||
this.element.querySelectorAll(".create-natural-weapon").forEach((el) => {
|
||||
el.addEventListener("click", () => {
|
||||
const system = foundry.utils.duplicate(game.bol.config.defaultNaturalWeapon)
|
||||
this.actor.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("BOL.ui.newNaturalWeapon"), type: "item", system }], { renderSheet: true })
|
||||
})
|
||||
})
|
||||
|
||||
// Create natural protection
|
||||
this.element.querySelectorAll(".create-natural-protection").forEach((el) => {
|
||||
el.addEventListener("click", () => {
|
||||
const system = foundry.utils.duplicate(game.bol.config.defaultNaturalProtection)
|
||||
this.actor.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("BOL.ui.newNaturalProtection"), type: "item", system }], { renderSheet: true })
|
||||
})
|
||||
})
|
||||
|
||||
// Item create via header dataset (type-based creation)
|
||||
this.element.querySelectorAll(".item-create").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => {
|
||||
ev.preventDefault()
|
||||
const header = ev.currentTarget
|
||||
const type = header.dataset.type
|
||||
const data = foundry.utils.duplicate(header.dataset)
|
||||
const name = `New ${type}`
|
||||
delete data.type
|
||||
this.actor.createEmbeddedDocuments("Item", [{ name, type, data }])
|
||||
})
|
||||
})
|
||||
|
||||
// Add XP Log entry
|
||||
this.element.querySelectorAll(".xplog-add").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => {
|
||||
ev.preventDefault()
|
||||
this.actor.addXPLog("other", "Nouveau", 0, 0)
|
||||
})
|
||||
})
|
||||
|
||||
// Add item by category/subtype (equipment tab headers)
|
||||
this.element.querySelectorAll(".item-add").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => {
|
||||
ev.preventDefault()
|
||||
const { itemType, category, subtype } = ev.currentTarget.dataset
|
||||
const system = { category, subtype }
|
||||
this.actor.createEmbeddedDocuments("Item", [{
|
||||
name: game.i18n.localize("BOL.ui.newEquipment"),
|
||||
type: itemType || "item",
|
||||
system,
|
||||
}], { renderSheet: true })
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
307
module/applications/sheets/base-actor-sheet.mjs
Normal file
307
module/applications/sheets/base-actor-sheet.mjs
Normal file
@@ -0,0 +1,307 @@
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||
|
||||
import { BoLRoll } from "../../controllers/bol-rolls.js"
|
||||
import { BoLUtility } from "../../system/bol-utility.js"
|
||||
|
||||
/**
|
||||
* Base Actor Sheet for BoL system using AppV2
|
||||
* @extends {ActorSheetV2}
|
||||
*/
|
||||
export default class BoLBaseActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
|
||||
constructor(options = {}) {
|
||||
super(options)
|
||||
this.#dragDrop = this.#createDragDropHandlers()
|
||||
}
|
||||
|
||||
#dragDrop
|
||||
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["bol", "sheet", "actor"],
|
||||
position: {
|
||||
width: 836,
|
||||
height: 807,
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
closeOnSubmit: false,
|
||||
},
|
||||
window: {
|
||||
resizable: true,
|
||||
},
|
||||
tabs: [
|
||||
{
|
||||
navSelector: "nav[data-group=\"primary\"]",
|
||||
contentSelector: "section.sheet-body",
|
||||
initial: "stats",
|
||||
},
|
||||
],
|
||||
dragDrop: [{ dragSelector: ".items-list .item", dropSelector: null }],
|
||||
actions: {},
|
||||
}
|
||||
|
||||
/** Tab groups state */
|
||||
tabGroups = { primary: "stats" }
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const actor = this.document
|
||||
return {
|
||||
actor,
|
||||
system: actor.system,
|
||||
config: game.bol.config,
|
||||
isGM: game.user.isGM,
|
||||
isEditable: this.isEditable,
|
||||
owner: this.document.isOwner,
|
||||
cssClass: this.options.classes.join(" "),
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_onRender(context, options) {
|
||||
super._onRender(context, options)
|
||||
this.#dragDrop.forEach((d) => d.bind(this.element))
|
||||
this._activateTabs()
|
||||
this._activateListeners()
|
||||
this._applyBackgroundImage()
|
||||
this._activateImageEdit()
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply background image to the actor form
|
||||
* @private
|
||||
*/
|
||||
_applyBackgroundImage() {
|
||||
const logoUrl = BoLUtility.getLogoActorSheet()
|
||||
const form = this.element.querySelector(".bol-actor-form")
|
||||
if (form) form.style.backgroundImage = `url(${logoUrl})`
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate image editing via FilePicker
|
||||
* @private
|
||||
*/
|
||||
_activateImageEdit() {
|
||||
const img = this.element.querySelector('[data-edit="img"]')
|
||||
if (img && this.isEditable) {
|
||||
img.style.cursor = "pointer"
|
||||
img.addEventListener("click", () => {
|
||||
new FilePicker({
|
||||
type: "image",
|
||||
current: this.document.img,
|
||||
callback: (path) => this.document.update({ img: path }),
|
||||
}).browse()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate tab navigation
|
||||
* @private
|
||||
*/
|
||||
_activateTabs() {
|
||||
const nav = this.element.querySelector("nav[data-group]")
|
||||
if (!nav) return
|
||||
|
||||
const group = nav.dataset.group
|
||||
const activeTab = this.tabGroups[group] || "stats"
|
||||
|
||||
nav.querySelectorAll("[data-tab]").forEach((link) => {
|
||||
const tab = link.dataset.tab
|
||||
link.classList.toggle("active", tab === activeTab)
|
||||
link.addEventListener("click", (event) => {
|
||||
event.preventDefault()
|
||||
this.tabGroups[group] = tab
|
||||
this.render()
|
||||
})
|
||||
})
|
||||
|
||||
this.element.querySelectorAll(`[data-group="${group}"][data-tab]`).forEach((content) => {
|
||||
content.classList.toggle("active", content.dataset.tab === activeTab)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate event listeners (replaces activateListeners with vanilla DOM)
|
||||
* @private
|
||||
*/
|
||||
_activateListeners() {
|
||||
if (!this.isEditable) return
|
||||
|
||||
// Item edit
|
||||
this.element.querySelectorAll(".item-edit").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => {
|
||||
const li = ev.currentTarget.closest(".item")
|
||||
const item = this.actor.items.get(li?.dataset.itemId)
|
||||
item?.sheet.render(true)
|
||||
})
|
||||
})
|
||||
|
||||
// Item delete
|
||||
this.element.querySelectorAll(".item-delete").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => {
|
||||
const li = ev.currentTarget.closest(".item")
|
||||
const itemId = li?.dataset.itemId
|
||||
Dialog.confirm({
|
||||
title: game.i18n.localize("BOL.ui.deletetitle"),
|
||||
content: game.i18n.localize("BOL.ui.confirmdelete"),
|
||||
yes: () => {
|
||||
this.actor.deleteEmbeddedDocuments("Item", [itemId])
|
||||
li?.remove()
|
||||
},
|
||||
no: () => {},
|
||||
defaultYes: false,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Item equip/unequip
|
||||
this.element.querySelectorAll(".item-equip").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => {
|
||||
const li = ev.currentTarget.closest(".item")
|
||||
const item = this.actor.items.get(li?.dataset.itemId)
|
||||
if (item) this.actor.toggleEquipItem(item)
|
||||
})
|
||||
})
|
||||
|
||||
// Toggle fight option
|
||||
this.element.querySelectorAll(".toggle-fight-option").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => {
|
||||
const li = ev.currentTarget.closest(".item")
|
||||
this.actor.toggleFightOption(li?.dataset.itemId)
|
||||
})
|
||||
})
|
||||
|
||||
// Inc/dec alchemy points
|
||||
this.element.querySelectorAll(".inc-dec-btns-alchemy").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => {
|
||||
const li = ev.currentTarget.closest(".item")
|
||||
this.actor.spendAlchemyPoint(li?.dataset.itemId, 1)
|
||||
})
|
||||
})
|
||||
|
||||
// Inc/dec resource buttons
|
||||
this.element.querySelectorAll(".inc-dec-btns-resource").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => {
|
||||
const dataset = ev.currentTarget.dataset
|
||||
this.actor.incDecResources(dataset.target, parseInt(dataset.incr))
|
||||
})
|
||||
})
|
||||
|
||||
// Generic inc/dec buttons for item fields
|
||||
this.element.querySelectorAll(".inc-dec-btns").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => {
|
||||
const li = ev.currentTarget.closest(".item")
|
||||
if (!li) return
|
||||
const item = this.actor.items.get(li.dataset.itemId)
|
||||
if (!item) return
|
||||
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
|
||||
// eslint-disable-next-line no-eval
|
||||
let value = eval("item." + target) || 0
|
||||
if (operator === "minus") value = value >= min + incr ? value - incr : min
|
||||
if (operator === "plus") value = value <= max - incr ? value + incr : max
|
||||
item.update({ [target]: value })
|
||||
})
|
||||
})
|
||||
|
||||
// Rollable elements
|
||||
this.element.querySelectorAll(".rollable").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => this._onRoll(ev))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle clickable rolls (replaces _onRoll with vanilla DOM)
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
_onRoll(event) {
|
||||
event.preventDefault()
|
||||
const element = event.currentTarget
|
||||
const dataset = element.dataset
|
||||
const rollType = dataset.rollType
|
||||
const li = element.closest(".item")
|
||||
const itemId = li?.dataset.itemId
|
||||
|
||||
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(itemId)
|
||||
break
|
||||
case "damage":
|
||||
this.actor.rollWeaponDamage(itemId)
|
||||
break
|
||||
case "aptitudexp":
|
||||
this.actor.incAptitudeXP(dataset.key)
|
||||
break
|
||||
case "attributexp":
|
||||
this.actor.incAttributeXP(dataset.key)
|
||||
break
|
||||
case "careerxp":
|
||||
this.actor.incCareerXP(itemId)
|
||||
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
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// #region Drag-and-Drop
|
||||
|
||||
#createDragDropHandlers() {
|
||||
return (this.options.dragDrop || []).map((dragDrop) =>
|
||||
new foundry.applications.ux.DragDrop.implementation({
|
||||
...dragDrop,
|
||||
permissions: {
|
||||
dragstart: this._canDragStart.bind(this),
|
||||
drop: this._canDragDrop.bind(this),
|
||||
},
|
||||
callbacks: {
|
||||
dragstart: this._onDragStart.bind(this),
|
||||
dragover: this._onDragOver.bind(this),
|
||||
drop: this._onDrop.bind(this),
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
_canDragStart(selector) {
|
||||
return this.isEditable
|
||||
}
|
||||
|
||||
_canDragDrop(selector) {
|
||||
return this.isEditable
|
||||
}
|
||||
|
||||
// #endregion
|
||||
}
|
||||
255
module/applications/sheets/base-item-sheet.mjs
Normal file
255
module/applications/sheets/base-item-sheet.mjs
Normal file
@@ -0,0 +1,255 @@
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||
|
||||
/**
|
||||
* Base Item Sheet for BoL system using AppV2
|
||||
* @extends {ItemSheetV2}
|
||||
*/
|
||||
export default class BoLBaseItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
|
||||
constructor(options = {}) {
|
||||
super(options)
|
||||
this.#dragDrop = this.#createDragDropHandlers()
|
||||
}
|
||||
|
||||
#dragDrop
|
||||
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["bol", "sheet", "item"],
|
||||
position: {
|
||||
width: 650,
|
||||
height: 780,
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
},
|
||||
window: {
|
||||
resizable: true,
|
||||
},
|
||||
tabs: [
|
||||
{
|
||||
navSelector: 'nav[data-group="primary"]',
|
||||
contentSelector: "section.sheet-body",
|
||||
initial: "description",
|
||||
},
|
||||
],
|
||||
actions: {
|
||||
editImage: BoLBaseItemSheet.#onEditImage,
|
||||
postItem: BoLBaseItemSheet.#onPostItem,
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Tab groups state
|
||||
* @type {object}
|
||||
*/
|
||||
tabGroups = { primary: "description" }
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = {
|
||||
// Document & system
|
||||
fields: this.document.schema.fields,
|
||||
systemFields: this.document.system.schema.fields,
|
||||
item: this.document,
|
||||
system: this.document.system,
|
||||
source: this.document.toObject(),
|
||||
|
||||
// Enriched content
|
||||
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||
this.document.system.description,
|
||||
{ async: true }
|
||||
),
|
||||
|
||||
// Properties
|
||||
category: this.document.system.category,
|
||||
itemProperties: this.document.itemProperties,
|
||||
|
||||
// Config & permissions
|
||||
config: game.bol.config,
|
||||
isGM: game.user.isGM,
|
||||
isEditable: this.isEditable,
|
||||
|
||||
// CSS classes for template
|
||||
cssClass: this.options.classes.join(" "),
|
||||
|
||||
// Tab state
|
||||
tabs: this._getTabs(),
|
||||
activeTab: this.tabGroups.primary || "description"
|
||||
}
|
||||
|
||||
// Add careers if item is on an actor
|
||||
if (this.document.actor) {
|
||||
context.careers = this.document.actor.careers
|
||||
}
|
||||
|
||||
// Apply dynamic defaults based on item type
|
||||
this._applyDynamicDefaults(context)
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tabs configuration
|
||||
* @returns {object[]}
|
||||
* @private
|
||||
*/
|
||||
_getTabs() {
|
||||
return [
|
||||
{ id: "description", label: "BOL.ui.tab.description", icon: "fa-solid fa-book" },
|
||||
{ id: "properties", label: "BOL.ui.tab.details", icon: "fa-solid fa-cog" }
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply dynamic defaults to context based on item type and category
|
||||
* @param {object} context
|
||||
* @private
|
||||
*/
|
||||
_applyDynamicDefaults(context) {
|
||||
const itemData = context.item
|
||||
|
||||
if (itemData.type === "item") {
|
||||
// Set default category
|
||||
if (!itemData.system.category) {
|
||||
itemData.system.category = "equipment"
|
||||
}
|
||||
|
||||
// Handle equipment slot
|
||||
if (itemData.system.category === "equipment" && itemData.system.properties.equipable) {
|
||||
if (!itemData.system.properties.slot) {
|
||||
itemData.system.properties.slot = "-"
|
||||
}
|
||||
}
|
||||
|
||||
// Handle spell conditions
|
||||
if (itemData.system.category === 'spell') {
|
||||
if (!itemData.system.properties.mandatoryconditions) {
|
||||
itemData.system.properties.mandatoryconditions = []
|
||||
}
|
||||
if (!itemData.system.properties.optionnalconditions) {
|
||||
itemData.system.properties.optionnalconditions = []
|
||||
}
|
||||
for (let i = 0; i < 4; i++) {
|
||||
itemData.system.properties.mandatoryconditions[i] = itemData.system.properties.mandatoryconditions[i] ?? ""
|
||||
}
|
||||
for (let i = 0; i < 8; i++) {
|
||||
itemData.system.properties.optionnalconditions[i] = itemData.system.properties.optionnalconditions[i] ?? ""
|
||||
}
|
||||
}
|
||||
} else if (itemData.type === "feature") {
|
||||
// Set default subtype/category
|
||||
if (!itemData.system.subtype) {
|
||||
itemData.system.category = "origin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_onRender(context, options) {
|
||||
super._onRender(context, options)
|
||||
this.#dragDrop.forEach((d) => d.bind(this.element))
|
||||
this._activateTabs()
|
||||
this._activateListeners()
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate tab navigation via CSS only (no re-render) to preserve unsaved form state.
|
||||
* @private
|
||||
*/
|
||||
_activateTabs() {
|
||||
const nav = this.element.querySelector('nav[data-group="primary"]')
|
||||
if (!nav) return
|
||||
const section = this.element.querySelector('section.sheet-body')
|
||||
if (!section) return
|
||||
|
||||
const activeTab = this.tabGroups.primary || "description"
|
||||
|
||||
// Set initial active state
|
||||
nav.querySelectorAll('[data-tab]').forEach(link => {
|
||||
link.classList.toggle('active', link.dataset.tab === activeTab)
|
||||
})
|
||||
section.querySelectorAll('[data-tab]').forEach(content => {
|
||||
content.classList.toggle('active', content.dataset.tab === activeTab)
|
||||
})
|
||||
|
||||
// Tab click — CSS-only switch, no render()
|
||||
nav.querySelectorAll('[data-tab]').forEach(link => {
|
||||
link.addEventListener('click', (event) => {
|
||||
event.preventDefault()
|
||||
const tab = link.dataset.tab
|
||||
this.tabGroups.primary = tab
|
||||
nav.querySelectorAll('[data-tab]').forEach(l => l.classList.toggle('active', l.dataset.tab === tab))
|
||||
section.querySelectorAll('[data-tab]').forEach(c => c.classList.toggle('active', c.dataset.tab === tab))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate custom listeners
|
||||
* @private
|
||||
*/
|
||||
_activateListeners() {
|
||||
if (!this.isEditable) return
|
||||
|
||||
// Armor quality change handler
|
||||
const armorQuality = this.element.querySelector('.armorQuality')
|
||||
if (armorQuality) {
|
||||
armorQuality.addEventListener('change', (ev) => {
|
||||
const value = ev.currentTarget.value
|
||||
const soakFormula = this.element.querySelector('.soakFormula')
|
||||
if (soakFormula && game.bol.config.soakFormulas[value]) {
|
||||
soakFormula.value = game.bol.config.soakFormulas[value]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// #region Drag-and-Drop Workflow
|
||||
|
||||
/**
|
||||
* Create drag-and-drop workflow handlers for this Application
|
||||
* @returns {DragDrop[]}
|
||||
* @private
|
||||
*/
|
||||
#createDragDropHandlers() {
|
||||
return []
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Actions
|
||||
|
||||
/**
|
||||
* Handle editing the item image
|
||||
* @param {PointerEvent} event
|
||||
* @param {HTMLElement} target
|
||||
* @private
|
||||
*/
|
||||
static async #onEditImage(event, target) {
|
||||
const fp = new FilePicker({
|
||||
current: this.document.img,
|
||||
type: "image",
|
||||
callback: (path) => {
|
||||
this.document.update({ img: path })
|
||||
},
|
||||
})
|
||||
return fp.browse()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle posting the item to chat
|
||||
* @param {PointerEvent} event
|
||||
* @param {HTMLElement} target
|
||||
* @private
|
||||
*/
|
||||
static async #onPostItem(event, target) {
|
||||
const BoLUtility = (await import("../../system/bol-utility.js")).BoLUtility
|
||||
let chatData = foundry.utils.duplicate(this.document)
|
||||
if (this.document.actor) {
|
||||
chatData.actor = { id: this.document.actor.id }
|
||||
}
|
||||
BoLUtility.postItem(chatData)
|
||||
}
|
||||
|
||||
// #endregion
|
||||
}
|
||||
39
module/applications/sheets/feature-sheet.mjs
Normal file
39
module/applications/sheets/feature-sheet.mjs
Normal file
@@ -0,0 +1,39 @@
|
||||
import BoLBaseItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
/**
|
||||
* Item Sheet for "feature" type items (boons, careers, origins, etc.)
|
||||
* @extends {BoLBaseItemSheet}
|
||||
*/
|
||||
export default class BoLFeatureSheet extends BoLBaseItemSheet {
|
||||
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["bol", "sheet", "item", "item-type-feature"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/bol/templates/item/feature-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
|
||||
// Add feature-specific context
|
||||
context.isFeature = true
|
||||
context.isBoon = context.system.subtype === "boon"
|
||||
context.isFlaw = context.system.subtype === "flaw"
|
||||
context.isCareer = context.system.subtype === "career"
|
||||
context.isOrigin = context.system.subtype === "origin"
|
||||
context.isRace = context.system.subtype === "race"
|
||||
context.isFightOption = context.system.subtype === "fightoption"
|
||||
context.isEffect = context.system.subtype === "effect"
|
||||
context.isHoroscope = context.system.subtype === "horoscope"
|
||||
context.isXpLog = context.system.subtype === "xplog"
|
||||
|
||||
return context
|
||||
}
|
||||
}
|
||||
65
module/applications/sheets/horde-sheet.mjs
Normal file
65
module/applications/sheets/horde-sheet.mjs
Normal file
@@ -0,0 +1,65 @@
|
||||
import BoLBaseActorSheet from "./base-actor-sheet.mjs"
|
||||
|
||||
/**
|
||||
* Actor Sheet for BoL hordes using AppV2
|
||||
*/
|
||||
export default class BoLHordeSheet extends BoLBaseActorSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes],
|
||||
actions: {
|
||||
...super.DEFAULT_OPTIONS.actions,
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
sheet: {
|
||||
template: "systems/bol/templates/actor/horde-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = { primary: "stats" }
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
const actor = this.document
|
||||
|
||||
context.options = this.options
|
||||
context.editScore = this.options.editScore
|
||||
context.description = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||
actor.system.details?.biography || "", { async: true }
|
||||
)
|
||||
|
||||
console.log("HORDE (AppV2)", context)
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_activateListeners() {
|
||||
super._activateListeners()
|
||||
if (!this.isEditable) return
|
||||
|
||||
// Item create via header dataset
|
||||
this.element.querySelectorAll(".item-create").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => {
|
||||
ev.preventDefault()
|
||||
const header = ev.currentTarget
|
||||
const type = header.dataset.type
|
||||
const data = foundry.utils.duplicate(header.dataset)
|
||||
delete data.type
|
||||
this.actor.createEmbeddedDocuments("Item", [{ name: `New ${type}`, type, data }])
|
||||
})
|
||||
})
|
||||
|
||||
// Create generic item
|
||||
this.element.querySelectorAll(".create_item").forEach((el) => {
|
||||
el.addEventListener("click", () => {
|
||||
this.actor.createEmbeddedDocuments("Item", [{ name: "Nouvel Equipement", type: "item" }], { renderSheet: true })
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
38
module/applications/sheets/item-sheet.mjs
Normal file
38
module/applications/sheets/item-sheet.mjs
Normal file
@@ -0,0 +1,38 @@
|
||||
import BoLBaseItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
/**
|
||||
* Item Sheet for "item" type items (equipment, weapons, etc.)
|
||||
* @extends {BoLBaseItemSheet}
|
||||
*/
|
||||
export default class BoLItemSheet extends BoLBaseItemSheet {
|
||||
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["bol", "sheet", "item", "item-type-item"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/bol/templates/item/item-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
|
||||
// Add item-specific context
|
||||
context.isItem = true
|
||||
context.isEquipment = context.category === "equipment"
|
||||
context.isWeapon = context.category === "weapon"
|
||||
context.isProtection = context.category === "protection"
|
||||
context.isSpell = context.category === "spell"
|
||||
context.isAlchemy = context.category === "alchemy"
|
||||
context.isCapacity = context.category === "capacity"
|
||||
context.isMagical = context.category === "magical"
|
||||
context.isVehicle = context.category === "vehicle"
|
||||
|
||||
return context
|
||||
}
|
||||
}
|
||||
70
module/applications/sheets/vehicle-sheet.mjs
Normal file
70
module/applications/sheets/vehicle-sheet.mjs
Normal file
@@ -0,0 +1,70 @@
|
||||
import BoLBaseActorSheet from "./base-actor-sheet.mjs"
|
||||
|
||||
/**
|
||||
* Actor Sheet for BoL vehicles using AppV2
|
||||
*/
|
||||
export default class BoLVehicleSheet extends BoLBaseActorSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes],
|
||||
actions: {
|
||||
...super.DEFAULT_OPTIONS.actions,
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
sheet: {
|
||||
template: "systems/bol/templates/actor/vehicle-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = { primary: "stats" }
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
const actor = this.document
|
||||
|
||||
context.weapons = actor.vehicleWeapons
|
||||
context.options = this.options
|
||||
context.editScore = this.options.editScore
|
||||
context.description = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||
actor.system.description || "", { async: true }
|
||||
)
|
||||
|
||||
console.log("VEHICLE (AppV2)", context) // TODO: remove before release
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_activateListeners() {
|
||||
super._activateListeners()
|
||||
if (!this.isEditable) return
|
||||
|
||||
// Item create via header dataset
|
||||
this.element.querySelectorAll(".item-create").forEach((el) => {
|
||||
el.addEventListener("click", (ev) => {
|
||||
ev.preventDefault()
|
||||
const header = ev.currentTarget
|
||||
const type = header.dataset.type
|
||||
const data = foundry.utils.duplicate(header.dataset)
|
||||
delete data.type
|
||||
this.actor.createEmbeddedDocuments("Item", [{ name: `New ${type}`, type, data }])
|
||||
})
|
||||
})
|
||||
|
||||
// Create vehicle weapon
|
||||
this.element.querySelectorAll(".vehicle-weapon-add").forEach((el) => {
|
||||
el.addEventListener("click", () => {
|
||||
this.actor.createEmbeddedDocuments("Item", [{
|
||||
name: game.i18n.localize("BOL.ui.newEquipment"),
|
||||
type: "item",
|
||||
system: { category: "vehicleweapon" },
|
||||
}], { renderSheet: true })
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
/* -------------------------------------------- */
|
||||
// Import Modules
|
||||
import { BoLActor } from "./actor/actor.js"
|
||||
import { BoLActorSheet } from "./actor/actor-sheet.js"
|
||||
import { BoLVehicleSheet } from "./actor/vehicle-sheet.js"
|
||||
import { BoLHordeSheet } from "./actor/horde-sheet.js"
|
||||
// AppV1 actor sheets kept for reference only (AppV2 used via sheets.* below)
|
||||
import { BoLItem } from "./item/item.js"
|
||||
import { BoLItemSheet } from "./item/item-sheet.js"
|
||||
// Note: Old BoLItemSheet (AppV1) is now replaced by AppV2 sheets
|
||||
import { System, BOL } from "./system/config.js"
|
||||
import { preloadHandlebarsTemplates } from "./system/templates.js"
|
||||
import { registerHandlebarsHelpers } from "./system/helpers.js"
|
||||
@@ -18,6 +16,12 @@ import { BoLHotbar } from "./system/bol-hotbar.js"
|
||||
import { BoLCommands } from "./system/bol-commands.js"
|
||||
import { BoLRoll } from "./controllers/bol-rolls.js"
|
||||
|
||||
// Import DataModels
|
||||
import * as models from "./models/_module.mjs"
|
||||
|
||||
// Import AppV2 Sheets
|
||||
import * as sheets from "./applications/sheets/_module.mjs"
|
||||
|
||||
/* -------------------------------------------- */
|
||||
Hooks.once('init', async function () {
|
||||
|
||||
@@ -28,10 +32,12 @@ Hooks.once('init', async function () {
|
||||
BoLRoll,
|
||||
BoLUtility,
|
||||
macros: Macros,
|
||||
config: BOL
|
||||
config: BOL,
|
||||
models,
|
||||
sheets
|
||||
};
|
||||
|
||||
// Game socket
|
||||
// Game socket
|
||||
game.socket.on("system.bol", sockmsg => {
|
||||
BoLUtility.onSocketMessage(sockmsg);
|
||||
})
|
||||
@@ -47,17 +53,38 @@ Hooks.once('init', async function () {
|
||||
|
||||
// Define custom Entity classes
|
||||
CONFIG.Actor.documentClass = BoLActor;
|
||||
CONFIG.Actor.dataModels = {
|
||||
character: models.BoLCharacter,
|
||||
encounter: models.BoLEncounter,
|
||||
horde: models.BoLHorde,
|
||||
vehicle: models.BoLVehicle
|
||||
}
|
||||
|
||||
CONFIG.Item.documentClass = BoLItem;
|
||||
CONFIG.Item.dataModels = {
|
||||
item: models.BoLItem,
|
||||
feature: models.BoLFeature
|
||||
}
|
||||
|
||||
CONFIG.Combat.documentClass = BoLCombatManager;
|
||||
|
||||
// Register sheet application classes
|
||||
Actors.unregisterSheet("core", ActorSheet);
|
||||
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 })
|
||||
foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet);
|
||||
foundry.documents.collections.Actors.registerSheet("bol", sheets.BoLActorSheet, { types: ["character", "encounter"], makeDefault: true })
|
||||
foundry.documents.collections.Actors.registerSheet("bol", sheets.BoLVehicleSheet, { types: ["vehicle"], makeDefault: true })
|
||||
foundry.documents.collections.Actors.registerSheet("bol", sheets.BoLHordeSheet, { types: ["horde"], makeDefault: true })
|
||||
|
||||
Items.unregisterSheet("core", ItemSheet);
|
||||
Items.registerSheet("bol", BoLItemSheet, { makeDefault: true });
|
||||
// Register AppV2 Item Sheets
|
||||
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet);
|
||||
foundry.documents.collections.Items.registerSheet("bol", sheets.BoLItemSheet, { types: ["item"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("bol", sheets.BoLFeatureSheet, { types: ["feature"], makeDefault: true });
|
||||
|
||||
// Debug: Verify AppV2 sheets are loaded
|
||||
console.log("BoL Item Sheets registered:", {
|
||||
BoLItemSheet: sheets.BoLItemSheet.name,
|
||||
BoLFeatureSheet: sheets.BoLFeatureSheet.name,
|
||||
extendsApplicationV2: sheets.BoLItemSheet.prototype instanceof foundry.applications.api.ApplicationV2
|
||||
});
|
||||
|
||||
// Inot useful stuff
|
||||
BoLUtility.init()
|
||||
@@ -78,34 +105,27 @@ Hooks.once('init', async function () {
|
||||
Babele.get().setSystemTranslationsDir("compendiums");
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
function welcomeMessage() {
|
||||
ChatMessage.create({
|
||||
user: game.user.id,
|
||||
whisper: [game.user.id],
|
||||
content: `<div id="welcome-message-bol"><span class="rdd-roll-part">
|
||||
<strong>` + game.i18n.localize("BOL.chat.welcome1") + `</strong><p>` +
|
||||
game.i18n.localize("BOL.chat.welcome2") + "<p>" +
|
||||
game.i18n.localize("BOL.chat.welcome3") + "<p>" +
|
||||
game.i18n.localize("BOL.chat.welcome4") + "</p>" +
|
||||
game.i18n.localize("BOL.chat.welcome5") + "<br>" +
|
||||
game.i18n.localize("BOL.chat.welcome6")
|
||||
})
|
||||
|
||||
if (game.user.isGM && game.i18n.lang == 'en' && !game.modules.find(m => m.id == "babele") ){
|
||||
async function welcomeMessage() {
|
||||
const noRulebook = !game.modules.find(m => m.id === "bol-rulebook")
|
||||
const content = await foundry.applications.handlebars.renderTemplate(
|
||||
"systems/bol/templates/chat/chat-welcome.hbs",
|
||||
{ noRulebook }
|
||||
)
|
||||
ChatMessage.create({ user: game.user.id, whisper: [game.user.id], content })
|
||||
|
||||
if (game.user.isGM && game.i18n.lang == 'en' && !game.modules.find(m => m.id == "babele")) {
|
||||
ChatMessage.create({
|
||||
user: game.user.id,
|
||||
whisper: [game.user.id],
|
||||
content: `<div id="welcome-message-bol"><span class="rdd-roll-part">
|
||||
<strong>WARNING ! English language selected, but babele module is not installed !<br>Please install babele from the module tab in Foundry interface.`
|
||||
} )
|
||||
ui.notifications.warn("WARNING ! English language selected, but babele module is not installed !<br>Please install babele from the module tab in Foundry interface.")
|
||||
content: `<div class="bol-welcome-card"><div class="welcome-body"><p class="welcome-warning">⚠ WARNING ! English language selected, but Babele module is not installed !<br>Please install babele from the module tab in Foundry interface.</p></div></div>`
|
||||
})
|
||||
ui.notifications.warn("WARNING ! English language selected, but babele module is not installed !<br>Please install babele from the module tab in Foundry interface.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -160,13 +180,11 @@ Hooks.once('ready', async function () {
|
||||
"d6B": "d6H (Bonus)",
|
||||
"d6BB": "d6H + Bonus die",
|
||||
}
|
||||
|
||||
|
||||
if (game.i18n.lang === "fr") {
|
||||
game.bol.config.damageValues = damageFR;
|
||||
} else {
|
||||
game.bol.config.damageValues = damageEN;
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -5,11 +5,6 @@ const _apt2attr = { init: "mind", melee: "agility", ranged: "agility", def: "vig
|
||||
/* -------------------------------------------- */
|
||||
export class BoLRoll {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static options() {
|
||||
return { classes: ["bol", "dialog"], width: 480, height: 'fit-content' };
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getDefaultAttribute(key) {
|
||||
return _apt2attr[key]
|
||||
@@ -19,9 +14,9 @@ export class BoLRoll {
|
||||
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)) ){
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -76,7 +71,7 @@ export class BoLRoll {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static attributeCheck(actor, key="vigor", event=undefined, combatData=undefined) {
|
||||
static attributeCheck(actor, key = "vigor", event = undefined, combatData = undefined) {
|
||||
|
||||
let attribute = eval(`actor.system.attributes.${key}`)
|
||||
|
||||
@@ -89,7 +84,7 @@ export class BoLRoll {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static aptitudeCheck(actor, key="init", event=undefined, combatData=undefined) {
|
||||
static aptitudeCheck(actor, key = "init", event = undefined, combatData = undefined) {
|
||||
|
||||
let aptitude = eval(`actor.system.aptitudes.${key}`)
|
||||
let attrKey = this.getDefaultAttribute(key)
|
||||
@@ -129,7 +124,7 @@ export class BoLRoll {
|
||||
rangeMsg = "BOL.chat.range6"
|
||||
}
|
||||
ChatMessage.create({
|
||||
content: await renderTemplate('systems/bol/templates/chat/chat-info-range.hbs', {
|
||||
content: await foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/chat-info-range.hbs', {
|
||||
weapon: weapon,
|
||||
attackerName: _token.actor.name,
|
||||
defenderName: target.actor.name,
|
||||
@@ -305,29 +300,34 @@ export class BoLRoll {
|
||||
// Keep track of the final effect modifier
|
||||
this.rollData.effectModifier = effectModifier
|
||||
|
||||
// Final number of dices
|
||||
// Final number of dices
|
||||
this.rollData.nbDice = 2 + Math.abs(this.rollData.bmDice)
|
||||
// Bonus or Malus ?
|
||||
if (this.rollData.bmDice == 0) {
|
||||
$('#roll-nbdice').val("2")
|
||||
} else {
|
||||
let letter = (this.rollData.bmDice > 0) ? "B" : "M"
|
||||
$('#roll-nbdice').val("2 + " + String(Math.abs(this.rollData.bmDice)) + letter)
|
||||
const nbDiceEl = document.querySelector('#roll-nbdice')
|
||||
if (nbDiceEl) {
|
||||
if (this.rollData.bmDice == 0) {
|
||||
nbDiceEl.value = "2"
|
||||
} else {
|
||||
let letter = (this.rollData.bmDice > 0) ? "B" : "M"
|
||||
nbDiceEl.value = "2 + " + String(Math.abs(this.rollData.bmDice)) + letter
|
||||
}
|
||||
}
|
||||
let rollbase = this.rollData.attrValue + "+" + this.rollData.aptValue
|
||||
if (this.rollData.weapon && this.rollData.weapon.system.properties.onlymodifier) {
|
||||
rollbase = ""
|
||||
}
|
||||
$('#roll-modifier').val(rollbase + "+" + this.rollData.careerBonus + "+" + this.rollData.mod + "+" +
|
||||
const modifierEl = document.querySelector('#roll-modifier')
|
||||
if (modifierEl) modifierEl.value = rollbase + "+" + this.rollData.careerBonus + "+" + this.rollData.mod + "+" +
|
||||
this.rollData.modRanged + "+" + this.rollData.weaponModifier + "-" + this.rollData.defence + "-" + this.rollData.modArmorMalus + "-" +
|
||||
this.rollData.shieldMalus + "+" + this.rollData.attackModifier + "+" + this.rollData.appliedArmorMalus + "+" + effectModifier)
|
||||
this.rollData.shieldMalus + "+" + this.rollData.attackModifier + "+" + this.rollData.appliedArmorMalus + "+" + effectModifier
|
||||
|
||||
// Rebuild lits of applicable effects
|
||||
// Rebuild list 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)
|
||||
const effectsEl = document.querySelector('#applicable-effects')
|
||||
if (effectsEl) effectsEl.innerHTML = selectEffects
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -360,46 +360,48 @@ export class BoLRoll {
|
||||
/* -------------------------------------------- */
|
||||
static updateArmorMalus(rollData) {
|
||||
rollData.appliedArmorMalus = 0
|
||||
const agiEl = document.querySelector('#armor-agi-malus')
|
||||
if (rollData.attribute.key == "agility") {
|
||||
$("#armor-agi-malus").show()
|
||||
if (agiEl) agiEl.style.display = ''
|
||||
rollData.appliedArmorMalus += rollData.armorAgiMalus
|
||||
} else {
|
||||
$("#armor-agi-malus").hide()
|
||||
if (agiEl) agiEl.style.display = 'none'
|
||||
}
|
||||
const initEl = document.querySelector('#armor-init-malus')
|
||||
if (rollData.aptitude && rollData.aptitude.key == "init") {
|
||||
$("#armor-init-malus").show()
|
||||
if (initEl) initEl.style.display = ''
|
||||
rollData.appliedArmorMalus += rollData.armorInitMalus
|
||||
} else {
|
||||
$("#armor-init-malus").hide()
|
||||
if (initEl) initEl.style.display = 'none'
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------ -------------- */
|
||||
static updatePPCost(rollData) {
|
||||
$('#ppcost').html(rollData.ppCost + " + Armor(" + rollData.ppCostArmor + ")=" + Number(rollData.ppCost + rollData.ppCostArmor))
|
||||
const el = document.querySelector('#ppcost')
|
||||
if (el) el.innerHTML = rollData.ppCost + " + Armor(" + rollData.ppCostArmor + ")=" + Number(rollData.ppCost + rollData.ppCostArmor)
|
||||
}
|
||||
|
||||
/* ------------------------------ -------------- */
|
||||
static rollDialogListener(html) {
|
||||
|
||||
this.updateTotalDice()
|
||||
|
||||
html.find('#optcond').change((event) => { // Dynamic change of PP cost of spell
|
||||
html.querySelector('#optcond')?.addEventListener('change', (event) => {
|
||||
let pp = BoLUtility.computeSpellCost(this.rollData.spell, event.currentTarget.selectedOptions.length)
|
||||
this.rollData.ppCost = pp
|
||||
this.updatePPCost(this.rollData)
|
||||
})
|
||||
|
||||
html.find('#mod').change((event) => {
|
||||
html.querySelector('#mod')?.addEventListener('change', (event) => {
|
||||
this.rollData.mod = Number(event.currentTarget.value)
|
||||
this.updateTotalDice()
|
||||
})
|
||||
html.find('#modRanged').change((event) => {
|
||||
html.querySelector('#modRanged')?.addEventListener('change', (event) => {
|
||||
this.rollData.modRanged = Number(event.currentTarget.value)
|
||||
this.updateTotalDice()
|
||||
})
|
||||
|
||||
html.find('#attr').change((event) => {
|
||||
html.querySelector('#attr')?.addEventListener('change', (event) => {
|
||||
let attrKey = event.currentTarget.value
|
||||
let actor = BoLUtility.getActorFromRollData(this.rollData)
|
||||
this.rollData.attribute = foundry.utils.duplicate(actor.system.attributes[attrKey])
|
||||
@@ -407,7 +409,7 @@ export class BoLRoll {
|
||||
this.rollData.bolApplicableEffects = this.updateApplicableEffects(this.rollData)
|
||||
this.updateTotalDice()
|
||||
})
|
||||
html.find('#apt').change((event) => {
|
||||
html.querySelector('#apt')?.addEventListener('change', (event) => {
|
||||
let aptKey = event.currentTarget.value
|
||||
let actor = BoLUtility.getActorFromRollData(this.rollData)
|
||||
this.rollData.aptitude = foundry.utils.duplicate(actor.system.aptitudes[aptKey])
|
||||
@@ -416,65 +418,58 @@ export class BoLRoll {
|
||||
this.updateTotalDice()
|
||||
})
|
||||
|
||||
html.find('#applyShieldMalus').click((event) => {
|
||||
if (event.currentTarget.checked) {
|
||||
this.rollData.shieldMalus = this.rollData.shieldAttackMalus
|
||||
} else {
|
||||
this.rollData.shieldMalus = 0
|
||||
}
|
||||
html.querySelector('#applyShieldMalus')?.addEventListener('click', (event) => {
|
||||
this.rollData.shieldMalus = event.currentTarget.checked ? this.rollData.shieldAttackMalus : 0
|
||||
this.updateTotalDice()
|
||||
})
|
||||
|
||||
html.find('#career').change((event) => {
|
||||
let careers = $('#career').val()
|
||||
html.querySelector('#career')?.addEventListener('change', (event) => {
|
||||
let careers = Array.from(event.currentTarget.selectedOptions).map(o => o.value)
|
||||
this.rollData.careerBonus = (!careers || careers.length == 0) ? 0 : Math.max(...careers.map(i => parseInt(i)))
|
||||
this.updateTotalDice()
|
||||
})
|
||||
html.find('#boon').change((event) => {
|
||||
let boons = $('#boon').val()
|
||||
html.querySelector('#boon')?.addEventListener('change', (event) => {
|
||||
let boons = Array.from(event.currentTarget.selectedOptions).map(o => o.value)
|
||||
this.rollData.nbBoons = (!boons || boons.length == 0) ? 0 : boons.length
|
||||
this.updateTotalDice()
|
||||
})
|
||||
html.find('#flaw').change((event) => {
|
||||
let flaws = $('#flaw').val()
|
||||
html.querySelector('#flaw')?.addEventListener('change', (event) => {
|
||||
let flaws = Array.from(event.currentTarget.selectedOptions).map(o => o.value)
|
||||
this.rollData.nbFlaws = (!flaws || flaws.length == 0) ? 0 : flaws.length
|
||||
this.updateTotalDice()
|
||||
})
|
||||
html.find('.bdice').click((event) => {
|
||||
html.querySelectorAll('.bdice').forEach(el => el.addEventListener('click', (event) => {
|
||||
this.rollData.mDice = 0
|
||||
this.rollData.bDice = Number(event.currentTarget.value)
|
||||
this.updateTotalDice()
|
||||
})
|
||||
html.find('.mdice').click((event) => {
|
||||
}))
|
||||
html.querySelectorAll('.mdice').forEach(el => el.addEventListener('click', (event) => {
|
||||
this.rollData.bDice = 0
|
||||
this.rollData.mDice = Number(event.currentTarget.value)
|
||||
this.updateTotalDice()
|
||||
})
|
||||
html.find('#horoscope-bonus-applied').change((event) => {
|
||||
}))
|
||||
html.querySelector('#horoscope-bonus-applied')?.addEventListener('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()
|
||||
let horoscopes = Array.from(event.currentTarget.selectedOptions).map(o => o.value)
|
||||
this.rollData.horoscopeBonus = (!horoscopes || horoscopes.length == 0) ? 0 : horoscopes.length
|
||||
this.updateTotalDice()
|
||||
})
|
||||
|
||||
html.find('#horoscope-malus-applied').change((event) => {
|
||||
html.querySelector('#horoscope-malus-applied')?.addEventListener('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()
|
||||
let horoscopes = Array.from(event.currentTarget.selectedOptions).map(o => o.value)
|
||||
this.rollData.horoscopeMalus = (!horoscopes || horoscopes.length == 0) ? 0 : horoscopes.length
|
||||
this.updateTotalDice()
|
||||
})
|
||||
html.find('#horoscope-group-applied').change((event) => {
|
||||
html.querySelector('#horoscope-group-applied')?.addEventListener('change', (event) => {
|
||||
this.rollData.selectedGroupHoroscopeIndex = event.currentTarget.value
|
||||
this.updateTotalDice()
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -482,14 +477,19 @@ export class BoLRoll {
|
||||
if (rollData.mode == "weapon") {
|
||||
rollData.weaponModifier = rollData.weapon.system.properties.attackModifiers ?? 0
|
||||
rollData.attackBonusDice = rollData.weapon.system.properties.attackBonusDice
|
||||
rollData.attackMalusDice = rollData.weapon.system.properties.attackMalusDice
|
||||
if (rollData.attackBonusDice) {
|
||||
rollData.adv = "1B"
|
||||
rollData.bDice = 1
|
||||
}
|
||||
if (rollData.attackMalusDice) {
|
||||
rollData.adv = "1M"
|
||||
rollData.mDice = 1
|
||||
}
|
||||
if (defender) { // If target is selected
|
||||
rollData.defence = defender.defenseValue
|
||||
rollData.armorMalus = defender.armorMalusValue
|
||||
rollData.defenderHeroPoints = defender.getHeroPoints()
|
||||
rollData.defenderHeroPoints = defender.getHeroPoints()
|
||||
rollData.shieldBlock = 'none'
|
||||
let shields = defender.shields
|
||||
//console.log("Defender stats", defender)
|
||||
@@ -534,8 +534,9 @@ export class BoLRoll {
|
||||
rollData.id = foundry.utils.randomID(16)
|
||||
rollData.weaponModifier = 0
|
||||
rollData.attackBonusDice = false
|
||||
rollData.attackMalusDice = false
|
||||
rollData.armorMalus = 0
|
||||
// Specific stuff
|
||||
// Specific stuff
|
||||
this.preProcessWeapon(rollData, defender)
|
||||
this.preProcessFightOption(rollData)
|
||||
this.updateArmorMalus(rollData)
|
||||
@@ -546,43 +547,49 @@ export class BoLRoll {
|
||||
} else {
|
||||
rollData.shieldMalus = 0
|
||||
}
|
||||
// Save
|
||||
// Save & pre-initialize computed fields
|
||||
this.rollData = rollData
|
||||
this.updateTotalDice()
|
||||
console.log("ROLLDATA", rollData)
|
||||
|
||||
// Then display+process the dialog
|
||||
const rollOptionContent = await renderTemplate(rollOptionTpl, rollData);
|
||||
let d = new Dialog({
|
||||
title: rollData.label,
|
||||
const rollOptionContent = await foundry.applications.handlebars.renderTemplate(rollOptionTpl, rollData);
|
||||
// Use Hooks to reliably get the rendered HTMLElement (renderDialogV2 receives (app, element, context))
|
||||
Hooks.once('renderDialogV2', (app, element) => {
|
||||
element.classList.add('bol');
|
||||
this.rollDialogListener(element);
|
||||
});
|
||||
return foundry.applications.api.DialogV2.wait({
|
||||
window: { title: rollData.label },
|
||||
content: rollOptionContent,
|
||||
rollData: rollData,
|
||||
render: html => this.rollDialogListener(html),
|
||||
buttons: {
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
rejectClose: false,
|
||||
buttons: [
|
||||
{
|
||||
type: 'button',
|
||||
label: game.i18n.localize("BOL.ui.cancel"),
|
||||
callback: () => {
|
||||
}
|
||||
icon: 'fas fa-times',
|
||||
action: 'cancel'
|
||||
},
|
||||
submit: {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
{
|
||||
type: 'submit',
|
||||
label: game.i18n.localize("BOL.ui.submit"),
|
||||
callback: (html) => {
|
||||
icon: 'fas fa-check',
|
||||
action: 'submit',
|
||||
callback: (event, button, dialog) => {
|
||||
console.log("Submit Roll!!!!");
|
||||
if (rollData.mode == 'spell' && rollData.ppCurrent < rollData.ppCost) { // Check PP available
|
||||
if (rollData.mode == 'spell' && rollData.ppCurrent < rollData.ppCost) {
|
||||
ui.notifications.warn("Pas assez de Points de Pouvoir !")
|
||||
return
|
||||
return false
|
||||
}
|
||||
rollData.registerInit = (rollData.aptitude && rollData.aptitude.key == 'init') ? $('#register-init').is(":checked") : false;
|
||||
rollData.registerInit = (rollData.aptitude && rollData.aptitude.key == 'init') ?
|
||||
(dialog.element.querySelector('#register-init')?.checked ?? false) : false;
|
||||
|
||||
const isMalus = (rollData.bmDice < 0)
|
||||
|
||||
let rollbase = rollData.attrValue + rollData.aptValue
|
||||
if (rollData.weapon?.system.properties.onlymodifier) {
|
||||
rollbase = 0
|
||||
}
|
||||
if (rollData.weapon?.system.properties.onlymodifier) rollbase = 0
|
||||
|
||||
let diceData = BoLUtility.getDiceData()
|
||||
let malusInit = rollData.combatData?.malusInit || 0
|
||||
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
|
||||
@@ -593,12 +600,8 @@ export class BoLRoll {
|
||||
r.roll();
|
||||
}
|
||||
}
|
||||
},
|
||||
default: onEnter,
|
||||
close: () => { }
|
||||
}, this.options());
|
||||
|
||||
return d.render(true);
|
||||
]
|
||||
}, { classes: ['bol', 'dialog'], width: 480 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,16 +637,16 @@ export class BoLDefaultRoll {
|
||||
const diceTotal = activeDice.map(r => r.result).reduce((a, b) => a + b)
|
||||
this.rollData.roll = r
|
||||
this.rollData.isFumble = (diceTotal <= diceData.criticalFailureValue)
|
||||
if ( this.rollData.isFumble ) {
|
||||
this.rollData.isSuccess = false
|
||||
if (this.rollData.isFumble) {
|
||||
this.rollData.isSuccess = false
|
||||
this.rollData.isCritical = false
|
||||
this.rollData.isRealCritical = false
|
||||
this.rollData.isHeroic = false
|
||||
this.rollData.isFailure = true
|
||||
this.rollData.isFailure = true
|
||||
} else {
|
||||
this.rollData.isCritical = (diceTotal >= diceData.criticalSuccessValue)
|
||||
if ( this.rollData.isCritical) {
|
||||
this.rollData.isSuccess = true
|
||||
if (this.rollData.isCritical) {
|
||||
this.rollData.isSuccess = true
|
||||
} else {
|
||||
this.rollData.isSuccess = (r.total >= diceData.successValue)
|
||||
}
|
||||
@@ -692,18 +695,15 @@ export class BoLDefaultRoll {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async sendChatMessage() {
|
||||
let actor = BoLUtility.getActorFromRollData(this.rollData)
|
||||
this._buildChatMessage(this.rollData).then(async msgFlavor => {
|
||||
//console.log("MSG", msgFlavor )
|
||||
let msg = await this.rollData.roll.toMessage({
|
||||
user: game.user.id,
|
||||
rollMode: game.settings.get("core", "rollMode"),
|
||||
flavor: msgFlavor,
|
||||
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)
|
||||
})
|
||||
const actor = BoLUtility.getActorFromRollData(this.rollData)
|
||||
const rollMode = game.settings.get("core", "rollMode")
|
||||
const msgFlavor = await this._buildChatMessage(this.rollData)
|
||||
const msg = await this.rollData.roll.toMessage({
|
||||
flavor: msgFlavor,
|
||||
speaker: ChatMessage.getSpeaker({ actor: actor }),
|
||||
}, { rollMode })
|
||||
this.rollData.roll = foundry.utils.duplicate(this.rollData.roll)
|
||||
if (msg) await msg.setFlag("world", "bol-roll-data", this.rollData)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -805,13 +805,13 @@ export class BoLDefaultRoll {
|
||||
/* -------------------------------------------- */
|
||||
_buildDamageChatMessage(rollData) {
|
||||
const rollMessageTpl = 'systems/bol/templates/chat/rolls/damage-roll-card.hbs';
|
||||
return renderTemplate(rollMessageTpl, rollData)
|
||||
return foundry.applications.handlebars.renderTemplate(rollMessageTpl, rollData)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_buildChatMessage(rollData) {
|
||||
const rollMessageTpl = 'systems/bol/templates/chat/rolls/default-roll-card.hbs'
|
||||
return renderTemplate(rollMessageTpl, rollData)
|
||||
return foundry.applications.handlebars.renderTemplate(rollMessageTpl, rollData)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { BoLUtility } from "../system/bol-utility.js";
|
||||
* Extend the basic ItemSheet with some very simple modifications
|
||||
* @extends {ItemSheet}
|
||||
*/
|
||||
export class BoLItemSheet extends ItemSheet {
|
||||
export class BoLItemSheet extends foundry.appv1.sheets.ItemSheet {
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
@@ -13,6 +13,7 @@ export class BoLItemSheet extends ItemSheet {
|
||||
template: "systems/bol/templates/item/item-sheet.hbs",
|
||||
width: 650,
|
||||
height: 780,
|
||||
dragDrop: [{ dragSelector: null, dropSelector: null }],
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }]
|
||||
});
|
||||
}
|
||||
@@ -27,7 +28,7 @@ export class BoLItemSheet extends ItemSheet {
|
||||
data.category = itemData.system.category
|
||||
data.isGM = game.user.isGM;
|
||||
data.itemProperties = this.item.itemProperties;
|
||||
data.description = await TextEditor.enrichHTML(this.object.system.description, { async: true })
|
||||
data.description = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.description, { async: true })
|
||||
if (data.document.actor) {
|
||||
data.careers = data.document.actor.careers
|
||||
}
|
||||
@@ -102,6 +103,7 @@ export class BoLItemSheet extends ItemSheet {
|
||||
activateListeners(html) {
|
||||
|
||||
super.activateListeners(html);
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
// Roll handlers, click handlers, etc. would go here.
|
||||
119
module/item.backup/item-sheet.js.appv1
Normal file
119
module/item.backup/item-sheet.js.appv1
Normal file
@@ -0,0 +1,119 @@
|
||||
import { BoLUtility } from "../system/bol-utility.js";
|
||||
|
||||
/**
|
||||
* Extend the basic ItemSheet with some very simple modifications
|
||||
* @extends {ItemSheet}
|
||||
*/
|
||||
export class BoLItemSheet extends foundry.appv1.sheets.ItemSheet {
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
classes: ["bol", "sheet", "item"],
|
||||
template: "systems/bol/templates/item/item-sheet.hbs",
|
||||
width: 650,
|
||||
height: 780,
|
||||
dragDrop: [{ dragSelector: null, dropSelector: null }],
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }]
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
async getData(options) {
|
||||
const data = super.getData(options)
|
||||
let itemData = foundry.utils.duplicate(data.document)
|
||||
data.config = game.bol.config
|
||||
data.item = itemData
|
||||
data.category = itemData.system.category
|
||||
data.isGM = game.user.isGM;
|
||||
data.itemProperties = this.item.itemProperties;
|
||||
data.description = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.description, { async: true })
|
||||
if (data.document.actor) {
|
||||
data.careers = data.document.actor.careers
|
||||
}
|
||||
// Dynamic default data fix/adapt
|
||||
if (itemData.type == "item") {
|
||||
if (!itemData.system.category) {
|
||||
itemData.system.category = "equipment"
|
||||
}
|
||||
if (itemData.system.category == "equipment" && itemData.system.properties.equipable) {
|
||||
if (!itemData.system.properties.slot) {
|
||||
itemData.system.properties.slot = "-"
|
||||
}
|
||||
}
|
||||
if (itemData.system.category == 'spell') {
|
||||
if (!itemData.system.properties.mandatoryconditions) {
|
||||
itemData.system.properties.mandatoryconditions = []
|
||||
}
|
||||
if (!itemData.system.properties.optionnalconditions) {
|
||||
itemData.system.properties.optionnalconditions = []
|
||||
}
|
||||
for (let i = 0; i < 4; i++) {
|
||||
itemData.system.properties.mandatoryconditions[i] = itemData.system.properties.mandatoryconditions[i] ?? ""
|
||||
}
|
||||
for (let i = 0; i < 8; i++) {
|
||||
itemData.system.properties.optionnalconditions[i] = itemData.system.properties.optionnalconditions[i] ?? ""
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!itemData.system.subtype) {
|
||||
itemData.system.category = "origin"
|
||||
}
|
||||
}
|
||||
|
||||
console.log("ITEMDATA", data);
|
||||
return data;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_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 */
|
||||
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;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
|
||||
super.activateListeners(html);
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
// Roll handlers, click handlers, etc. would go here.
|
||||
|
||||
html.find('.armorQuality').change(ev => {
|
||||
const li = $(ev.currentTarget);
|
||||
console.log(game.bol.config.soakFormulas[li.val()]);
|
||||
$('.soakFormula').val(game.bol.config.soakFormulas[li.val()]);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
36
module/item.backup/item.js
Normal file
36
module/item.backup/item.js
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Extend the basic Item with some very simple modifications.
|
||||
* @extends {Item}
|
||||
*/
|
||||
export class BoLItem extends Item {
|
||||
/**
|
||||
* Augment the basic Item data model with additional dynamic data.
|
||||
*/
|
||||
prepareData() {
|
||||
super.prepareData()
|
||||
|
||||
const actorData = this.actor ? this.actor.system : {}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
get properties() {
|
||||
return this.system.properties
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/**
|
||||
* Get the Array of item properties which are used in the small sidebar of the description tab
|
||||
* @return {Array}
|
||||
* @private
|
||||
*/
|
||||
get itemProperties() {
|
||||
const props = [];
|
||||
if ( this.type === "item" ) {
|
||||
const entries = Object.entries(this.system.properties)
|
||||
props.push(...entries.filter(e => e[1] === true).map(e => { return game.bol.config.itemProperties2[e[0]] }))
|
||||
}
|
||||
return props.filter(p => !!p)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
112
module/models/README.md
Normal file
112
module/models/README.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# BoL DataModels
|
||||
|
||||
Ce dossier contient les DataModels pour le système Barbarians of Lemuria (BoL).
|
||||
|
||||
## Structure
|
||||
|
||||
### Actors DataModels
|
||||
|
||||
- **character.mjs** : Personnages joueurs
|
||||
- Attributs (Vigor, Agility, Mind, Appeal)
|
||||
- Aptitudes (Initiative, Mêlée, Distance, Défense)
|
||||
- Ressources (HP, Hero Points, Faith, Power, Alchemy, Astrology)
|
||||
- XP et création
|
||||
- Bougette (argent)
|
||||
|
||||
- **encounter.mjs** : PNJ et créatures
|
||||
- Mêmes attributs que character
|
||||
- Champs spécifiques : chartype (tough/villain), isundead, size, environment
|
||||
|
||||
- **horde.mjs** : Hordes de créatures
|
||||
- Mêmes attributs de base
|
||||
- Champs spécifiques : hordesize, hordebasehp, hasdamagerule, damagerule
|
||||
|
||||
- **vehicle.mjs** : Véhicules (navires, chars, etc.)
|
||||
- Attributs véhicules : hull, crew, resources
|
||||
- Champs spécifiques : vehicletype, row, spur, status
|
||||
|
||||
### Items DataModels
|
||||
|
||||
- **item.mjs** : Équipements et objets
|
||||
- Propriétés (weapon, armor, magical, etc.)
|
||||
- Équipement (quantity, weight, price, worn)
|
||||
- Category et subtype
|
||||
|
||||
- **feature.mjs** : Capacités, traits, sorts
|
||||
- Rank (niveau/rang)
|
||||
- Description
|
||||
- Category et subtype
|
||||
|
||||
## Architecture
|
||||
|
||||
Tous les DataModels héritent de `foundry.abstract.TypeDataModel` et définissent leur schéma via `defineSchema()`.
|
||||
|
||||
Exemple de structure :
|
||||
|
||||
```javascript
|
||||
export default class BoLCharacterDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
const requiredInteger = { required: true, nullable: false, integer: true };
|
||||
|
||||
return {
|
||||
// Définition des champs
|
||||
};
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["BOL.Character"];
|
||||
|
||||
// Méthodes personnalisées (à ajouter)
|
||||
}
|
||||
```
|
||||
|
||||
## Types de champs utilisés
|
||||
|
||||
- `StringField` : Chaînes de caractères
|
||||
- `NumberField` : Nombres (avec option `integer: true` pour entiers)
|
||||
- `BooleanField` : Booléens
|
||||
- `HTMLField` : HTML enrichi (descriptions, biographies)
|
||||
- `ArrayField` : Tableaux
|
||||
- `SchemaField` : Objets imbriqués
|
||||
|
||||
## Export
|
||||
|
||||
Le fichier `_module.mjs` exporte tous les DataModels :
|
||||
|
||||
```javascript
|
||||
export { default as BoLCharacter } from "./character.mjs"
|
||||
export { default as BoLEncounter } from "./encounter.mjs"
|
||||
export { default as BoLHorde } from "./horde.mjs"
|
||||
export { default as BoLVehicle } from "./vehicle.mjs"
|
||||
export { default as BoLItem } from "./item.mjs"
|
||||
export { default as BoLFeature } from "./feature.mjs"
|
||||
```
|
||||
|
||||
## Configuration dans bol.js
|
||||
|
||||
Les DataModels sont enregistrés dans `CONFIG` :
|
||||
|
||||
```javascript
|
||||
CONFIG.Actor.dataModels = {
|
||||
character: models.BoLCharacter,
|
||||
encounter: models.BoLEncounter,
|
||||
horde: models.BoLHorde,
|
||||
vehicle: models.BoLVehicle
|
||||
}
|
||||
|
||||
CONFIG.Item.dataModels = {
|
||||
item: models.BoLItem,
|
||||
feature: models.BoLFeature
|
||||
}
|
||||
```
|
||||
|
||||
## Compatibilité
|
||||
|
||||
Les DataModels sont compatibles avec le `template.json` existant. La migration est transparente pour les données existantes.
|
||||
|
||||
## Prochaines étapes
|
||||
|
||||
1. Ajouter `prepareDerivedData()` pour les calculs automatiques
|
||||
2. Migrer la logique métier depuis actor.js
|
||||
3. Ajouter des validations personnalisées
|
||||
4. Documenter avec JSDoc
|
||||
6
module/models/_module.mjs
Normal file
6
module/models/_module.mjs
Normal file
@@ -0,0 +1,6 @@
|
||||
export { default as BoLCharacter } from "./character.mjs"
|
||||
export { default as BoLEncounter } from "./encounter.mjs"
|
||||
export { default as BoLHorde } from "./horde.mjs"
|
||||
export { default as BoLVehicle } from "./vehicle.mjs"
|
||||
export { default as BoLItem } from "./item.mjs"
|
||||
export { default as BoLFeature } from "./feature.mjs"
|
||||
192
module/models/character.mjs
Normal file
192
module/models/character.mjs
Normal file
@@ -0,0 +1,192 @@
|
||||
/**
|
||||
* Data model for Character actors
|
||||
*/
|
||||
export default class BoLCharacterDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
const requiredInteger = { required: true, nullable: false, integer: true };
|
||||
|
||||
return {
|
||||
// Details
|
||||
details: new fields.SchemaField({
|
||||
biography: new fields.HTMLField({ initial: "" }),
|
||||
notes: new fields.HTMLField({ initial: "" }),
|
||||
height: new fields.StringField({ initial: "" }),
|
||||
age: new fields.StringField({ initial: "" }),
|
||||
weight: new fields.StringField({ initial: "" }),
|
||||
hair: new fields.StringField({ initial: "" }),
|
||||
eyes: new fields.StringField({ initial: "" }),
|
||||
signs: new fields.StringField({ initial: "" }),
|
||||
size: new fields.StringField({ initial: "" }),
|
||||
languages: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||
xplog: new fields.ArrayField(new fields.ObjectField(), { initial: [] })
|
||||
}),
|
||||
|
||||
// Combat
|
||||
combat: new fields.SchemaField({
|
||||
lastinit: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
iscritical: new fields.BooleanField({ initial: false }),
|
||||
isfumble: new fields.BooleanField({ initial: false }),
|
||||
islegendary: new fields.BooleanField({ initial: false })
|
||||
}),
|
||||
|
||||
// Character type
|
||||
chartype: new fields.StringField({ initial: "player" }),
|
||||
villainy: new fields.BooleanField({ initial: false }),
|
||||
|
||||
// Bougette
|
||||
bougette: new fields.SchemaField({
|
||||
state: new fields.StringField({ initial: "nomoney" }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
|
||||
// XP
|
||||
xp: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "xp" }),
|
||||
label: new fields.StringField({ initial: "BOL.traits.xp" }),
|
||||
total: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
spent: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
|
||||
// Creation
|
||||
creation: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "creation" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.creation" }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
|
||||
// Protection
|
||||
prot: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "prot" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.prot" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
|
||||
// Attributes
|
||||
attributes: new fields.SchemaField({
|
||||
vigor: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "vigor" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.vigor" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: -1 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
agility: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "agility" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.agility" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: -1 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
mind: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "mind" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.mind" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: -1 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
appeal: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "appeal" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.appeal" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
})
|
||||
}),
|
||||
|
||||
// Aptitudes
|
||||
aptitudes: new fields.SchemaField({
|
||||
init: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "init" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.init" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
melee: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "melee" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.melee" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
ranged: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "ranged" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.ranged" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
def: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "def" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.def" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
})
|
||||
}),
|
||||
|
||||
// Resources
|
||||
resources: new fields.SchemaField({
|
||||
hp: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "hp" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.hp" }),
|
||||
ismain: new fields.BooleanField({ initial: true }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 1 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 1 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 1 })
|
||||
}),
|
||||
hero: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "hero" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.hero" }),
|
||||
ismain: new fields.BooleanField({ initial: true }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 5 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 })
|
||||
}),
|
||||
faith: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "faith" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.faith" }),
|
||||
ismain: new fields.BooleanField({ initial: true }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
power: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "power" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.power" }),
|
||||
ismain: new fields.BooleanField({ initial: true }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
alchemypoints: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "alchemypoints" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.alchemypoints" }),
|
||||
ismain: new fields.BooleanField({ initial: false }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
astrologypoints: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "astrologypoints" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.astrologypoints" }),
|
||||
ismain: new fields.BooleanField({ initial: false }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
})
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["BOL.Character"];
|
||||
}
|
||||
173
module/models/encounter.mjs
Normal file
173
module/models/encounter.mjs
Normal file
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* Data model for Encounter actors
|
||||
*/
|
||||
export default class BoLEncounterDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
const requiredInteger = { required: true, nullable: false, integer: true };
|
||||
|
||||
return {
|
||||
// Details
|
||||
details: new fields.SchemaField({
|
||||
biography: new fields.HTMLField({ initial: "" }),
|
||||
notes: new fields.HTMLField({ initial: "" }),
|
||||
height: new fields.StringField({ initial: "" }),
|
||||
age: new fields.StringField({ initial: "" }),
|
||||
weight: new fields.StringField({ initial: "" }),
|
||||
hair: new fields.StringField({ initial: "" }),
|
||||
eyes: new fields.StringField({ initial: "" }),
|
||||
signs: new fields.StringField({ initial: "" }),
|
||||
size: new fields.StringField({ initial: "" }),
|
||||
languages: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||
xplog: new fields.ArrayField(new fields.ObjectField(), { initial: [] })
|
||||
}),
|
||||
|
||||
// Combat
|
||||
combat: new fields.SchemaField({
|
||||
lastinit: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
iscritical: new fields.BooleanField({ initial: false }),
|
||||
isfumble: new fields.BooleanField({ initial: false }),
|
||||
islegendary: new fields.BooleanField({ initial: false })
|
||||
}),
|
||||
|
||||
// Character type
|
||||
chartype: new fields.StringField({ initial: "tough" }),
|
||||
isundead: new fields.BooleanField({ initial: false }),
|
||||
villainy: new fields.BooleanField({ initial: false }),
|
||||
size: new fields.StringField({ initial: "" }),
|
||||
environment: new fields.StringField({ initial: "" }),
|
||||
|
||||
// Protection
|
||||
prot: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "prot" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.prot" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
|
||||
// Attributes
|
||||
attributes: new fields.SchemaField({
|
||||
vigor: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "vigor" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.vigor" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: -1 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
agility: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "agility" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.agility" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: -1 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
mind: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "mind" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.mind" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: -1 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
appeal: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "appeal" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.appeal" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
})
|
||||
}),
|
||||
|
||||
// Aptitudes
|
||||
aptitudes: new fields.SchemaField({
|
||||
init: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "init" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.init" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
melee: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "melee" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.melee" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
ranged: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "ranged" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.ranged" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
def: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "def" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.def" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
})
|
||||
}),
|
||||
|
||||
// Resources
|
||||
resources: new fields.SchemaField({
|
||||
hp: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "hp" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.hp" }),
|
||||
ismain: new fields.BooleanField({ initial: true }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 1 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 1 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 1 })
|
||||
}),
|
||||
hero: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "hero" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.hero" }),
|
||||
ismain: new fields.BooleanField({ initial: true }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 5 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 })
|
||||
}),
|
||||
faith: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "faith" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.faith" }),
|
||||
ismain: new fields.BooleanField({ initial: true }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
power: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "power" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.power" }),
|
||||
ismain: new fields.BooleanField({ initial: true }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
alchemypoints: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "alchemypoints" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.alchemypoints" }),
|
||||
ismain: new fields.BooleanField({ initial: false }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
astrologypoints: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "astrologypoints" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.astrologypoints" }),
|
||||
ismain: new fields.BooleanField({ initial: false }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
})
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["BOL.Encounter"];
|
||||
}
|
||||
55
module/models/feature.mjs
Normal file
55
module/models/feature.mjs
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Data model for Feature items
|
||||
*/
|
||||
export default class BoLFeatureDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
const requiredInteger = { required: true, nullable: false, integer: true };
|
||||
const nullableNumber = { required: false, nullable: true, initial: null };
|
||||
|
||||
return {
|
||||
// Base fields
|
||||
category: new fields.StringField({ initial: "" }),
|
||||
subtype: new fields.StringField({ initial: "default" }),
|
||||
description: new fields.HTMLField({ initial: "" }),
|
||||
properties: new fields.SchemaField({
|
||||
// Career
|
||||
sorcerer: new fields.BooleanField({ initial: false }),
|
||||
alchemist: new fields.BooleanField({ initial: false }),
|
||||
priest: new fields.BooleanField({ initial: false }),
|
||||
astrologer: new fields.BooleanField({ initial: false }),
|
||||
|
||||
// Boon
|
||||
isbonusdice: new fields.BooleanField({ initial: false }),
|
||||
|
||||
// Flaw
|
||||
ismalusdice: new fields.BooleanField({ initial: false }),
|
||||
|
||||
// Fight option
|
||||
fightoptiontype: new fields.StringField({ initial: "" }),
|
||||
activated: new fields.BooleanField({ initial: false }),
|
||||
isspecial: new fields.BooleanField({ initial: false }),
|
||||
|
||||
// Effect (boleffect)
|
||||
identifier: new fields.StringField({ initial: "" }),
|
||||
modifier: new fields.StringField({ initial: "" }),
|
||||
|
||||
// Horoscope
|
||||
horoscopeanswer: new fields.StringField({ initial: "" }),
|
||||
rank: new fields.NumberField({ ...nullableNumber }),
|
||||
|
||||
// XP log
|
||||
xptype: new fields.StringField({ initial: "" }),
|
||||
xpdate: new fields.StringField({ initial: "" }),
|
||||
xpname: new fields.StringField({ initial: "" }),
|
||||
xpcost: new fields.NumberField({ ...nullableNumber }),
|
||||
xpvalue: new fields.NumberField({ ...nullableNumber }),
|
||||
}),
|
||||
|
||||
// Feature-specific fields
|
||||
rank: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
};
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["BOL.Feature"];
|
||||
}
|
||||
174
module/models/horde.mjs
Normal file
174
module/models/horde.mjs
Normal file
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* Data model for Horde actors
|
||||
*/
|
||||
export default class BoLHordeDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
const requiredInteger = { required: true, nullable: false, integer: true };
|
||||
|
||||
return {
|
||||
// Details
|
||||
details: new fields.SchemaField({
|
||||
biography: new fields.HTMLField({ initial: "" }),
|
||||
notes: new fields.HTMLField({ initial: "" }),
|
||||
height: new fields.StringField({ initial: "" }),
|
||||
age: new fields.StringField({ initial: "" }),
|
||||
weight: new fields.StringField({ initial: "" }),
|
||||
hair: new fields.StringField({ initial: "" }),
|
||||
eyes: new fields.StringField({ initial: "" }),
|
||||
signs: new fields.StringField({ initial: "" }),
|
||||
size: new fields.StringField({ initial: "" }),
|
||||
languages: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||
xplog: new fields.ArrayField(new fields.ObjectField(), { initial: [] })
|
||||
}),
|
||||
|
||||
// Combat
|
||||
combat: new fields.SchemaField({
|
||||
lastinit: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
iscritical: new fields.BooleanField({ initial: false }),
|
||||
isfumble: new fields.BooleanField({ initial: false }),
|
||||
islegendary: new fields.BooleanField({ initial: false })
|
||||
}),
|
||||
|
||||
// Character type
|
||||
chartype: new fields.StringField({ initial: "horde" }),
|
||||
villainy: new fields.BooleanField({ initial: false }),
|
||||
hordesize: new fields.NumberField({ ...requiredInteger, initial: 1 }),
|
||||
hordebasehp: new fields.NumberField({ ...requiredInteger, initial: 1 }),
|
||||
hasdamagerule: new fields.BooleanField({ initial: false }),
|
||||
damagerule: new fields.StringField({ initial: "none" }),
|
||||
|
||||
// Protection
|
||||
prot: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "prot" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.prot" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
|
||||
// Attributes
|
||||
attributes: new fields.SchemaField({
|
||||
vigor: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "vigor" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.vigor" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: -1 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
agility: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "agility" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.agility" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: -1 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
mind: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "mind" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.mind" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: -1 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
appeal: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "appeal" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.appeal" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
})
|
||||
}),
|
||||
|
||||
// Aptitudes
|
||||
aptitudes: new fields.SchemaField({
|
||||
init: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "init" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.init" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
melee: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "melee" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.melee" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
ranged: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "ranged" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.ranged" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
def: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "def" }),
|
||||
label: new fields.StringField({ initial: "BOL.aptitudes.def" }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
})
|
||||
}),
|
||||
|
||||
// Resources
|
||||
resources: new fields.SchemaField({
|
||||
hp: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "hp" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.hp" }),
|
||||
ismain: new fields.BooleanField({ initial: true }),
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 1 }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 1 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 1 })
|
||||
}),
|
||||
hero: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "hero" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.hero" }),
|
||||
ismain: new fields.BooleanField({ initial: true }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 5 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 })
|
||||
}),
|
||||
faith: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "faith" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.faith" }),
|
||||
ismain: new fields.BooleanField({ initial: true }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
power: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "power" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.power" }),
|
||||
ismain: new fields.BooleanField({ initial: true }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
alchemypoints: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "alchemypoints" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.alchemypoints" }),
|
||||
ismain: new fields.BooleanField({ initial: false }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
}),
|
||||
astrologypoints: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "astrologypoints" }),
|
||||
label: new fields.StringField({ initial: "BOL.resources.astrologypoints" }),
|
||||
ismain: new fields.BooleanField({ initial: false }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
})
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["BOL.Horde"];
|
||||
}
|
||||
113
module/models/item.mjs
Normal file
113
module/models/item.mjs
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* Data model for Item items
|
||||
*/
|
||||
export default class BoLItemDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
const requiredInteger = { required: true, nullable: false, integer: true };
|
||||
const nullableNumber = { required: false, nullable: true, initial: null };
|
||||
|
||||
return {
|
||||
// Base fields
|
||||
category: new fields.StringField({ initial: "" }),
|
||||
subtype: new fields.StringField({ initial: "default" }),
|
||||
description: new fields.HTMLField({ initial: "" }),
|
||||
properties: new fields.SchemaField({
|
||||
// Base flags
|
||||
ranged: new fields.BooleanField({ initial: false }),
|
||||
melee: new fields.BooleanField({ initial: false }),
|
||||
spell: new fields.BooleanField({ initial: false }),
|
||||
protection: new fields.BooleanField({ initial: false }),
|
||||
weapon: new fields.BooleanField({ initial: false }),
|
||||
armor: new fields.BooleanField({ initial: false }),
|
||||
helm: new fields.BooleanField({ initial: false }),
|
||||
shield: new fields.BooleanField({ initial: false }),
|
||||
equipable: new fields.BooleanField({ initial: false }),
|
||||
consumable: new fields.BooleanField({ initial: false }),
|
||||
magical: new fields.BooleanField({ initial: false }),
|
||||
"2H": new fields.BooleanField({ initial: false }),
|
||||
reloadable: new fields.BooleanField({ initial: false }),
|
||||
bow: new fields.BooleanField({ initial: false }),
|
||||
crossbow: new fields.BooleanField({ initial: false }),
|
||||
throwing: new fields.BooleanField({ initial: false }),
|
||||
|
||||
// Equipment
|
||||
stackable: new fields.BooleanField({ initial: false }),
|
||||
stacksize: new fields.NumberField({ ...nullableNumber }),
|
||||
slot: new fields.StringField({ initial: "-" }),
|
||||
|
||||
// Weapon flags
|
||||
natural: new fields.BooleanField({ initial: false }),
|
||||
concealable: new fields.BooleanField({ initial: false }),
|
||||
ignoreshield: new fields.BooleanField({ initial: false }),
|
||||
attackBonusDice: new fields.BooleanField({ initial: false }),
|
||||
attackMalusDice: new fields.BooleanField({ initial: false }),
|
||||
onlymodifier: new fields.BooleanField({ initial: false }),
|
||||
bashing: new fields.BooleanField({ initial: false }),
|
||||
throwable: new fields.BooleanField({ initial: false }),
|
||||
damageReroll1: new fields.BooleanField({ initial: false }),
|
||||
|
||||
// Weapon stats
|
||||
attackAttribute: new fields.StringField({ initial: "vigor" }),
|
||||
attackAptitude: new fields.StringField({ initial: "melee" }),
|
||||
attackModifiers: new fields.NumberField({ ...nullableNumber }),
|
||||
weaponSize: new fields.StringField({ initial: "unarmed" }),
|
||||
damage: new fields.StringField({ initial: "0" }),
|
||||
damageAttribute: new fields.StringField({ initial: "" }),
|
||||
damageModifiers: new fields.NumberField({ ...nullableNumber }),
|
||||
damageMultiplier: new fields.StringField({ initial: "1" }),
|
||||
range: new fields.NumberField({ ...nullableNumber }),
|
||||
reload: new fields.NumberField({ ...nullableNumber }),
|
||||
|
||||
// Protection
|
||||
armorQuality: new fields.StringField({ initial: "" }),
|
||||
soak: new fields.SchemaField({
|
||||
formula: new fields.StringField({ initial: "" }),
|
||||
value: new fields.NumberField({ initial: 0, nullable: true }),
|
||||
modifier: new fields.NumberField({ initial: 0, nullable: true }),
|
||||
}),
|
||||
blocking: new fields.SchemaField({
|
||||
malus: new fields.NumberField({ initial: 0, nullable: true }),
|
||||
blocking1: new fields.BooleanField({ initial: false }),
|
||||
blockingAll: new fields.BooleanField({ initial: false }),
|
||||
}),
|
||||
modifiers: new fields.SchemaField({
|
||||
init: new fields.NumberField({ initial: 0, nullable: true }),
|
||||
agility: new fields.NumberField({ initial: 0, nullable: true }),
|
||||
powercost: new fields.NumberField({ initial: 0, nullable: true }),
|
||||
social: new fields.BooleanField({ initial: false }),
|
||||
}),
|
||||
|
||||
// Spell
|
||||
circle: new fields.NumberField({ initial: 0, nullable: true }),
|
||||
difficulty: new fields.StringField({ initial: "" }),
|
||||
ppcost: new fields.NumberField({ initial: 0, nullable: true }),
|
||||
duration: new fields.StringField({ initial: "" }),
|
||||
nbmandatoryconditions: new fields.NumberField({ initial: 0, nullable: true }),
|
||||
mandatoryconditions: new fields.ArrayField(new fields.StringField()),
|
||||
optionnalconditions: new fields.ArrayField(new fields.StringField()),
|
||||
|
||||
// Alchemy
|
||||
alchemytype: new fields.StringField({ initial: "" }),
|
||||
pccost: new fields.NumberField({ initial: 0, nullable: true }),
|
||||
pccurrent: new fields.NumberField({ initial: 0, nullable: true }),
|
||||
|
||||
// Vehicle weapon
|
||||
isfiredamage: new fields.BooleanField({ initial: false }),
|
||||
ishulldamage: new fields.BooleanField({ initial: false }),
|
||||
iscrewdamage: new fields.BooleanField({ initial: false }),
|
||||
isboarding: new fields.BooleanField({ initial: false }),
|
||||
isspur: new fields.BooleanField({ initial: false }),
|
||||
isbreakrow: new fields.BooleanField({ initial: false }),
|
||||
}),
|
||||
|
||||
// Equipment fields
|
||||
quantity: new fields.NumberField({ ...requiredInteger, initial: 1 }),
|
||||
weight: new fields.NumberField({ initial: 0 }),
|
||||
price: new fields.NumberField({ initial: 0 }),
|
||||
worn: new fields.BooleanField({ initial: false })
|
||||
};
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["BOL.Item"];
|
||||
}
|
||||
55
module/models/vehicle.mjs
Normal file
55
module/models/vehicle.mjs
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Data model for Vehicle actors
|
||||
*/
|
||||
export default class BoLVehicleDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
const requiredInteger = { required: true, nullable: false, integer: true };
|
||||
|
||||
return {
|
||||
vehicletype: new fields.StringField({ initial: "boat" }),
|
||||
|
||||
attributes: new fields.SchemaField({
|
||||
hull: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "hull" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.hull" }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 })
|
||||
}),
|
||||
crew: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "crew" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.crew" }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 })
|
||||
}),
|
||||
resources: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "resources" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.resources" }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 })
|
||||
})
|
||||
}),
|
||||
|
||||
row: new fields.SchemaField({
|
||||
key: new fields.StringField({ initial: "row" }),
|
||||
label: new fields.StringField({ initial: "BOL.attributes.row" }),
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
min: new fields.NumberField({ ...requiredInteger, initial: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 5 })
|
||||
}),
|
||||
|
||||
spur: new fields.SchemaField({
|
||||
value: new fields.StringField({ initial: "" })
|
||||
}),
|
||||
|
||||
status: new fields.SchemaField({}),
|
||||
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["BOL.Vehicle"];
|
||||
}
|
||||
@@ -12,8 +12,8 @@ export class BoLTokenHud {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async removeExtensionHud(app, html, tokenId) {
|
||||
html.find('.control-icon.bol-roll').remove()
|
||||
html.find('.control-icon.bol-action').remove()
|
||||
$(html).find('.control-icon.bol-roll').remove()
|
||||
$(html).find('.control-icon.bol-action').remove()
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -25,7 +25,7 @@ export class BoLTokenHud {
|
||||
|
||||
const hudData = { actor: actor, actionsList: actor.buildListeActions(), rollsList: actor.buildRollList() }
|
||||
|
||||
const controlIconActions = html.find('.control-icon[data-action=combat]');
|
||||
const controlIconActions = $(html).find('.control-icon[data-action=combat]');
|
||||
// initiative
|
||||
await BoLTokenHud._configureSubMenu(controlIconActions, 'systems/bol/templates/token/hud-actor-actions.hbs', hudData,
|
||||
(event) => {
|
||||
@@ -43,7 +43,7 @@ export class BoLTokenHud {
|
||||
}
|
||||
})
|
||||
|
||||
const controlIconTarget = html.find('.control-icon[data-action=target]');
|
||||
const controlIconTarget = $(html).find('.control-icon[data-action=target]');
|
||||
// att+apt+career
|
||||
await BoLTokenHud._configureSubMenu(controlIconTarget, 'systems/bol/templates/token/hud-actor-rolls.hbs', hudData,
|
||||
(event) => {
|
||||
@@ -59,7 +59,7 @@ export class BoLTokenHud {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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) {
|
||||
BoLTokenHud.addExtensionHud(app, html, tokenId);
|
||||
}
|
||||
@@ -67,7 +67,7 @@ export class BoLTokenHud {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async _configureSubMenu(insertionPoint, template, hudData, onMenuItem) {
|
||||
const hud = $(await renderTemplate(template, hudData))
|
||||
const hud = $(await foundry.applications.handlebars.renderTemplate(template, hudData))
|
||||
const list = hud.find('div.bol-hud-list')
|
||||
|
||||
BoLTokenHud._toggleHudListActive(hud, list);
|
||||
|
||||
@@ -221,10 +221,10 @@ export class BoLCalendar extends Application {
|
||||
let hn = defHeure.heure;
|
||||
let chiffreAstral = this.getCurrentNombreAstral() ?? 0;
|
||||
heuresChancesMalchances[0] = { value : "+4", heures: [this.getHeureNumber((hn + chiffreAstral) % RDD_HEURES_PAR_JOUR).label]};
|
||||
heuresChancesMalchances[1] = { value : "+2", heures: [this.getHeureNumber((hn + chiffreAstral+4) % RDD_HEURES_PAR_JOUR).label,
|
||||
heuresChancesMalchances[1] = { value : "+2", heures: [this.getHeureNumber((hn + chiffreAstral+4) % RDD_HEURES_PAR_JOUR).label,
|
||||
this.getHeureNumber((hn + chiffreAstral + 8) % RDD_HEURES_PAR_JOUR).label ] };
|
||||
heuresChancesMalchances[2] = { value : "-4", heures: [this.getHeureNumber((hn + chiffreAstral+6) % RDD_HEURES_PAR_JOUR).label]};
|
||||
heuresChancesMalchances[3] = { value : "-2", heures: [this.getHeureNumber((hn + chiffreAstral+3) % RDD_HEURES_PAR_JOUR).label,
|
||||
heuresChancesMalchances[3] = { value : "-2", heures: [this.getHeureNumber((hn + chiffreAstral+3) % RDD_HEURES_PAR_JOUR).label,
|
||||
this.getHeureNumber((hn + chiffreAstral + 9) % RDD_HEURES_PAR_JOUR).label ]};
|
||||
}
|
||||
return heuresChancesMalchances;
|
||||
@@ -331,7 +331,7 @@ export class BoLCalendar extends Application {
|
||||
calendrierData.jourMoisOptions = RdDCalendrier.buildJoursMois();
|
||||
calendrierData.heuresOptions = [0, 1];
|
||||
calendrierData.minutesOptions = Array(RDD_MINUTES_PAR_HEURES).fill().map((item, index) => 0 + index);
|
||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html', calendrierData);
|
||||
let html = await foundry.applications.handlebars.renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html', calendrierData);
|
||||
this.editeur = new RdDCalendrierEditeur(html, this, calendrierData)
|
||||
}
|
||||
this.editeur.updateData(calendrierData);
|
||||
@@ -360,7 +360,7 @@ export class BoLCalendar extends Application {
|
||||
let heureNaissance = actor.getHeureNaissance();
|
||||
if ( heureNaissance) {
|
||||
heuresParActeur[actor.name] = this.getHeuresChanceMalchance(heureNaissance);
|
||||
}
|
||||
}
|
||||
}
|
||||
//console.log("ASTRO", astrologieArray);
|
||||
calendrierData.astrologieData = astrologieArray;
|
||||
@@ -398,7 +398,7 @@ export class BoLCalendar extends Application {
|
||||
let isRightMB = false;
|
||||
if ("which" in ev) { // Gecko (Firefox), WebKit (Safari/Chrome) & Opera
|
||||
isRightMB = ev.which == 3;
|
||||
} else if ("button" in ev) { // IE, Opera
|
||||
} else if ("button" in ev) { // IE, Opera
|
||||
isRightMB = ev.button == 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ export class BoLUtility {
|
||||
})
|
||||
game.settings.register("bol", "auto-remove-dead", {
|
||||
name: game.i18n.localize("BOL.settings.removeDead"),
|
||||
hint: game.i18n.localize("BOL.settings.removeDeadTooltip"),
|
||||
hint: game.i18n.localize("BOL.settings.removeDeadTooltip"),
|
||||
scope: "world",
|
||||
config: true,
|
||||
default: false,
|
||||
@@ -237,6 +237,11 @@ export class BoLUtility {
|
||||
if (chatData.img.includes("/blank.png")) {
|
||||
chatData.img = null;
|
||||
}
|
||||
// For old-format weapon items lacking stat fields, apply defaults so the chat card can display them
|
||||
if (chatData.system?.properties?.weapon && !chatData.system.properties.damage) {
|
||||
const defaults = game.bol.config.defaultNaturalWeapon?.properties ?? {};
|
||||
chatData.system.properties = Object.assign(foundry.utils.duplicate(defaults), chatData.system.properties);
|
||||
}
|
||||
// JSON object for easy creation
|
||||
chatData.jsondata = JSON.stringify(
|
||||
{
|
||||
@@ -244,7 +249,7 @@ export class BoLUtility {
|
||||
payload: chatData,
|
||||
});
|
||||
|
||||
renderTemplate('systems/bol/templates/item/post-item.hbs', chatData).then(html => {
|
||||
foundry.applications.handlebars.renderTemplate('systems/bol/templates/item/post-item.hbs', chatData).then(html => {
|
||||
let chatOptions = BoLUtility.chatDataSetup(html);
|
||||
ChatMessage.create(chatOptions)
|
||||
});
|
||||
@@ -344,7 +349,7 @@ export class BoLUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async chatMessageHandler(message, html, data) {
|
||||
const chatCard = html.find('.flavor-text')
|
||||
const chatCard = $(html).find('.flavor-text')
|
||||
if (chatCard.length > 0) {
|
||||
// If the user is the message author or the actor owner, proceed
|
||||
const actor = game.actors.get(data.message.speaker.actor)
|
||||
@@ -381,6 +386,8 @@ export class BoLUtility {
|
||||
/* -------------------------------------------- */
|
||||
static async chatListeners(html) {
|
||||
|
||||
html = $(html);
|
||||
|
||||
// Damage handling
|
||||
html.on("click", '.chat-damage-apply', event => {
|
||||
let rollData = BoLUtility.getRollDataFromMessage(event)
|
||||
@@ -427,7 +434,7 @@ export class BoLUtility {
|
||||
html.on("click", '.damage-handling', event => {
|
||||
event.preventDefault()
|
||||
let attr = event.currentTarget.attributes['data-attack-id']
|
||||
if ( !attr) {
|
||||
if (!attr) {
|
||||
ui.notifications.warn("Impossible de trouver l'attaque correspondante, erreur de suivi de combat.")
|
||||
return
|
||||
}
|
||||
@@ -480,13 +487,17 @@ export class BoLUtility {
|
||||
|
||||
if (defenseMode == 'damage-with-armor') {
|
||||
let armorFormula = defender.getArmorFormula()
|
||||
rollData.rollArmor = new Roll(armorFormula)
|
||||
await rollData.rollArmor.roll()
|
||||
let msg = await rollData.rollArmor.toMessage({ flavor: "BOL.chat.armorRoll : " + armorFormula });
|
||||
if ( game.dice3d) { // wait animation end when DsN is there
|
||||
await game.dice3d.waitFor3DAnimationByMessageID(msg.id);
|
||||
if (armorFormula === "0") {
|
||||
rollData.armorProtect = 0
|
||||
} else {
|
||||
rollData.rollArmor = new Roll(armorFormula)
|
||||
await rollData.rollArmor.roll()
|
||||
let msg = await rollData.rollArmor.toMessage({ flavor: game.i18n.localize("BOL.chat.armorRoll") + " : " + armorFormula })
|
||||
if (game.dice3d && msg) {
|
||||
await game.dice3d.waitFor3DAnimationByMessageID(msg.id)
|
||||
}
|
||||
rollData.armorProtect = (rollData.rollArmor.total < 0) ? 0 : rollData.rollArmor.total
|
||||
}
|
||||
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)
|
||||
@@ -498,9 +509,17 @@ export class BoLUtility {
|
||||
}
|
||||
if (defenseMode == 'hero-reduce-damage') {
|
||||
let armorFormula = defender.getArmorFormula()
|
||||
rollData.rollArmor = new Roll(armorFormula)
|
||||
await rollData.rollArmor.roll()
|
||||
rollData.armorProtect = (rollData.rollArmor.total < 0) ? 0 : rollData.rollArmor.total
|
||||
if (armorFormula === "0") {
|
||||
rollData.armorProtect = 0
|
||||
} else {
|
||||
rollData.rollArmor = new Roll(armorFormula)
|
||||
await rollData.rollArmor.roll()
|
||||
let msg = await rollData.rollArmor.toMessage({ flavor: game.i18n.localize("BOL.chat.armorRoll") + " : " + armorFormula })
|
||||
if (game.dice3d && msg) {
|
||||
await game.dice3d.waitFor3DAnimationByMessageID(msg.id)
|
||||
}
|
||||
rollData.armorProtect = (rollData.rollArmor.total < 0) ? 0 : rollData.rollArmor.total
|
||||
}
|
||||
rollData.rollHero = new Roll("1d6")
|
||||
await rollData.rollHero.roll()
|
||||
rollData.finalDamage = rollData.damageTotal - rollData.rollHero.total - rollData.armorProtect
|
||||
@@ -535,13 +554,13 @@ export class BoLUtility {
|
||||
ChatMessage.create({
|
||||
alias: defender.name,
|
||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(defender.name),
|
||||
content: await renderTemplate('systems/bol/templates/chat/rolls/defense-result-card.hbs', damageResults)
|
||||
content: await foundry.applications.handlebars.foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/rolls/defense-result-card.hbs', damageResults)
|
||||
})
|
||||
console.log("Defender data : ", defenderUser)
|
||||
ChatMessage.create({
|
||||
alias: defender.name,
|
||||
whisper: BoLUtility.getOtherWhisperRecipients(defenderUser?.name),
|
||||
content: await renderTemplate('systems/bol/templates/chat/rolls/defense-summary-card.hbs', damageResults)
|
||||
content: await foundry.applications.handlebars.foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/rolls/defense-summary-card.hbs', damageResults)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -628,11 +647,11 @@ export class BoLUtility {
|
||||
let msg = await ChatMessage.create({
|
||||
alias: defender.name,
|
||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(defender.name),
|
||||
content: await renderTemplate('systems/bol/templates/chat/rolls/defense-request-card.hbs', {
|
||||
content: await foundry.applications.handlebars.foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/rolls/defense-request-card.hbs', {
|
||||
attackId: rollData.id,
|
||||
attacker: rollData.attacker,
|
||||
defender: defender,
|
||||
defenderHeroPoints:defender.getHeroPoints(),
|
||||
defenderHeroPoints: defender.getHeroPoints(),
|
||||
defenderWeapons: defenderWeapons,
|
||||
damageTotal: rollData.damageTotal,
|
||||
damagesIgnoresArmor: rollData.damagesIgnoresArmor,
|
||||
|
||||
@@ -188,19 +188,25 @@ BOL.rangeModifiers = {
|
||||
"-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.difficultyModifiers = [
|
||||
{ value: "-12", label: "BOL.dialog.divine" },
|
||||
{ value: "-11", label: "BOL.dialog.mythic11" },
|
||||
{ value: "-10", label: "BOL.dialog.mythic" },
|
||||
{ value: "-9", label: "BOL.dialog.heroic9" },
|
||||
{ value: "-8", label: "BOL.dialog.heroic" },
|
||||
{ value: "-7", label: "BOL.dialog.formidable7" },
|
||||
{ value: "-6", label: "BOL.dialog.formidable" },
|
||||
{ value: "-5", label: "BOL.dialog.demanding5" },
|
||||
{ value: "-4", label: "BOL.dialog.demanding" },
|
||||
{ value: "-3", label: "BOL.dialog.tough3" },
|
||||
{ value: "-2", label: "BOL.dialog.tough" },
|
||||
{ value: "-1", label: "BOL.dialog.hard" },
|
||||
{ value: "0", label: "BOL.dialog.moderate" },
|
||||
{ value: "1", label: "BOL.dialog.easy" },
|
||||
{ value: "2", label: "BOL.dialog.veryeasy" },
|
||||
{ value: "3", label: "BOL.dialog.soeasy3" },
|
||||
{ value: "4", label: "BOL.dialog.soeasy" },
|
||||
]
|
||||
|
||||
BOL.alchemyModifiers = {
|
||||
"2": "BOL.dialog.veryeasy",
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function registerHooks() {
|
||||
}))
|
||||
|
||||
Hooks.on('renderChatLog', (log, html, data) => BoLUtility.chatListeners(html))
|
||||
Hooks.on('renderChatMessage', (message, html, data) => BoLUtility.chatMessageHandler(message, html, data))
|
||||
Hooks.on('renderChatMessageHTML', (message, html, data) => BoLUtility.chatMessageHandler(message, html, data))
|
||||
|
||||
/**
|
||||
* Create a macro when dropping an entity on the hotbar
|
||||
@@ -73,8 +73,8 @@ export default function registerHooks() {
|
||||
button.addEventListener('click', () => {
|
||||
game.bol.charSummary.render(true)
|
||||
})
|
||||
html.find('.header-actions').after(button)
|
||||
$(html).find('.header-actions').after(button)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ export const preloadHandlebarsTemplates = async function () {
|
||||
"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/chat/chat-welcome.hbs",
|
||||
"systems/bol/templates/dialogs/aptitude-roll-part.hbs",
|
||||
"systems/bol/templates/dialogs/attribute-roll-part.hbs",
|
||||
"systems/bol/templates/dialogs/mod-roll-part.hbs",
|
||||
@@ -60,11 +61,12 @@ export const preloadHandlebarsTemplates = async function () {
|
||||
"systems/bol/templates/dialogs/effect-roll-part.hbs",
|
||||
"systems/bol/templates/dialogs/boons-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/horoscope-roll-part.hbs"
|
||||
"systems/bol/templates/dialogs/horoscope-roll-part.hbs",
|
||||
"systems/bol/templates/apps/character-summary-template.html"
|
||||
];
|
||||
|
||||
// Load the template parts
|
||||
return loadTemplates(templatePaths);
|
||||
return foundry.applications.handlebars.loadTemplates(templatePaths);
|
||||
};
|
||||
|
||||
Binary file not shown.
BIN
packs/aides-de-jeu/000774.ldb
Normal file
BIN
packs/aides-de-jeu/000774.ldb
Normal file
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000642
|
||||
MANIFEST-001076
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:46:21.360031 7f25b97fa6c0 Recovering log #640
|
||||
2024/12/12-21:46:21.492497 7f25b97fa6c0 Delete type=3 #638
|
||||
2024/12/12-21:46:21.492569 7f25b97fa6c0 Delete type=0 #640
|
||||
2024/12/12-21:50:13.987586 7f25b2ffd6c0 Level-0 table #645: started
|
||||
2024/12/12-21:50:13.987627 7f25b2ffd6c0 Level-0 table #645: 0 bytes OK
|
||||
2024/12/12-21:50:13.994186 7f25b2ffd6c0 Delete type=0 #643
|
||||
2024/12/12-21:50:14.007425 7f25b2ffd6c0 Manual compaction at level-0 from '!journal!3xJg1rCxnWvEmoxS' @ 72057594037927935 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:50:14.007460 7f25b2ffd6c0 Manual compaction at level-1 from '!journal!3xJg1rCxnWvEmoxS' @ 72057594037927935 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:53.852685 7f56e3fff6c0 Recovering log #1074
|
||||
2026/02/28-22:59:53.863099 7f56e3fff6c0 Delete type=3 #1072
|
||||
2026/02/28-22:59:53.863210 7f56e3fff6c0 Delete type=0 #1074
|
||||
2026/03/01-01:08:46.366409 7f54e37ef6c0 Level-0 table #1079: started
|
||||
2026/03/01-01:08:46.366440 7f54e37ef6c0 Level-0 table #1079: 0 bytes OK
|
||||
2026/03/01-01:08:46.372420 7f54e37ef6c0 Delete type=0 #1077
|
||||
2026/03/01-01:08:46.391669 7f54e37ef6c0 Manual compaction at level-0 from '!journal!3xJg1rCxnWvEmoxS' @ 72057594037927935 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at (end)
|
||||
2026/03/01-01:08:46.391720 7f54e37ef6c0 Manual compaction at level-1 from '!journal!3xJg1rCxnWvEmoxS' @ 72057594037927935 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:11:43.910823 7f25b37fe6c0 Recovering log #636
|
||||
2024/12/12-21:11:44.036050 7f25b37fe6c0 Delete type=3 #634
|
||||
2024/12/12-21:11:44.036107 7f25b37fe6c0 Delete type=0 #636
|
||||
2024/12/12-21:40:17.197599 7f25b2ffd6c0 Level-0 table #641: started
|
||||
2024/12/12-21:40:17.197635 7f25b2ffd6c0 Level-0 table #641: 0 bytes OK
|
||||
2024/12/12-21:40:17.203956 7f25b2ffd6c0 Delete type=0 #639
|
||||
2024/12/12-21:40:17.217330 7f25b2ffd6c0 Manual compaction at level-0 from '!journal!3xJg1rCxnWvEmoxS' @ 72057594037927935 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:40:17.217374 7f25b2ffd6c0 Manual compaction at level-1 from '!journal!3xJg1rCxnWvEmoxS' @ 72057594037927935 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-17:23:52.883622 7f56f93fe6c0 Recovering log #1070
|
||||
2026/02/28-17:23:52.893895 7f56f93fe6c0 Delete type=3 #1068
|
||||
2026/02/28-17:23:52.893967 7f56f93fe6c0 Delete type=0 #1070
|
||||
2026/02/28-22:59:43.750682 7f54e37ef6c0 Level-0 table #1075: started
|
||||
2026/02/28-22:59:43.750749 7f54e37ef6c0 Level-0 table #1075: 0 bytes OK
|
||||
2026/02/28-22:59:43.758241 7f54e37ef6c0 Delete type=0 #1073
|
||||
2026/02/28-22:59:43.758440 7f54e37ef6c0 Manual compaction at level-0 from '!journal!3xJg1rCxnWvEmoxS' @ 72057594037927935 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:43.758473 7f54e37ef6c0 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/aides-de-jeu/MANIFEST-001076
Normal file
BIN
packs/aides-de-jeu/MANIFEST-001076
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs/armors/000679.ldb
Normal file
BIN
packs/armors/000679.ldb
Normal file
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000548
|
||||
MANIFEST-000981
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:46:21.083865 7f25b37fe6c0 Recovering log #546
|
||||
2024/12/12-21:46:21.217856 7f25b37fe6c0 Delete type=3 #544
|
||||
2024/12/12-21:46:21.217918 7f25b37fe6c0 Delete type=0 #546
|
||||
2024/12/12-21:50:13.981247 7f25b2ffd6c0 Level-0 table #551: started
|
||||
2024/12/12-21:50:13.981272 7f25b2ffd6c0 Level-0 table #551: 0 bytes OK
|
||||
2024/12/12-21:50:13.987466 7f25b2ffd6c0 Delete type=0 #549
|
||||
2024/12/12-21:50:14.007412 7f25b2ffd6c0 Manual compaction at level-0 from '!items!G3dZTHIabA3LA1hY' @ 72057594037927935 : 1 .. '!items!xhEcsi3WHjbt2ro9' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:50:14.007452 7f25b2ffd6c0 Manual compaction at level-1 from '!items!G3dZTHIabA3LA1hY' @ 72057594037927935 : 1 .. '!items!xhEcsi3WHjbt2ro9' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:53.826224 7f56f8bfd6c0 Recovering log #979
|
||||
2026/02/28-22:59:53.836758 7f56f8bfd6c0 Delete type=3 #977
|
||||
2026/02/28-22:59:53.836823 7f56f8bfd6c0 Delete type=0 #979
|
||||
2026/03/01-01:08:46.372471 7f54e37ef6c0 Level-0 table #984: started
|
||||
2026/03/01-01:08:46.372486 7f54e37ef6c0 Level-0 table #984: 0 bytes OK
|
||||
2026/03/01-01:08:46.378495 7f54e37ef6c0 Delete type=0 #982
|
||||
2026/03/01-01:08:46.391687 7f54e37ef6c0 Manual compaction at level-0 from '!items!G3dZTHIabA3LA1hY' @ 72057594037927935 : 1 .. '!items!xhEcsi3WHjbt2ro9' @ 0 : 0; will stop at (end)
|
||||
2026/03/01-01:08:46.391731 7f54e37ef6c0 Manual compaction at level-1 from '!items!G3dZTHIabA3LA1hY' @ 72057594037927935 : 1 .. '!items!xhEcsi3WHjbt2ro9' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:11:43.620616 7f25b8ff96c0 Recovering log #542
|
||||
2024/12/12-21:11:43.750156 7f25b8ff96c0 Delete type=3 #540
|
||||
2024/12/12-21:11:43.750213 7f25b8ff96c0 Delete type=0 #542
|
||||
2024/12/12-21:40:17.191315 7f25b2ffd6c0 Level-0 table #547: started
|
||||
2024/12/12-21:40:17.191339 7f25b2ffd6c0 Level-0 table #547: 0 bytes OK
|
||||
2024/12/12-21:40:17.197420 7f25b2ffd6c0 Delete type=0 #545
|
||||
2024/12/12-21:40:17.217313 7f25b2ffd6c0 Manual compaction at level-0 from '!items!G3dZTHIabA3LA1hY' @ 72057594037927935 : 1 .. '!items!xhEcsi3WHjbt2ro9' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:40:17.217363 7f25b2ffd6c0 Manual compaction at level-1 from '!items!G3dZTHIabA3LA1hY' @ 72057594037927935 : 1 .. '!items!xhEcsi3WHjbt2ro9' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-17:23:52.858522 7f56e3fff6c0 Recovering log #975
|
||||
2026/02/28-17:23:52.869495 7f56e3fff6c0 Delete type=3 #973
|
||||
2026/02/28-17:23:52.869552 7f56e3fff6c0 Delete type=0 #975
|
||||
2026/02/28-22:59:43.737596 7f54e37ef6c0 Level-0 table #980: started
|
||||
2026/02/28-22:59:43.737635 7f54e37ef6c0 Level-0 table #980: 0 bytes OK
|
||||
2026/02/28-22:59:43.743801 7f54e37ef6c0 Delete type=0 #978
|
||||
2026/02/28-22:59:43.758414 7f54e37ef6c0 Manual compaction at level-0 from '!items!G3dZTHIabA3LA1hY' @ 72057594037927935 : 1 .. '!items!xhEcsi3WHjbt2ro9' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:43.758457 7f54e37ef6c0 Manual compaction at level-1 from '!items!G3dZTHIabA3LA1hY' @ 72057594037927935 : 1 .. '!items!xhEcsi3WHjbt2ro9' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
BIN
packs/armors/MANIFEST-000981
Normal file
BIN
packs/armors/MANIFEST-000981
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs/boons/000843.ldb
Normal file
BIN
packs/boons/000843.ldb
Normal file
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000641
|
||||
MANIFEST-001075
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:46:20.029795 7f25b37fe6c0 Recovering log #639
|
||||
2024/12/12-21:46:20.162579 7f25b37fe6c0 Delete type=3 #637
|
||||
2024/12/12-21:46:20.162683 7f25b37fe6c0 Delete type=0 #639
|
||||
2024/12/12-21:50:13.926457 7f25b2ffd6c0 Level-0 table #644: started
|
||||
2024/12/12-21:50:13.926508 7f25b2ffd6c0 Level-0 table #644: 0 bytes OK
|
||||
2024/12/12-21:50:13.934036 7f25b2ffd6c0 Delete type=0 #642
|
||||
2024/12/12-21:50:13.954229 7f25b2ffd6c0 Manual compaction at level-0 from '!items!039ZF3E3MtAGwbiX' @ 72057594037927935 : 1 .. '!items!zgspy1QKaxdEetEw' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:50:13.954282 7f25b2ffd6c0 Manual compaction at level-1 from '!items!039ZF3E3MtAGwbiX' @ 72057594037927935 : 1 .. '!items!zgspy1QKaxdEetEw' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:53.718001 7f56f8bfd6c0 Recovering log #1073
|
||||
2026/02/28-22:59:53.729345 7f56f8bfd6c0 Delete type=3 #1071
|
||||
2026/02/28-22:59:53.729412 7f56f8bfd6c0 Delete type=0 #1073
|
||||
2026/03/01-01:08:46.321084 7f54e37ef6c0 Level-0 table #1078: started
|
||||
2026/03/01-01:08:46.321111 7f54e37ef6c0 Level-0 table #1078: 0 bytes OK
|
||||
2026/03/01-01:08:46.327221 7f54e37ef6c0 Delete type=0 #1076
|
||||
2026/03/01-01:08:46.339937 7f54e37ef6c0 Manual compaction at level-0 from '!items!039ZF3E3MtAGwbiX' @ 72057594037927935 : 1 .. '!items!zgspy1QKaxdEetEw' @ 0 : 0; will stop at (end)
|
||||
2026/03/01-01:08:46.339972 7f54e37ef6c0 Manual compaction at level-1 from '!items!039ZF3E3MtAGwbiX' @ 72057594037927935 : 1 .. '!items!zgspy1QKaxdEetEw' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:11:42.417136 7f25b8ff96c0 Recovering log #635
|
||||
2024/12/12-21:11:42.597818 7f25b8ff96c0 Delete type=3 #633
|
||||
2024/12/12-21:11:42.597875 7f25b8ff96c0 Delete type=0 #635
|
||||
2024/12/12-21:40:17.139303 7f25b2ffd6c0 Level-0 table #640: started
|
||||
2024/12/12-21:40:17.139355 7f25b2ffd6c0 Level-0 table #640: 0 bytes OK
|
||||
2024/12/12-21:40:17.145373 7f25b2ffd6c0 Delete type=0 #638
|
||||
2024/12/12-21:40:17.165314 7f25b2ffd6c0 Manual compaction at level-0 from '!items!039ZF3E3MtAGwbiX' @ 72057594037927935 : 1 .. '!items!zgspy1QKaxdEetEw' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:40:17.165365 7f25b2ffd6c0 Manual compaction at level-1 from '!items!039ZF3E3MtAGwbiX' @ 72057594037927935 : 1 .. '!items!zgspy1QKaxdEetEw' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-17:23:52.757933 7f56f9bff6c0 Recovering log #1069
|
||||
2026/02/28-17:23:52.767692 7f56f9bff6c0 Delete type=3 #1067
|
||||
2026/02/28-17:23:52.767761 7f56f9bff6c0 Delete type=0 #1069
|
||||
2026/02/28-22:59:43.697108 7f54e37ef6c0 Level-0 table #1074: started
|
||||
2026/02/28-22:59:43.697152 7f54e37ef6c0 Level-0 table #1074: 0 bytes OK
|
||||
2026/02/28-22:59:43.704224 7f54e37ef6c0 Delete type=0 #1072
|
||||
2026/02/28-22:59:43.704461 7f54e37ef6c0 Manual compaction at level-0 from '!items!039ZF3E3MtAGwbiX' @ 72057594037927935 : 1 .. '!items!zgspy1QKaxdEetEw' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:43.704511 7f54e37ef6c0 Manual compaction at level-1 from '!items!039ZF3E3MtAGwbiX' @ 72057594037927935 : 1 .. '!items!zgspy1QKaxdEetEw' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
BIN
packs/boons/MANIFEST-001075
Normal file
BIN
packs/boons/MANIFEST-001075
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs/boonsflawscreatures/000772.ldb
Normal file
BIN
packs/boonsflawscreatures/000772.ldb
Normal file
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000641
|
||||
MANIFEST-001074
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:46:20.169625 7f25b8ff96c0 Recovering log #639
|
||||
2024/12/12-21:46:20.298341 7f25b8ff96c0 Delete type=3 #637
|
||||
2024/12/12-21:46:20.298399 7f25b8ff96c0 Delete type=0 #639
|
||||
2024/12/12-21:50:13.934153 7f25b2ffd6c0 Level-0 table #644: started
|
||||
2024/12/12-21:50:13.934178 7f25b2ffd6c0 Level-0 table #644: 0 bytes OK
|
||||
2024/12/12-21:50:13.940593 7f25b2ffd6c0 Delete type=0 #642
|
||||
2024/12/12-21:50:13.954244 7f25b2ffd6c0 Manual compaction at level-0 from '!items!CoqlfsDV1gL5swbK' @ 72057594037927935 : 1 .. '!items!yofwG0YrsL902G77' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:50:13.954292 7f25b2ffd6c0 Manual compaction at level-1 from '!items!CoqlfsDV1gL5swbK' @ 72057594037927935 : 1 .. '!items!yofwG0YrsL902G77' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:53.732583 7f56e3fff6c0 Recovering log #1072
|
||||
2026/02/28-22:59:53.742972 7f56e3fff6c0 Delete type=3 #1070
|
||||
2026/02/28-22:59:53.743061 7f56e3fff6c0 Delete type=0 #1072
|
||||
2026/03/01-01:08:46.313828 7f54e37ef6c0 Level-0 table #1077: started
|
||||
2026/03/01-01:08:46.313877 7f54e37ef6c0 Level-0 table #1077: 0 bytes OK
|
||||
2026/03/01-01:08:46.320973 7f54e37ef6c0 Delete type=0 #1075
|
||||
2026/03/01-01:08:46.339925 7f54e37ef6c0 Manual compaction at level-0 from '!items!CoqlfsDV1gL5swbK' @ 72057594037927935 : 1 .. '!items!yofwG0YrsL902G77' @ 0 : 0; will stop at (end)
|
||||
2026/03/01-01:08:46.339953 7f54e37ef6c0 Manual compaction at level-1 from '!items!CoqlfsDV1gL5swbK' @ 72057594037927935 : 1 .. '!items!yofwG0YrsL902G77' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:11:42.611933 7f25b3fff6c0 Recovering log #635
|
||||
2024/12/12-21:11:42.739932 7f25b3fff6c0 Delete type=3 #633
|
||||
2024/12/12-21:11:42.740037 7f25b3fff6c0 Delete type=0 #635
|
||||
2024/12/12-21:40:17.158730 7f25b2ffd6c0 Level-0 table #640: started
|
||||
2024/12/12-21:40:17.158762 7f25b2ffd6c0 Level-0 table #640: 0 bytes OK
|
||||
2024/12/12-21:40:17.165130 7f25b2ffd6c0 Delete type=0 #638
|
||||
2024/12/12-21:40:17.165357 7f25b2ffd6c0 Manual compaction at level-0 from '!items!CoqlfsDV1gL5swbK' @ 72057594037927935 : 1 .. '!items!yofwG0YrsL902G77' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:40:17.165391 7f25b2ffd6c0 Manual compaction at level-1 from '!items!CoqlfsDV1gL5swbK' @ 72057594037927935 : 1 .. '!items!yofwG0YrsL902G77' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-17:23:52.769847 7f56f93fe6c0 Recovering log #1068
|
||||
2026/02/28-17:23:52.780583 7f56f93fe6c0 Delete type=3 #1066
|
||||
2026/02/28-17:23:52.780639 7f56f93fe6c0 Delete type=0 #1068
|
||||
2026/02/28-22:59:43.677524 7f54e37ef6c0 Level-0 table #1073: started
|
||||
2026/02/28-22:59:43.677620 7f54e37ef6c0 Level-0 table #1073: 0 bytes OK
|
||||
2026/02/28-22:59:43.684329 7f54e37ef6c0 Delete type=0 #1071
|
||||
2026/02/28-22:59:43.704401 7f54e37ef6c0 Manual compaction at level-0 from '!items!CoqlfsDV1gL5swbK' @ 72057594037927935 : 1 .. '!items!yofwG0YrsL902G77' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:43.704474 7f54e37ef6c0 Manual compaction at level-1 from '!items!CoqlfsDV1gL5swbK' @ 72057594037927935 : 1 .. '!items!yofwG0YrsL902G77' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
BIN
packs/boonsflawscreatures/MANIFEST-001074
Normal file
BIN
packs/boonsflawscreatures/MANIFEST-001074
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs/careers/000772.ldb
Normal file
BIN
packs/careers/000772.ldb
Normal file
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000641
|
||||
MANIFEST-001074
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:46:20.429002 7f25b3fff6c0 Recovering log #639
|
||||
2024/12/12-21:46:20.557790 7f25b3fff6c0 Delete type=3 #637
|
||||
2024/12/12-21:46:20.557866 7f25b3fff6c0 Delete type=0 #639
|
||||
2024/12/12-21:50:13.940754 7f25b2ffd6c0 Level-0 table #644: started
|
||||
2024/12/12-21:50:13.940780 7f25b2ffd6c0 Level-0 table #644: 0 bytes OK
|
||||
2024/12/12-21:50:13.947933 7f25b2ffd6c0 Delete type=0 #642
|
||||
2024/12/12-21:50:13.954259 7f25b2ffd6c0 Manual compaction at level-0 from '!items!4S4xAfMXGnuU0O1a' @ 72057594037927935 : 1 .. '!items!zxY3sW0iCJBvwjOS' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:50:13.954302 7f25b2ffd6c0 Manual compaction at level-1 from '!items!4S4xAfMXGnuU0O1a' @ 72057594037927935 : 1 .. '!items!zxY3sW0iCJBvwjOS' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:53.759689 7f56f8bfd6c0 Recovering log #1072
|
||||
2026/02/28-22:59:53.770229 7f56f8bfd6c0 Delete type=3 #1070
|
||||
2026/02/28-22:59:53.770305 7f56f8bfd6c0 Delete type=0 #1072
|
||||
2026/03/01-01:08:46.327327 7f54e37ef6c0 Level-0 table #1077: started
|
||||
2026/03/01-01:08:46.327354 7f54e37ef6c0 Level-0 table #1077: 0 bytes OK
|
||||
2026/03/01-01:08:46.333262 7f54e37ef6c0 Delete type=0 #1075
|
||||
2026/03/01-01:08:46.339946 7f54e37ef6c0 Manual compaction at level-0 from '!items!4S4xAfMXGnuU0O1a' @ 72057594037927935 : 1 .. '!items!zxY3sW0iCJBvwjOS' @ 0 : 0; will stop at (end)
|
||||
2026/03/01-01:08:46.339979 7f54e37ef6c0 Manual compaction at level-1 from '!items!4S4xAfMXGnuU0O1a' @ 72057594037927935 : 1 .. '!items!zxY3sW0iCJBvwjOS' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:11:42.873685 7f25b97fa6c0 Recovering log #635
|
||||
2024/12/12-21:11:43.006883 7f25b97fa6c0 Delete type=3 #633
|
||||
2024/12/12-21:11:43.006940 7f25b97fa6c0 Delete type=0 #635
|
||||
2024/12/12-21:40:17.165812 7f25b2ffd6c0 Level-0 table #640: started
|
||||
2024/12/12-21:40:17.165866 7f25b2ffd6c0 Level-0 table #640: 0 bytes OK
|
||||
2024/12/12-21:40:17.172013 7f25b2ffd6c0 Delete type=0 #638
|
||||
2024/12/12-21:40:17.191170 7f25b2ffd6c0 Manual compaction at level-0 from '!items!4S4xAfMXGnuU0O1a' @ 72057594037927935 : 1 .. '!items!zxY3sW0iCJBvwjOS' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:40:17.191207 7f25b2ffd6c0 Manual compaction at level-1 from '!items!4S4xAfMXGnuU0O1a' @ 72057594037927935 : 1 .. '!items!zxY3sW0iCJBvwjOS' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-17:23:52.796426 7f56f9bff6c0 Recovering log #1068
|
||||
2026/02/28-17:23:52.805920 7f56f9bff6c0 Delete type=3 #1066
|
||||
2026/02/28-17:23:52.805973 7f56f9bff6c0 Delete type=0 #1068
|
||||
2026/02/28-22:59:43.711333 7f54e37ef6c0 Level-0 table #1073: started
|
||||
2026/02/28-22:59:43.711370 7f54e37ef6c0 Level-0 table #1073: 0 bytes OK
|
||||
2026/02/28-22:59:43.717336 7f54e37ef6c0 Delete type=0 #1071
|
||||
2026/02/28-22:59:43.731041 7f54e37ef6c0 Manual compaction at level-0 from '!items!4S4xAfMXGnuU0O1a' @ 72057594037927935 : 1 .. '!items!zxY3sW0iCJBvwjOS' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:43.731086 7f54e37ef6c0 Manual compaction at level-1 from '!items!4S4xAfMXGnuU0O1a' @ 72057594037927935 : 1 .. '!items!zxY3sW0iCJBvwjOS' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
BIN
packs/careers/MANIFEST-001074
Normal file
BIN
packs/careers/MANIFEST-001074
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs/effets-exemples/000770.ldb
Normal file
BIN
packs/effets-exemples/000770.ldb
Normal file
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000639
|
||||
MANIFEST-001072
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:46:22.297524 7f25b97fa6c0 Recovering log #637
|
||||
2024/12/12-21:46:22.422030 7f25b97fa6c0 Delete type=3 #635
|
||||
2024/12/12-21:46:22.422102 7f25b97fa6c0 Delete type=0 #637
|
||||
2024/12/12-21:50:14.036330 7f25b2ffd6c0 Level-0 table #642: started
|
||||
2024/12/12-21:50:14.036351 7f25b2ffd6c0 Level-0 table #642: 0 bytes OK
|
||||
2024/12/12-21:50:14.042312 7f25b2ffd6c0 Delete type=0 #640
|
||||
2024/12/12-21:50:14.062514 7f25b2ffd6c0 Manual compaction at level-0 from '!items!6fTZ6hOKR4pWbWOe' @ 72057594037927935 : 1 .. '!items!zwSNMO9HpiqUCMt8' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:50:14.062568 7f25b2ffd6c0 Manual compaction at level-1 from '!items!6fTZ6hOKR4pWbWOe' @ 72057594037927935 : 1 .. '!items!zwSNMO9HpiqUCMt8' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:53.948768 7f56f93fe6c0 Recovering log #1070
|
||||
2026/02/28-22:59:53.958702 7f56f93fe6c0 Delete type=3 #1068
|
||||
2026/02/28-22:59:53.958781 7f56f93fe6c0 Delete type=0 #1070
|
||||
2026/03/01-01:08:46.425514 7f54e37ef6c0 Level-0 table #1075: started
|
||||
2026/03/01-01:08:46.425561 7f54e37ef6c0 Level-0 table #1075: 0 bytes OK
|
||||
2026/03/01-01:08:46.431671 7f54e37ef6c0 Delete type=0 #1073
|
||||
2026/03/01-01:08:46.445290 7f54e37ef6c0 Manual compaction at level-0 from '!items!6fTZ6hOKR4pWbWOe' @ 72057594037927935 : 1 .. '!items!zwSNMO9HpiqUCMt8' @ 0 : 0; will stop at (end)
|
||||
2026/03/01-01:08:46.445328 7f54e37ef6c0 Manual compaction at level-1 from '!items!6fTZ6hOKR4pWbWOe' @ 72057594037927935 : 1 .. '!items!zwSNMO9HpiqUCMt8' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:11:44.902849 7f25b3fff6c0 Recovering log #633
|
||||
2024/12/12-21:11:45.032391 7f25b3fff6c0 Delete type=3 #631
|
||||
2024/12/12-21:11:45.032468 7f25b3fff6c0 Delete type=0 #633
|
||||
2024/12/12-21:40:17.243571 7f25b2ffd6c0 Level-0 table #638: started
|
||||
2024/12/12-21:40:17.243623 7f25b2ffd6c0 Level-0 table #638: 0 bytes OK
|
||||
2024/12/12-21:40:17.249629 7f25b2ffd6c0 Delete type=0 #636
|
||||
2024/12/12-21:40:17.269518 7f25b2ffd6c0 Manual compaction at level-0 from '!items!6fTZ6hOKR4pWbWOe' @ 72057594037927935 : 1 .. '!items!zwSNMO9HpiqUCMt8' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:40:17.269564 7f25b2ffd6c0 Manual compaction at level-1 from '!items!6fTZ6hOKR4pWbWOe' @ 72057594037927935 : 1 .. '!items!zwSNMO9HpiqUCMt8' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-17:23:52.970603 7f56f9bff6c0 Recovering log #1066
|
||||
2026/02/28-17:23:52.981835 7f56f9bff6c0 Delete type=3 #1064
|
||||
2026/02/28-17:23:52.981888 7f56f9bff6c0 Delete type=0 #1066
|
||||
2026/02/28-22:59:43.785498 7f54e37ef6c0 Level-0 table #1071: started
|
||||
2026/02/28-22:59:43.785523 7f54e37ef6c0 Level-0 table #1071: 0 bytes OK
|
||||
2026/02/28-22:59:43.792317 7f54e37ef6c0 Delete type=0 #1069
|
||||
2026/02/28-22:59:43.813749 7f54e37ef6c0 Manual compaction at level-0 from '!items!6fTZ6hOKR4pWbWOe' @ 72057594037927935 : 1 .. '!items!zwSNMO9HpiqUCMt8' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:43.813808 7f54e37ef6c0 Manual compaction at level-1 from '!items!6fTZ6hOKR4pWbWOe' @ 72057594037927935 : 1 .. '!items!zwSNMO9HpiqUCMt8' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
BIN
packs/effets-exemples/MANIFEST-001072
Normal file
BIN
packs/effets-exemples/MANIFEST-001072
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs/equipment/000773.ldb
Normal file
BIN
packs/equipment/000773.ldb
Normal file
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000642
|
||||
MANIFEST-001075
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:46:20.825829 7f25b97fa6c0 Recovering log #640
|
||||
2024/12/12-21:46:20.946944 7f25b97fa6c0 Delete type=3 #638
|
||||
2024/12/12-21:46:20.947007 7f25b97fa6c0 Delete type=0 #640
|
||||
2024/12/12-21:50:13.961670 7f25b2ffd6c0 Level-0 table #645: started
|
||||
2024/12/12-21:50:13.961702 7f25b2ffd6c0 Level-0 table #645: 0 bytes OK
|
||||
2024/12/12-21:50:13.967794 7f25b2ffd6c0 Delete type=0 #643
|
||||
2024/12/12-21:50:13.981101 7f25b2ffd6c0 Manual compaction at level-0 from '!items!0ErhyqifZLDCmMfT' @ 72057594037927935 : 1 .. '!items!yE8UH6YAgNGjKDEu' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:50:13.981151 7f25b2ffd6c0 Manual compaction at level-1 from '!items!0ErhyqifZLDCmMfT' @ 72057594037927935 : 1 .. '!items!yE8UH6YAgNGjKDEu' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:53.798832 7f56f9bff6c0 Recovering log #1073
|
||||
2026/02/28-22:59:53.809449 7f56f9bff6c0 Delete type=3 #1071
|
||||
2026/02/28-22:59:53.809533 7f56f9bff6c0 Delete type=0 #1073
|
||||
2026/03/01-01:08:46.340100 7f54e37ef6c0 Level-0 table #1078: started
|
||||
2026/03/01-01:08:46.340139 7f54e37ef6c0 Level-0 table #1078: 0 bytes OK
|
||||
2026/03/01-01:08:46.346846 7f54e37ef6c0 Delete type=0 #1076
|
||||
2026/03/01-01:08:46.366221 7f54e37ef6c0 Manual compaction at level-0 from '!items!0ErhyqifZLDCmMfT' @ 72057594037927935 : 1 .. '!items!yE8UH6YAgNGjKDEu' @ 0 : 0; will stop at (end)
|
||||
2026/03/01-01:08:46.366278 7f54e37ef6c0 Manual compaction at level-1 from '!items!0ErhyqifZLDCmMfT' @ 72057594037927935 : 1 .. '!items!yE8UH6YAgNGjKDEu' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2024/12/12-21:11:43.327343 7f25b37fe6c0 Recovering log #636
|
||||
2024/12/12-21:11:43.469585 7f25b37fe6c0 Delete type=3 #634
|
||||
2024/12/12-21:11:43.469659 7f25b37fe6c0 Delete type=0 #636
|
||||
2024/12/12-21:40:17.178441 7f25b2ffd6c0 Level-0 table #641: started
|
||||
2024/12/12-21:40:17.178475 7f25b2ffd6c0 Level-0 table #641: 0 bytes OK
|
||||
2024/12/12-21:40:17.185036 7f25b2ffd6c0 Delete type=0 #639
|
||||
2024/12/12-21:40:17.191191 7f25b2ffd6c0 Manual compaction at level-0 from '!items!0ErhyqifZLDCmMfT' @ 72057594037927935 : 1 .. '!items!yE8UH6YAgNGjKDEu' @ 0 : 0; will stop at (end)
|
||||
2024/12/12-21:40:17.191219 7f25b2ffd6c0 Manual compaction at level-1 from '!items!0ErhyqifZLDCmMfT' @ 72057594037927935 : 1 .. '!items!yE8UH6YAgNGjKDEu' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-17:23:52.834261 7f56f9bff6c0 Recovering log #1069
|
||||
2026/02/28-17:23:52.843912 7f56f9bff6c0 Delete type=3 #1067
|
||||
2026/02/28-17:23:52.843969 7f56f9bff6c0 Delete type=0 #1069
|
||||
2026/02/28-22:59:43.704672 7f54e37ef6c0 Level-0 table #1074: started
|
||||
2026/02/28-22:59:43.704745 7f54e37ef6c0 Level-0 table #1074: 0 bytes OK
|
||||
2026/02/28-22:59:43.711212 7f54e37ef6c0 Delete type=0 #1072
|
||||
2026/02/28-22:59:43.731026 7f54e37ef6c0 Manual compaction at level-0 from '!items!0ErhyqifZLDCmMfT' @ 72057594037927935 : 1 .. '!items!yE8UH6YAgNGjKDEu' @ 0 : 0; will stop at (end)
|
||||
2026/02/28-22:59:43.731077 7f54e37ef6c0 Manual compaction at level-1 from '!items!0ErhyqifZLDCmMfT' @ 72057594037927935 : 1 .. '!items!yE8UH6YAgNGjKDEu' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user