Compare commits
7 Commits
6c70dc147c
...
14.0.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 405bcd7cf5 | |||
| 846e6f88b7 | |||
| 1a0f4cd3e9 | |||
| 8ef5c3c516 | |||
| 0eb952e43e | |||
| a549262d25 | |||
| 7adc1b3f07 |
@@ -12,15 +12,13 @@ jobs:
|
|||||||
|
|
||||||
#- uses: actions/checkout@v3
|
#- uses: actions/checkout@v3
|
||||||
- uses: RouxAntoine/checkout@v3.5.4
|
- uses: RouxAntoine/checkout@v3.5.4
|
||||||
with:
|
|
||||||
ref: "v13"
|
|
||||||
|
|
||||||
# get part of the tag after the `v`
|
# get part of the tag after the `v`
|
||||||
- name: Extract tag version number
|
- name: Extract tag version number
|
||||||
id: get_version
|
id: get_version
|
||||||
uses: battila7/get-version-action@v2
|
uses: battila7/get-version-action@v2
|
||||||
|
|
||||||
# Substitute the Manifest and Download URLs in the module.json
|
# Substitute the Manifest and Download URLs in the system.json
|
||||||
- name: Substitute Manifest and Download Links For Versioned Ones
|
- name: Substitute Manifest and Download Links For Versioned Ones
|
||||||
id: sub_manifest_link_version
|
id: sub_manifest_link_version
|
||||||
uses: microsoft/variable-substitution@v1
|
uses: microsoft/variable-substitution@v1
|
||||||
@@ -28,9 +26,9 @@ jobs:
|
|||||||
files: "system.json"
|
files: "system.json"
|
||||||
env:
|
env:
|
||||||
version: ${{steps.get_version.outputs.version-without-v}}
|
version: ${{steps.get_version.outputs.version-without-v}}
|
||||||
url: https://www.uberwald.me/gitea/public/bol
|
url: https://www.uberwald.me/gitea/${{gitea.repository}}
|
||||||
manifest: https://www.uberwald.me/gitea/public/bol/releases/latest/system.json
|
manifest: https://www.uberwald.me/gitea/public/bol/releases/download/latest/system.json
|
||||||
download: https://www.uberwald.me/gitea/public/bol/releases/download/${{github.event.release.tag_name}}/bol.zip
|
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
|
# Create a zip file with all files required by the module to add to the release
|
||||||
- run: |
|
- run: |
|
||||||
@@ -51,4 +49,15 @@ jobs:
|
|||||||
files: |-
|
files: |-
|
||||||
./bol.zip
|
./bol.zip
|
||||||
system.json
|
system.json
|
||||||
api_key: "${{secrets.RELEASE_TOKEN_BOL}}"
|
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: "14"
|
||||||
|
|||||||
1
.gitignore
vendored
@@ -8,3 +8,4 @@ todo.md
|
|||||||
/jsconfig.json
|
/jsconfig.json
|
||||||
/package.json
|
/package.json
|
||||||
/package-lock.json
|
/package-lock.json
|
||||||
|
/.github
|
||||||
@@ -1,286 +0,0 @@
|
|||||||
# 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
|
|
||||||
BIN
assets/pages/help-en-attribute-dialog.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
assets/pages/help-en-command.png
Normal file
|
After Width: | Height: | Size: 151 KiB |
BIN
assets/pages/help-en-compendium.png
Normal file
|
After Width: | Height: | Size: 517 KiB |
BIN
assets/pages/help-en-effect-sheet.png
Normal file
|
After Width: | Height: | Size: 109 KiB |
BIN
assets/pages/help-en-initiative-dialog.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
assets/pages/help-en-sheet-actions.png
Normal file
|
After Width: | Height: | Size: 272 KiB |
BIN
assets/pages/help-en-sheet-attributes.png
Normal file
|
After Width: | Height: | Size: 275 KiB |
BIN
assets/pages/help-en-sheet-description.png
Normal file
|
After Width: | Height: | Size: 247 KiB |
BIN
assets/pages/help-en-sheet-equipment.png
Normal file
|
After Width: | Height: | Size: 248 KiB |
BIN
assets/pages/help-en-sheet-spells.png
Normal file
|
After Width: | Height: | Size: 242 KiB |
BIN
assets/pages/help-en-sheet-traits.png
Normal file
|
After Width: | Height: | Size: 274 KiB |
BIN
assets/pages/help-en-weapon-dialog.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
63
compendiums/en/bol.aides-de-jeu.json
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
"label": "Game Aid",
|
||||||
|
"mapping": {
|
||||||
|
"name": "name",
|
||||||
|
"description": "content",
|
||||||
|
"categories": {
|
||||||
|
"path": "categories",
|
||||||
|
"converter": "nameCollection"
|
||||||
|
},
|
||||||
|
"pages": {
|
||||||
|
"path": "pages",
|
||||||
|
"converter": "pages"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"entries": {
|
||||||
|
"Aide du Jeu": "Game Aid",
|
||||||
|
"8ihDiCxC47fcdKVA": {
|
||||||
|
"name": "Game Aid",
|
||||||
|
"pages": {
|
||||||
|
"8agBoLYo99u530d1": {
|
||||||
|
"name": "Credits",
|
||||||
|
"text": "<p>This system was started by Zigmund, then taken over, completed and maintained by LeRatierBretonnien.</p><p>You can contact me on the French Foundry Discord: LeRatierBretonnien#2065</p><p>The git repository is available here: <a href=\"https://www.uberwald.me/gitea/public/bol\">https://www.uberwald.me/gitea/public/bol</a></p><p>Barbarians of Lemuria is a game by Simon Washbourne (Beyond Belief Games), translated into French by Ludospherik.</p><p>The full range is available on this page: <a href=\"http://www.ludospherik.fr/content/14-barbarians-of-lemuria\">http://www.ludospherik.fr/content/14-barbarians-of-lemuria</a></p><img src=\"systems/bol/assets/pages/b9BjVFaWB6uyyKsD-pages-8agBoLYo99u530d1-image-Rg2nVaMlglfJ6Qcm.png\" />"
|
||||||
|
},
|
||||||
|
"NAcpMm6NlyhwvWRA": {
|
||||||
|
"name": "Features",
|
||||||
|
"text": "<p>The BoL system under Foundry allows you to:</p><ul><li><p>create characters and NPCs (minions, toughs, rivals),</p></li><li><p>create creatures,</p></li><li><p>make dice rolls for attributes, aptitudes, and careers,</p></li><li><p>make dice rolls for combat attacks,</p></li><li><p>manage initiative,</p></li><li><p>make dice rolls to cast spells or perform alchemical recipes,</p></li><li><p>manage damage and lifeblood loss,</p></li><li><p>display and manage automations in chat windows, with assistance for the use of Hero Points and critical successes.</p></li></ul>"
|
||||||
|
},
|
||||||
|
"hdQixhZGfAytdbSg": {
|
||||||
|
"name": "Compendiums",
|
||||||
|
"text": "<p>The system comes with a series of compendiums providing quick access to careers, boons, and equipment.</p><p>The official cards are available, with the kind permission of Ludospherik.</p><p>To use content from a compendium, simply drag and drop the item into the world. For example: open the armours compendium, select <em>Light Armour</em>, and drag it onto a character sheet.</p><img src=\"systems/bol/assets/pages/help-en-compendium.png\" />"
|
||||||
|
},
|
||||||
|
"UfvTY80U49k6YFwe": {
|
||||||
|
"name": "Dice Rolls (Attributes/Aptitudes)",
|
||||||
|
"text": "<p>When a player clicks an attribute or aptitude, the following window appears:</p><img src=\"systems/bol/assets/pages/help-en-attribute-dialog.png\" /><ol><li><p>Attribute the player clicked on. It can be changed with this drop-down menu.</p></li><li><p>Career to apply if needed. Left-click to select, CTRL+left-click to deselect. When selected, the career rank is applied.</p></li><li><p>Available boons (i.e. those that grant a bonus die). Selection mode is identical to careers. When selected, the bonus die is applied to the roll.</p></li><li><p>Available flaws (i.e. those that impose a penalty die). Selection mode is identical to careers. When selected, the penalty die is applied to the roll.</p></li><li><p>Effects. Effects are permanent modifiers that affect certain rolls. See the corresponding chapter.</p></li><li><p>Manual addition of penalty or bonus dice.</p></li><li><p>Manual modifiers, according to the GM's ruling.</p></li><li><p>Reminder of the number of dice, based on the choices made in the dialog.</p></li><li><p>Complete list of modifiers applied to the roll.</p></li></ol>"
|
||||||
|
},
|
||||||
|
"4CLyyt3dtpG6YNMi": {
|
||||||
|
"name": "Dice Rolls (Weapon)",
|
||||||
|
"text": "<p>To make an attack with a weapon, go to the <strong>Actions</strong> tab and click the weapon's name. Targeting an opponent is recommended in order to take advantage of the system automations.</p><img src=\"systems/bol/assets/pages/help-en-weapon-dialog.png\" /><ol><li><p>Default weapon attribute. It can be changed with this drop-down menu.</p></li><li><p>Default weapon aptitude. It can be changed with this drop-down menu.</p></li><li><p>Possible weapon bonus on the attack roll.</p></li><li><p>Target defence, when an opponent is targeted.</p></li><li><p>Career to apply if needed. Left-click to select, CTRL+left-click to deselect. When selected, the career rank is applied.</p></li><li><p>Available boons (i.e. those that grant a bonus die). Selection mode is identical to careers. When selected, the bonus die is applied to the roll.</p></li><li><p>Available flaws (i.e. those that impose a penalty die). Selection mode is identical to careers. When selected, the penalty die is applied to the roll.</p></li><li><p>Effects. Effects are permanent modifiers that affect certain rolls. See the corresponding chapter.</p></li><li><p>Manual addition of penalty or bonus dice.</p></li><li><p>Information area if the weapon has the <em>Bonus Die</em> option enabled.</p></li><li><p>Agility penalty from armour and shield.</p></li><li><p>Manual modifiers, according to the GM's ruling.</p></li><li><p>Reminder of the number of dice, based on the choices made in the dialog.</p></li><li><p>Complete list of modifiers applied to the roll.</p></li></ol>"
|
||||||
|
},
|
||||||
|
"r003R5yIaiKxThOc": {
|
||||||
|
"name": "Character Sheet",
|
||||||
|
"text": "<h2>Attributes</h2><img src=\"systems/bol/assets/pages/help-en-sheet-attributes.png\" /><ol><li><p>Name + Experience area.</p></li><li><p>Tab bar for moving between sections.</p></li><li><p>Attributes area. Clicking a name opens the roll dialog, clicking a number allows editing.</p></li><li><p>Aptitudes area, same idea as attributes.</p></li><li><p>Counters area. The red value is the current one, the black value underneath is the maximum.</p></li></ol><h2>Actions</h2><img src=\"systems/bol/assets/pages/help-en-sheet-actions.png\" /><ol><li><p>Weapons. Clicking the name opens the attack dialog for that weapon.</p></li><li><p>Damage. Clicking the damage formula rolls it.</p></li><li><p>List of protections.</p></li><li><p>Clicking the protection formula rolls it.</p></li><li><p>List of shields.</p></li><li><p>Combat options the character knows. Once activated, they appear in the weapon attack dialog.</p></li></ol><h2>Traits</h2><img src=\"systems/bol/assets/pages/help-en-sheet-traits.png\" /><ol><li><p>List of careers. Left-click a career for details.</p></li><li><p>Career rank helper.</p></li><li><p>List of origins. Left-click for details.</p></li><li><p>List of boons. Left-click for details.</p></li><li><p>List of flaws. Left-click for details.</p></li><li><p>List of spoken languages. Left-click for details.</p></li><li><p>List of known combat options. Left-click for details.</p></li><li><p>List of beliefs. Left-click for details.</p></li><li><p>List of active effects. Left-click for details.</p></li></ol><h2>Equipment</h2><img src=\"systems/bol/assets/pages/help-en-sheet-equipment.png\" /><ol><li><p>Quick equipment creation controls.</p></li><li><p>Purse state (optional rule, system setting).</p></li><li><p>Weapons, with quantity management.</p></li><li><p>Shield equip / unequip control.</p></li><li><p>List of protections.</p></li><li><p>Armour equip / unequip control.</p></li></ol><h2>Spells & Alchemy</h2><p>This tab is only available if the character has the Alchemist or Sorcerer career.</p><img src=\"systems/bol/assets/pages/help-en-sheet-spells.png\" /><ol><li><p>List of spells. Left-click the name to open the dedicated roll dialog.</p></li><li><p>Reminder of circle and difficulty.</p></li><li><p>The square button opens the spell details.</p></li><li><p>List of known alchemical preparations.</p></li><li><p>Crafting progress management.</p></li><li><p>The square button opens the preparation details.</p></li></ol><h2>Description</h2><img src=\"systems/bol/assets/pages/help-en-sheet-description.png\" /><p>The description area contains free-form fields for customising the character.</p>"
|
||||||
|
},
|
||||||
|
"eRbEqbCW4AhU0cpm": {
|
||||||
|
"name": "Effects",
|
||||||
|
"text": "<p>Effects allow permanent modifiers to be applied as long as they are present on the character sheet.</p><p><span style=\"text-decoration:underline\"><span style=\"text-decoration:underline\">Example</span></span>: a character is poisoned, and the poison causes mental fatigue. In game terms, they suffer a -2 penalty to all Mind rolls. To represent this, create an <em>Effect</em> like this:</p><img src=\"systems/bol/assets/pages/help-en-effect-sheet.png\" /><ol><li><p>Create a <em>Trait</em>, and in the <em>Details</em> tab select the subtype <em>Effect</em>.</p></li><li><p>Select <em>Mind</em>.</p></li><li><p>Set a -2 modifier.</p></li></ol><p>Once placed on a character, the penalty is automatically applied whenever a Mind roll is requested. Remove the effect from the character sheet (<em>Traits</em> tab) to remove both the effect and its penalty.<br />A compendium of basic effects is available in the system.</p>"
|
||||||
|
},
|
||||||
|
"QmNF6p0lJf3pJoAy": {
|
||||||
|
"name": "Commands",
|
||||||
|
"text": "<p>The system provides commands (currently just one) for a few automated tasks.</p><p><strong><span style=\"text-decoration:underline\">This command is only available if the BoL-rulebook module is installed.</span></strong></p><h3>/adventure command</h3><img src=\"systems/bol/assets/pages/help-en-command.png\" /><ol><li><p>Type <code>/adventure</code> in the chat input area (or trigger it from a macro).</p></li><li><p>The system generates an adventure from the core rulebook tables and posts the result in chat.</p></li></ol>"
|
||||||
|
},
|
||||||
|
"MOWru5Dbvs4iozXm": {
|
||||||
|
"name": "Macros",
|
||||||
|
"text": "<p>The system exposes macros through <code>game.bol.macros</code>. They provide quick access to the most common rolls from a Foundry macro.</p><p><strong>Automatic actor selection:</strong></p><ul><li><p>if exactly one token is selected, the macro uses it;</p></li><li><p>if several tokens are selected, the macro shows a warning;</p></li><li><p>if no token is selected, a GM must select one; a player automatically falls back to their assigned character.</p></li></ul><p><strong>Available rolls</strong></p><p>Attributes (internal keys):</p><pre><code>game.bol.macros.rollAttribute(\"vigor\")\ngame.bol.macros.rollAttribute(\"agility\")\ngame.bol.macros.rollAttribute(\"mind\")\ngame.bol.macros.rollAttribute(\"appeal\")</code></pre><p>Aptitudes:</p><pre><code>game.bol.macros.rollAptitude(\"init\")\ngame.bol.macros.rollAptitude(\"melee\")\ngame.bol.macros.rollAptitude(\"ranged\")\ngame.bol.macros.rollAptitude(\"def\")</code></pre><p>Weapons, spells, and alchemy:</p><pre><code>game.bol.macros.rollWeapon(\"Spear\")\ngame.bol.macros.rollWeapon(0)\n\ngame.bol.macros.rollSpell(\"Javelin\")\ngame.bol.macros.rollSpell(0)\n\ngame.bol.macros.rollAlchemy(\"Fire\")\ngame.bol.macros.rollAlchemy(0)</code></pre><p>For weapons, spells, and alchemical preparations, name lookup is <strong>partial</strong> and <strong>case-insensitive</strong>. You may also use a numeric index.</p><p>Horoscope:</p><pre><code>game.bol.macros.rollHoroscope(\"minor\")\ngame.bol.macros.rollHoroscope(\"major\")</code></pre><p><strong>Generic macro</strong></p><pre><code>game.bol.macros.roll(\"attribute\", \"vigor\")\ngame.bol.macros.roll(\"aptitude\", \"melee\")\ngame.bol.macros.roll(\"weapon\", \"Spear\")\ngame.bol.macros.roll(\"spell\", \"Javelin\")\ngame.bol.macros.roll(\"alchemy\", 0)\ngame.bol.macros.roll(\"horoscope\", \"minor\")</code></pre><p><strong>Compatibility</strong></p><p>The legacy entry point <code>game.bol.macros.rollMacro(type, key)</code> is still available for existing macros.</p>"
|
||||||
|
},
|
||||||
|
"rERizrPxSAsvsZY2": {
|
||||||
|
"name": "Initiative",
|
||||||
|
"text": "<p>In BoL, initiative is rolled once at the start of combat.</p><p>You can request it automatically through the Combat Tracker, or roll Initiative manually and tick the corresponding box in the dialog:</p><img src=\"systems/bol/assets/pages/help-en-initiative-dialog.png\" /><p>According to the roll result, an initiative rank from 10 to 3 is assigned as follows:</p><p><strong>10</strong> - PC: Legendary Success<br /><strong>9</strong> - PC: Heroic Success<br /><strong>8</strong> - PC: Normal Success<br /><strong>7</strong> - NPC: Opponents or creatures larger than medium size<br /><strong>6</strong> - NPC: Toughs or creatures of medium size or smaller<br /><strong>5</strong> - PC: Normal Failure<br /><strong>4</strong> - NPC: Minions<br /><strong>3</strong> - PC: Critical Failure</p>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,30 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"entries": {
|
"entries": {
|
||||||
|
"Arc de guerre de Tyrus": {
|
||||||
|
"name": "Tyrus Warbow",
|
||||||
|
"description": "<h1>Tyrus Warbow</h1><p> The archers of Tyrus train from a very young age in the use of this powerful bow. Tyrus archers have fun with other warriors by lending their bows to them and then watching them struggle to aim at the proverbial “barn door”.</p>"
|
||||||
|
},
|
||||||
|
"Épée Valgardienne (1 Main)": {
|
||||||
|
"name": "Valgardian Blade (1H)",
|
||||||
|
"description": "<h1>Valgardian Blade (1H)</h1><p>Around 3’-4’ in length, the Valgardian blade is used either in one hand or in both. The Valgardian bladesmiths guard the secret of their work closely, although many have tried to copy it. It is rumoured that the strength of the blades due mainly to the quality of the iron mined locally.</p>"
|
||||||
|
},
|
||||||
|
"Épée Valgardienne (2 mains)": {
|
||||||
|
"name": "Valgardian Blade (2H)",
|
||||||
|
"description": "<h1>Valgardian Blade (2H)</h1><p>Around 3’-4’ in length, the Valgardian blade is used either in one hand or in both. The Valgardian bladesmiths guard the secret of their work closely, although many have tried to copy it. It is rumoured that the strength of the blades due mainly to the quality of the iron mined locally.</p>"
|
||||||
|
},
|
||||||
|
"Fronde de l’Axos": {
|
||||||
|
"name": "Axish Sling",
|
||||||
|
"description": "<h1>Axish Sling</h1><p>Sling: The sling is inexpensive and easy to build. It is a simple leather thong whirled around the head to cast small stones or cast lead bullets with some force, at 30’ range increments. Two-handed versions are fitted onto a staff and are called staff-slings. This imparts a greater range, making the increments 60’. The Axish sling is actually little different to any other common sling; it’s just that the people of the Axos mountains are particularly proficient with them. They have however played up the idea that there is some special plant fibre that the thongs are made from that gives them their extra range.</p>"
|
||||||
|
},
|
||||||
|
"Hache d’abordage de Parsool (1 main)": {
|
||||||
|
"name": "Parsool Sea Axe (1H)",
|
||||||
|
"description": "<h1>Parsool Sea Axe (1H)</h1><p>A boarding axe used by Parsool seamen which can be used one or two-handed.</p>"
|
||||||
|
},
|
||||||
|
"Hache d’abordage de Parsool (2 mains)": {
|
||||||
|
"name": "Parsool Sea Axe (2H)",
|
||||||
|
"description": "<h1>Parsool Sea Axe (2H)</h1><p>A boarding axe used by Parsool seamen which can be used one or two-handed.</p>"
|
||||||
|
},
|
||||||
"Arbalète": {
|
"Arbalète": {
|
||||||
"name": "Crossbow",
|
"name": "Crossbow",
|
||||||
"description": "<h1>Crossbow</h1><p>A crossbow is a simple device for firing a short bolt or quarrel with some force and little training. They take a round to load (ready to fire on the second round).</p>"
|
"description": "<h1>Crossbow</h1><p>A crossbow is a simple device for firing a short bolt or quarrel with some force and little training. They take a round to load (ready to fire on the second round).</p>"
|
||||||
|
|||||||
59
css/bol.css
@@ -1113,6 +1113,49 @@ h2.bad {
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
.chat-message .bol-damage-card .damage-target-select-label,
|
||||||
|
.chat-message .bol-defense-card .damage-target-select-label {
|
||||||
|
font-size: 0.78rem;
|
||||||
|
color: #7a0000;
|
||||||
|
font-family: "Wolfsbane2Expanded", cursive;
|
||||||
|
letter-spacing: 0.4px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
.chat-message .bol-damage-card .chat-target-select,
|
||||||
|
.chat-message .bol-defense-card .chat-target-select {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
padding: 3px 8px;
|
||||||
|
background: linear-gradient(135deg, #f5f0e8, #ede4d4);
|
||||||
|
border: 1px solid #c4a882;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #191813;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
cursor: pointer;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.chat-message .bol-damage-card .chat-target-select:hover,
|
||||||
|
.chat-message .bol-defense-card .chat-target-select:hover {
|
||||||
|
background: linear-gradient(135deg, #7a0000, darkred);
|
||||||
|
color: #e8d890;
|
||||||
|
border-color: #7a0000;
|
||||||
|
}
|
||||||
|
.chat-message .bol-damage-card .chat-target-select:hover .damage-target-icon,
|
||||||
|
.chat-message .bol-defense-card .chat-target-select:hover .damage-target-icon {
|
||||||
|
border-color: #e8d890;
|
||||||
|
}
|
||||||
|
.chat-message .bol-damage-card .chat-target-select .damage-target-icon,
|
||||||
|
.chat-message .bol-defense-card .chat-target-select .damage-target-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #c4a882;
|
||||||
|
object-fit: cover;
|
||||||
|
flex: 0 0 24px;
|
||||||
|
}
|
||||||
.chat-message .bol-damage-card .damage-note,
|
.chat-message .bol-damage-card .damage-note,
|
||||||
.chat-message .bol-defense-card .damage-note {
|
.chat-message .bol-defense-card .damage-note {
|
||||||
font-size: 0.78rem;
|
font-size: 0.78rem;
|
||||||
@@ -1521,6 +1564,18 @@ body.system-bol img#logo {
|
|||||||
color: #191813;
|
color: #191813;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
.bol.dialog .roll-dialog-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 0 8px;
|
||||||
|
align-items: start;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
.bol.dialog .roll-col {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
.bol.dialog .roll-box,
|
.bol.dialog .roll-box,
|
||||||
.bol.dialog .box-roll,
|
.bol.dialog .box-roll,
|
||||||
.bol.dialog div.flexrow:has(.bg-darkred) {
|
.bol.dialog div.flexrow:has(.bg-darkred) {
|
||||||
@@ -1583,8 +1638,8 @@ body.system-bol img#logo {
|
|||||||
.bol.dialog select option:hover,
|
.bol.dialog select option:hover,
|
||||||
.bol.dialog input[type="text"] option:hover,
|
.bol.dialog input[type="text"] option:hover,
|
||||||
.bol.dialog input[type="number"] option:hover {
|
.bol.dialog input[type="number"] option:hover {
|
||||||
background: darkred;
|
background: darkred !important;
|
||||||
color: white;
|
color: white !important;
|
||||||
}
|
}
|
||||||
.bol.dialog input:disabled {
|
.bol.dialog input:disabled {
|
||||||
color: #8b0000 !important;
|
color: #8b0000 !important;
|
||||||
|
|||||||
@@ -478,6 +478,7 @@
|
|||||||
"BOL.chat.damageresult": "Damages of {name} : {total}",
|
"BOL.chat.damageresult": "Damages of {name} : {total}",
|
||||||
"BOL.chat.damagetarget": "Target : {target}",
|
"BOL.chat.damagetarget": "Target : {target}",
|
||||||
"BOL.chat.applydamagetotarget": "Apply damages to the target",
|
"BOL.chat.applydamagetotarget": "Apply damages to the target",
|
||||||
|
"BOL.chat.selecttarget": "Choose a target:",
|
||||||
"BOL.chat.fightoption": "Combat options",
|
"BOL.chat.fightoption": "Combat options",
|
||||||
"BOL.chat.reroll": "Reroll (1 HP)",
|
"BOL.chat.reroll": "Reroll (1 HP)",
|
||||||
"BOL.chat.heroicreminder": "In addition of the actions below, you can : <ul><li>Carnage : Do a second free attack on the same opponent</li><li>Precise : 1 Malus Die on your opponent on a chosen location</li><li>Disarm</li><li>Rabble Massacre</li><li>Prone : Push your opponent on the ground (max +1 size)</li></ul>If you spent 1 Hero Point in addition, all these effects can be doubled.",
|
"BOL.chat.heroicreminder": "In addition of the actions below, you can : <ul><li>Carnage : Do a second free attack on the same opponent</li><li>Precise : 1 Malus Die on your opponent on a chosen location</li><li>Disarm</li><li>Rabble Massacre</li><li>Prone : Push your opponent on the ground (max +1 size)</li></ul>If you spent 1 Hero Point in addition, all these effects can be doubled.",
|
||||||
|
|||||||
@@ -506,6 +506,7 @@
|
|||||||
"BOL.chat.damageresult": "Dommages de {name} : {total}",
|
"BOL.chat.damageresult": "Dommages de {name} : {total}",
|
||||||
"BOL.chat.damagetarget": "Cible : {target}",
|
"BOL.chat.damagetarget": "Cible : {target}",
|
||||||
"BOL.chat.applydamagetotarget": "Appliquer les dommages à la cible",
|
"BOL.chat.applydamagetotarget": "Appliquer les dommages à la cible",
|
||||||
|
"BOL.chat.selecttarget": "Choisir une cible :",
|
||||||
"BOL.chat.fightoption": "Option de combat",
|
"BOL.chat.fightoption": "Option de combat",
|
||||||
"BOL.chat.reroll": "Relancer (1 P. Heroisme)",
|
"BOL.chat.reroll": "Relancer (1 P. Heroisme)",
|
||||||
"BOL.chat.heroicreminder": "En plus des actions indiquées sur les boutons ci-dessous, vous pouvez : <ul><li>Carnage : Attaquer une seconde fois le même adversaire</li><li>Coup précis : Un dé de malus à votre adversaire sur une localisation choisie</li><li>Désarmement</li><li>Massacrer la piétaille</li><li>Renversement : Renversez votre adversaire (1 taille de plus max)</li></ul>Si vous dépensez un Point d'Héroisme en plus, tout ces effets peuvent être doublés",
|
"BOL.chat.heroicreminder": "En plus des actions indiquées sur les boutons ci-dessous, vous pouvez : <ul><li>Carnage : Attaquer une seconde fois le même adversaire</li><li>Coup précis : Un dé de malus à votre adversaire sur une localisation choisie</li><li>Désarmement</li><li>Massacrer la piétaille</li><li>Renversement : Renversez votre adversaire (1 taille de plus max)</li></ul>Si vous dépensez un Point d'Héroisme en plus, tout ces effets peuvent être doublés",
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ export class BoLActor extends Actor {
|
|||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
alias: this.name,
|
alias: this.name,
|
||||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
|
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
|
||||||
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 })
|
content: await foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/chat-activate-fight-option.hbs', { name: this.name, img: fightOption.img, foName: fightOption.name, state: state })
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -877,7 +877,7 @@ export class BoLActor extends Actor {
|
|||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
alias: this.name,
|
alias: this.name,
|
||||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(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() })
|
content: await 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 {
|
} else {
|
||||||
if (prone) {
|
if (prone) {
|
||||||
@@ -912,7 +912,7 @@ export class BoLActor extends Actor {
|
|||||||
let msg = await ChatMessage.create({
|
let msg = await ChatMessage.create({
|
||||||
alias: this.name,
|
alias: this.name,
|
||||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
|
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
|
||||||
content: await foundry.applications.handlebars.foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/chat-recup-information.hbs', {
|
content: await foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/chat-recup-information.hbs', {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
img: this.img,
|
img: this.img,
|
||||||
actorId: this.id,
|
actorId: this.id,
|
||||||
|
|||||||
@@ -191,6 +191,11 @@ export class BoLRoll {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
alchemy = foundry.utils.duplicate(alchemy)
|
alchemy = foundry.utils.duplicate(alchemy)
|
||||||
|
return this.alchemyCheckWithItem(actor, alchemy)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static alchemyCheckWithItem(actor, alchemy) {
|
||||||
let alchemyData = alchemy.system
|
let alchemyData = alchemy.system
|
||||||
if (alchemyData.properties.pccurrent < alchemyData.properties.pccost) {
|
if (alchemyData.properties.pccurrent < alchemyData.properties.pccost) {
|
||||||
ui.notifications.warn("Pas assez de Points de Création investis dans la Préparation !")
|
ui.notifications.warn("Pas assez de Points de Création investis dans la Préparation !")
|
||||||
@@ -747,6 +752,12 @@ export class BoLDefaultRoll {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async sendDamageMessage() {
|
async sendDamageMessage() {
|
||||||
let actor = BoLUtility.getActorFromRollData(this.rollData)
|
let actor = BoLUtility.getActorFromRollData(this.rollData)
|
||||||
|
// If no target, collect potential targets from active scene (excluding attacker)
|
||||||
|
if (!this.rollData.targetId && game.scenes.current) {
|
||||||
|
this.rollData.potentialTargets = game.scenes.current.tokens
|
||||||
|
.filter(t => t.actor && t.actor.id !== this.rollData.actorId)
|
||||||
|
.map(t => ({ id: t.id, actorId: t.actor.id, name: t.name, img: t.texture?.src || t.actor.img }))
|
||||||
|
}
|
||||||
this._buildDamageChatMessage(this.rollData).then(async msgFlavor => {
|
this._buildDamageChatMessage(this.rollData).then(async msgFlavor => {
|
||||||
let msg = await this.rollData.damageRoll.toMessage({
|
let msg = await this.rollData.damageRoll.toMessage({
|
||||||
user: game.user.id,
|
user: game.user.id,
|
||||||
|
|||||||
@@ -1,119 +0,0 @@
|
|||||||
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()]);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
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()]);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -395,6 +395,16 @@ export class BoLUtility {
|
|||||||
BoLUtility.sendAttackSuccess(rollData)
|
BoLUtility.sendAttackSuccess(rollData)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
html.on("click", '.chat-target-select', event => {
|
||||||
|
event.preventDefault()
|
||||||
|
const btn = event.currentTarget
|
||||||
|
let rollData = BoLUtility.getRollDataFromMessage(event)
|
||||||
|
rollData.targetId = btn.dataset.tokenId
|
||||||
|
rollData.defenderId = btn.dataset.actorId
|
||||||
|
BoLUtility.cleanupButtons(rollData.applyId)
|
||||||
|
BoLUtility.sendAttackSuccess(rollData)
|
||||||
|
});
|
||||||
|
|
||||||
html.on("click", '.chat-damage-roll', event => {
|
html.on("click", '.chat-damage-roll', event => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
let rollData = BoLUtility.getRollDataFromMessage(event)
|
let rollData = BoLUtility.getRollDataFromMessage(event)
|
||||||
@@ -554,13 +564,13 @@ export class BoLUtility {
|
|||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
alias: defender.name,
|
alias: defender.name,
|
||||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(defender.name),
|
whisper: BoLUtility.getWhisperRecipientsAndGMs(defender.name),
|
||||||
content: await foundry.applications.handlebars.foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/rolls/defense-result-card.hbs', damageResults)
|
content: await foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/rolls/defense-result-card.hbs', damageResults)
|
||||||
})
|
})
|
||||||
console.log("Defender data : ", defenderUser)
|
console.log("Defender data : ", defenderUser)
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
alias: defender.name,
|
alias: defender.name,
|
||||||
whisper: BoLUtility.getOtherWhisperRecipients(defenderUser?.name),
|
whisper: BoLUtility.getOtherWhisperRecipients(defenderUser?.name),
|
||||||
content: await foundry.applications.handlebars.foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/rolls/defense-summary-card.hbs', damageResults)
|
content: await foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/rolls/defense-summary-card.hbs', damageResults)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -647,7 +657,7 @@ export class BoLUtility {
|
|||||||
let msg = await ChatMessage.create({
|
let msg = await ChatMessage.create({
|
||||||
alias: defender.name,
|
alias: defender.name,
|
||||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(defender.name),
|
whisper: BoLUtility.getWhisperRecipientsAndGMs(defender.name),
|
||||||
content: await foundry.applications.handlebars.foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/rolls/defense-request-card.hbs', {
|
content: await foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/rolls/defense-request-card.hbs', {
|
||||||
attackId: rollData.id,
|
attackId: rollData.id,
|
||||||
attacker: rollData.attacker,
|
attacker: rollData.attacker,
|
||||||
defender: defender,
|
defender: defender,
|
||||||
|
|||||||
@@ -1,52 +1,228 @@
|
|||||||
import {BoLRoll} from "../controllers/bol-rolls.js";
|
import { BoLRoll } from "../controllers/bol-rolls.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BoL Macro API — accessible via game.bol.macros
|
||||||
|
*
|
||||||
|
* Usage examples (in a Foundry macro):
|
||||||
|
*
|
||||||
|
* game.bol.macros.rollAttribute("vigor")
|
||||||
|
* game.bol.macros.rollAttribute("mind")
|
||||||
|
*
|
||||||
|
* game.bol.macros.rollAptitude("melee")
|
||||||
|
* game.bol.macros.rollAptitude("ranged")
|
||||||
|
* game.bol.macros.rollAptitude("def")
|
||||||
|
* game.bol.macros.rollAptitude("init")
|
||||||
|
*
|
||||||
|
* game.bol.macros.rollWeapon("Épée courte") // by name (partial match)
|
||||||
|
* game.bol.macros.rollWeapon(0) // by index (first weapon)
|
||||||
|
*
|
||||||
|
* game.bol.macros.rollSpell("Boule de feu") // by name (partial match)
|
||||||
|
* game.bol.macros.rollSpell(0) // by index
|
||||||
|
*
|
||||||
|
* game.bol.macros.rollAlchemy("Potion de soin") // by name (partial match)
|
||||||
|
* game.bol.macros.rollAlchemy(0) // by index
|
||||||
|
*
|
||||||
|
* game.bol.macros.rollHoroscope("minor")
|
||||||
|
* game.bol.macros.rollHoroscope("major")
|
||||||
|
*
|
||||||
|
* // Generic dispatcher:
|
||||||
|
* game.bol.macros.roll("attribute", "vigor")
|
||||||
|
* game.bol.macros.roll("aptitude", "melee")
|
||||||
|
* game.bol.macros.roll("weapon", "Épée courte")
|
||||||
|
* game.bol.macros.roll("spell", "Boule de feu")
|
||||||
|
* game.bol.macros.roll("alchemy", 0)
|
||||||
|
* game.bol.macros.roll("horoscope", "minor")
|
||||||
|
*/
|
||||||
export class Macros {
|
export class Macros {
|
||||||
/**
|
|
||||||
* @name getSpeakersActor
|
|
||||||
* @description
|
|
||||||
*
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
static getSpeakersActor = function(){
|
|
||||||
// Vérifie qu'un seul token est sélectionné
|
|
||||||
const tokens = canvas.tokens.controlled;
|
|
||||||
if (tokens.length > 1) {
|
|
||||||
ui.notifications.warn(game.i18n.localize('BOL.notification.MacroMultipleTokensSelected'));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const speaker = ChatMessage.getSpeaker();
|
/* -------------------------------------------- */
|
||||||
let actor;
|
/**
|
||||||
// Si un token est sélectionné, le prendre comme acteur cible
|
* Resolves the actor for macro use:
|
||||||
if (speaker.token) actor = game.actors.tokens[speaker.token];
|
* - If multiple tokens are selected → error (always)
|
||||||
// Sinon prendre l'acteur par défaut pour l'utilisateur courrant
|
* - If exactly one token is selected → use it (GM or player)
|
||||||
if (!actor) actor = game.actors.get(speaker.actor);
|
* - If no token selected and user is GM → error (GM must select a token)
|
||||||
return actor;
|
* - If no token selected and user is a player → use their assigned character
|
||||||
|
* @returns {Actor|null}
|
||||||
|
*/
|
||||||
|
static getSpeakersActor() {
|
||||||
|
const tokens = canvas.tokens?.controlled ?? []
|
||||||
|
|
||||||
|
if (tokens.length > 1) {
|
||||||
|
ui.notifications.warn(game.i18n.localize('BOL.notification.MacroMultipleTokensSelected'))
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
static rollMacro = async function (rollType, key, adv, mod){
|
if (tokens.length === 1) {
|
||||||
const actor = this.getSpeakersActor();
|
return tokens[0].actor ?? null
|
||||||
// Several tokens selected
|
|
||||||
if (actor === null) return;
|
|
||||||
// No token selected
|
|
||||||
if (actor === undefined) return ui.notifications.error(game.i18n.localize("BOL.notification.MacroNoTokenSelected"));
|
|
||||||
|
|
||||||
const actorData = {};
|
|
||||||
actorData.data = {
|
|
||||||
features : actor.buildFeatures()
|
|
||||||
};
|
|
||||||
|
|
||||||
if(rollType === "attribute") {
|
|
||||||
let attribute = eval(`actor.system.attributes.${key}`);
|
|
||||||
let rollLabel = (attribute.label) ? game.i18n.localize(attribute.label) : null;
|
|
||||||
let description = actor.name + " - " + game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label) ;
|
|
||||||
BoLRoll.attributeRollDialog(actor, actorData, attribute, rollLabel, description, adv, mod);
|
|
||||||
}
|
|
||||||
else if(rollType === "aptitude") {
|
|
||||||
let aptitude = eval(`actor.system.aptitudes.${key}`);
|
|
||||||
let rollLabel = (aptitude.label) ? game.i18n.localize(aptitude.label) : null;
|
|
||||||
let description = actor.name + " - " + game.i18n.localize('BOL.ui.aptitudeCheck') + " - " + game.i18n.localize(aptitude.label) ;
|
|
||||||
BoLRoll.aptitudeRollDialog(actor, actorData, aptitude, rollLabel, description, adv, mod);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No token selected
|
||||||
|
if (game.user.isGM) {
|
||||||
|
ui.notifications.error(game.i18n.localize("BOL.notification.MacroNoTokenSelected"))
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Player: fall back to their assigned character
|
||||||
|
const actor = game.user.character
|
||||||
|
if (!actor) {
|
||||||
|
ui.notifications.error(game.i18n.localize("BOL.notification.MacroNoTokenSelected"))
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return actor
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* Finds an item on an actor by name (partial, case-insensitive) or index.
|
||||||
|
* @param {Actor} actor
|
||||||
|
* @param {string} type - item type: "weapon", "spell", "alchemy"
|
||||||
|
* @param {string|number} nameOrIndex
|
||||||
|
* @returns {object|undefined}
|
||||||
|
*/
|
||||||
|
static _findItem(actor, type, nameOrIndex) {
|
||||||
|
const items = actor.items.filter(i => i.type === type)
|
||||||
|
if (items.length === 0) {
|
||||||
|
ui.notifications.warn(`${actor.name} : aucun(e) ${type} trouvé(e).`)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
if (nameOrIndex === undefined || nameOrIndex === null) {
|
||||||
|
if (items.length === 1) return foundry.utils.duplicate(items[0])
|
||||||
|
const names = items.map((it, i) => `[${i}] ${it.name}`).join(', ')
|
||||||
|
ui.notifications.warn(`Précisez le nom ou l'index : ${names}`)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
if (typeof nameOrIndex === "number") {
|
||||||
|
const item = items[nameOrIndex]
|
||||||
|
if (!item) {
|
||||||
|
ui.notifications.warn(`${actor.name} : index ${nameOrIndex} invalide pour ${type}.`)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
return foundry.utils.duplicate(item)
|
||||||
|
}
|
||||||
|
const lower = String(nameOrIndex).toLowerCase()
|
||||||
|
const found = items.find(i => i.name.toLowerCase().includes(lower))
|
||||||
|
if (!found) {
|
||||||
|
ui.notifications.warn(`${actor.name} : ${type} "${nameOrIndex}" introuvable.`)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
return foundry.utils.duplicate(found)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* Roll an attribute check.
|
||||||
|
* @param {string} key - "vigor" | "agility" | "mind" | "appeal"
|
||||||
|
* @param {Actor} [actor] - optional, defaults to selected/owned token
|
||||||
|
*/
|
||||||
|
static rollAttribute(key = "vigor", actor = undefined) {
|
||||||
|
actor = actor ?? this.getSpeakersActor()
|
||||||
|
if (!actor) return
|
||||||
|
if (!actor.system.attributes[key]) {
|
||||||
|
ui.notifications.warn(`Attribut inconnu : "${key}". Valeurs : vigor, agility, mind, appeal`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return BoLRoll.attributeCheck(actor, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* Roll an aptitude check.
|
||||||
|
* @param {string} key - "init" | "melee" | "ranged" | "def"
|
||||||
|
* @param {Actor} [actor] - optional, defaults to selected/owned token
|
||||||
|
*/
|
||||||
|
static rollAptitude(key = "melee", actor = undefined) {
|
||||||
|
actor = actor ?? this.getSpeakersActor()
|
||||||
|
if (!actor) return
|
||||||
|
if (!actor.system.aptitudes[key]) {
|
||||||
|
ui.notifications.warn(`Aptitude inconnue : "${key}". Valeurs : init, melee, ranged, def`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return BoLRoll.aptitudeCheck(actor, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* Roll a weapon attack.
|
||||||
|
* @param {string|number} [nameOrIndex] - weapon name (partial) or index. Defaults to first weapon if only one.
|
||||||
|
* @param {Actor} [actor] - optional, defaults to selected/owned token
|
||||||
|
*/
|
||||||
|
static rollWeapon(nameOrIndex = undefined, actor = undefined) {
|
||||||
|
actor = actor ?? this.getSpeakersActor()
|
||||||
|
if (!actor) return
|
||||||
|
const weapon = this._findItem(actor, "weapon", nameOrIndex)
|
||||||
|
if (!weapon) return
|
||||||
|
return BoLRoll.weaponCheckWithWeapon(actor, weapon)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* Roll a spell check.
|
||||||
|
* @param {string|number} [nameOrIndex] - spell name (partial) or index
|
||||||
|
* @param {Actor} [actor] - optional, defaults to selected/owned token
|
||||||
|
*/
|
||||||
|
static rollSpell(nameOrIndex = undefined, actor = undefined) {
|
||||||
|
actor = actor ?? this.getSpeakersActor()
|
||||||
|
if (!actor) return
|
||||||
|
if ((actor.system.resources.power?.value ?? 1) <= 0) {
|
||||||
|
ui.notifications.warn("Plus assez de points de Pouvoir !")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const spell = this._findItem(actor, "spell", nameOrIndex)
|
||||||
|
if (!spell) return
|
||||||
|
return BoLRoll.spellCheckWithSpell(actor, spell)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* Roll an alchemy check.
|
||||||
|
* @param {string|number} [nameOrIndex] - alchemy item name (partial) or index
|
||||||
|
* @param {Actor} [actor] - optional, defaults to selected/owned token
|
||||||
|
*/
|
||||||
|
static rollAlchemy(nameOrIndex = undefined, actor = undefined) {
|
||||||
|
actor = actor ?? this.getSpeakersActor()
|
||||||
|
if (!actor) return
|
||||||
|
const alchemy = this._findItem(actor, "alchemy", nameOrIndex)
|
||||||
|
if (!alchemy) return
|
||||||
|
return BoLRoll.alchemyCheckWithItem(actor, alchemy)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* Roll a horoscope check.
|
||||||
|
* @param {"minor"|"major"} [type="minor"]
|
||||||
|
* @param {Actor} [actor] - optional, defaults to selected/owned token
|
||||||
|
*/
|
||||||
|
static rollHoroscope(type = "minor", actor = undefined) {
|
||||||
|
actor = actor ?? this.getSpeakersActor()
|
||||||
|
if (!actor) return
|
||||||
|
return BoLRoll.horoscopeCheck(actor, undefined, type)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* Generic roll dispatcher.
|
||||||
|
* @param {"attribute"|"aptitude"|"weapon"|"spell"|"alchemy"|"horoscope"} type
|
||||||
|
* @param {string|number} [key] - attribute/aptitude key, item name/index, or horoscope type
|
||||||
|
* @param {Actor} [actor] - optional, defaults to selected/owned token
|
||||||
|
*/
|
||||||
|
static roll(type, key = undefined, actor = undefined) {
|
||||||
|
switch (type) {
|
||||||
|
case "attribute": return this.rollAttribute(key ?? "vigor", actor)
|
||||||
|
case "aptitude": return this.rollAptitude(key ?? "melee", actor)
|
||||||
|
case "weapon": return this.rollWeapon(key, actor)
|
||||||
|
case "spell": return this.rollSpell(key, actor)
|
||||||
|
case "alchemy": return this.rollAlchemy(key, actor)
|
||||||
|
case "horoscope": return this.rollHoroscope(key ?? "minor", actor)
|
||||||
|
default:
|
||||||
|
ui.notifications.warn(`Type de jet inconnu : "${type}". Types valides : attribute, aptitude, weapon, spell, alchemy, horoscope`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
// Kept for backward-compat (previously called by old macros)
|
||||||
|
static rollMacro = async function (rollType, key) {
|
||||||
|
const actor = Macros.getSpeakersActor()
|
||||||
|
if (!actor) return
|
||||||
|
return Macros.roll(rollType, key, actor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
packs/aides-de-jeu/001137.ldb
Normal file
@@ -1 +1 @@
|
|||||||
MANIFEST-001076
|
MANIFEST-001138
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
2026/02/28-22:59:53.852685 7f56e3fff6c0 Recovering log #1074
|
2026/04/11-21:28:04.733439 7ff3bebfd6c0 Recovering log #1135
|
||||||
2026/02/28-22:59:53.863099 7f56e3fff6c0 Delete type=3 #1072
|
2026/04/11-21:28:04.743122 7ff3bebfd6c0 Delete type=3 #1133
|
||||||
2026/02/28-22:59:53.863210 7f56e3fff6c0 Delete type=0 #1074
|
2026/04/11-21:28:04.743177 7ff3bebfd6c0 Delete type=0 #1135
|
||||||
2026/03/01-01:08:46.366409 7f54e37ef6c0 Level-0 table #1079: started
|
2026/04/11-21:28:49.377435 7ff3bdbfb6c0 Level-0 table #1141: started
|
||||||
2026/03/01-01:08:46.366440 7f54e37ef6c0 Level-0 table #1079: 0 bytes OK
|
2026/04/11-21:28:49.377469 7ff3bdbfb6c0 Level-0 table #1141: 0 bytes OK
|
||||||
2026/03/01-01:08:46.372420 7f54e37ef6c0 Delete type=0 #1077
|
2026/04/11-21:28:49.413622 7ff3bdbfb6c0 Delete type=0 #1139
|
||||||
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/04/11-21:28:49.456441 7ff3bdbfb6c0 Manual compaction at level-0 from '!journal!6cCdSvQgEHJ1bvX4' @ 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,14 @@
|
|||||||
2026/02/28-17:23:52.883622 7f56f93fe6c0 Recovering log #1070
|
2026/04/11-21:19:06.264443 7ff3bf3fe6c0 Recovering log #1130
|
||||||
2026/02/28-17:23:52.893895 7f56f93fe6c0 Delete type=3 #1068
|
2026/04/11-21:19:06.275289 7ff3bf3fe6c0 Delete type=3 #1128
|
||||||
2026/02/28-17:23:52.893967 7f56f93fe6c0 Delete type=0 #1070
|
2026/04/11-21:19:06.275358 7ff3bf3fe6c0 Delete type=0 #1130
|
||||||
2026/02/28-22:59:43.750682 7f54e37ef6c0 Level-0 table #1075: started
|
2026/04/11-21:27:57.082652 7ff3bdbfb6c0 Level-0 table #1136: started
|
||||||
2026/02/28-22:59:43.750749 7f54e37ef6c0 Level-0 table #1075: 0 bytes OK
|
2026/04/11-21:27:57.086593 7ff3bdbfb6c0 Level-0 table #1136: 2472 bytes OK
|
||||||
2026/02/28-22:59:43.758241 7f54e37ef6c0 Delete type=0 #1073
|
2026/04/11-21:27:57.092696 7ff3bdbfb6c0 Delete type=0 #1134
|
||||||
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/04/11-21:27:57.111697 7ff3bdbfb6c0 Manual compaction at level-0 from '!journal!6cCdSvQgEHJ1bvX4' @ 72057594037927935 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at '!journal.pages!8ihDiCxC47fcdKVA.MOWru5Dbvs4iozXm' @ 325 : 1
|
||||||
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)
|
2026/04/11-21:27:57.111705 7ff3bdbfb6c0 Compacting 1@0 + 1@1 files
|
||||||
|
2026/04/11-21:27:57.115555 7ff3bdbfb6c0 Generated table #1137@0: 23 keys, 27230 bytes
|
||||||
|
2026/04/11-21:27:57.115568 7ff3bdbfb6c0 Compacted 1@0 + 1@1 files => 27230 bytes
|
||||||
|
2026/04/11-21:27:57.121399 7ff3bdbfb6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
|
||||||
|
2026/04/11-21:27:57.121501 7ff3bdbfb6c0 Delete type=2 #1132
|
||||||
|
2026/04/11-21:27:57.121625 7ff3bdbfb6c0 Delete type=2 #1136
|
||||||
|
2026/04/11-21:27:57.121723 7ff3bdbfb6c0 Manual compaction at level-0 from '!journal.pages!8ihDiCxC47fcdKVA.MOWru5Dbvs4iozXm' @ 325 : 1 .. '!journal.pages!veAAxCtCKcFIsnln.0kUgZspxXO7VS8bd' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
BIN
packs/aides-de-jeu/MANIFEST-001138
Normal file
@@ -1 +1 @@
|
|||||||
MANIFEST-000981
|
MANIFEST-001039
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
2026/02/28-22:59:53.826224 7f56f8bfd6c0 Recovering log #979
|
2026/04/11-21:28:04.708004 7ff3be3fc6c0 Recovering log #1037
|
||||||
2026/02/28-22:59:53.836758 7f56f8bfd6c0 Delete type=3 #977
|
2026/04/11-21:28:04.718300 7ff3be3fc6c0 Delete type=3 #1035
|
||||||
2026/02/28-22:59:53.836823 7f56f8bfd6c0 Delete type=0 #979
|
2026/04/11-21:28:04.718366 7ff3be3fc6c0 Delete type=0 #1037
|
||||||
2026/03/01-01:08:46.372471 7f54e37ef6c0 Level-0 table #984: started
|
2026/04/11-21:28:49.305595 7ff3bdbfb6c0 Level-0 table #1042: started
|
||||||
2026/03/01-01:08:46.372486 7f54e37ef6c0 Level-0 table #984: 0 bytes OK
|
2026/04/11-21:28:49.305624 7ff3bdbfb6c0 Level-0 table #1042: 0 bytes OK
|
||||||
2026/03/01-01:08:46.378495 7f54e37ef6c0 Delete type=0 #982
|
2026/04/11-21:28:49.334673 7ff3bdbfb6c0 Delete type=0 #1040
|
||||||
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/04/11-21:28:49.456420 7ff3bdbfb6c0 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,7 @@
|
|||||||
2026/02/28-17:23:52.858522 7f56e3fff6c0 Recovering log #975
|
2026/04/11-21:19:06.240951 7ff3be3fc6c0 Recovering log #1033
|
||||||
2026/02/28-17:23:52.869495 7f56e3fff6c0 Delete type=3 #973
|
2026/04/11-21:19:06.250426 7ff3be3fc6c0 Delete type=3 #1031
|
||||||
2026/02/28-17:23:52.869552 7f56e3fff6c0 Delete type=0 #975
|
2026/04/11-21:19:06.250488 7ff3be3fc6c0 Delete type=0 #1033
|
||||||
2026/02/28-22:59:43.737596 7f54e37ef6c0 Level-0 table #980: started
|
2026/04/11-21:27:57.098718 7ff3bdbfb6c0 Level-0 table #1038: started
|
||||||
2026/02/28-22:59:43.737635 7f54e37ef6c0 Level-0 table #980: 0 bytes OK
|
2026/04/11-21:27:57.098740 7ff3bdbfb6c0 Level-0 table #1038: 0 bytes OK
|
||||||
2026/02/28-22:59:43.743801 7f54e37ef6c0 Delete type=0 #978
|
2026/04/11-21:27:57.104599 7ff3bdbfb6c0 Delete type=0 #1036
|
||||||
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/04/11-21:27:57.121701 7ff3bdbfb6c0 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)
|
|
||||||
|
|||||||
BIN
packs/armors/MANIFEST-001039
Normal file
@@ -1 +1 @@
|
|||||||
MANIFEST-001075
|
MANIFEST-001133
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
2026/02/28-22:59:53.718001 7f56f8bfd6c0 Recovering log #1073
|
2026/04/11-21:28:04.608888 7ff3be3fc6c0 Recovering log #1131
|
||||||
2026/02/28-22:59:53.729345 7f56f8bfd6c0 Delete type=3 #1071
|
2026/04/11-21:28:04.618597 7ff3be3fc6c0 Delete type=3 #1129
|
||||||
2026/02/28-22:59:53.729412 7f56f8bfd6c0 Delete type=0 #1073
|
2026/04/11-21:28:04.618657 7ff3be3fc6c0 Delete type=0 #1131
|
||||||
2026/03/01-01:08:46.321084 7f54e37ef6c0 Level-0 table #1078: started
|
2026/04/11-21:28:49.095706 7ff3bdbfb6c0 Level-0 table #1136: started
|
||||||
2026/03/01-01:08:46.321111 7f54e37ef6c0 Level-0 table #1078: 0 bytes OK
|
2026/04/11-21:28:49.095741 7ff3bdbfb6c0 Level-0 table #1136: 0 bytes OK
|
||||||
2026/03/01-01:08:46.327221 7f54e37ef6c0 Delete type=0 #1076
|
2026/04/11-21:28:49.132472 7ff3bdbfb6c0 Delete type=0 #1134
|
||||||
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/04/11-21:28:49.170383 7ff3bdbfb6c0 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,7 @@
|
|||||||
2026/02/28-17:23:52.757933 7f56f9bff6c0 Recovering log #1069
|
2026/04/11-21:19:06.144409 7ff3be3fc6c0 Recovering log #1127
|
||||||
2026/02/28-17:23:52.767692 7f56f9bff6c0 Delete type=3 #1067
|
2026/04/11-21:19:06.153957 7ff3be3fc6c0 Delete type=3 #1125
|
||||||
2026/02/28-17:23:52.767761 7f56f9bff6c0 Delete type=0 #1069
|
2026/04/11-21:19:06.154021 7ff3be3fc6c0 Delete type=0 #1127
|
||||||
2026/02/28-22:59:43.697108 7f54e37ef6c0 Level-0 table #1074: started
|
2026/04/11-21:27:57.045260 7ff3bdbfb6c0 Level-0 table #1132: started
|
||||||
2026/02/28-22:59:43.697152 7f54e37ef6c0 Level-0 table #1074: 0 bytes OK
|
2026/04/11-21:27:57.045286 7ff3bdbfb6c0 Level-0 table #1132: 0 bytes OK
|
||||||
2026/02/28-22:59:43.704224 7f54e37ef6c0 Delete type=0 #1072
|
2026/04/11-21:27:57.051070 7ff3bdbfb6c0 Delete type=0 #1130
|
||||||
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/04/11-21:27:57.057054 7ff3bdbfb6c0 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)
|
|
||||||
|
|||||||
BIN
packs/boons/MANIFEST-001133
Normal file
@@ -1 +1 @@
|
|||||||
MANIFEST-001074
|
MANIFEST-001132
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
2026/02/28-22:59:53.732583 7f56e3fff6c0 Recovering log #1072
|
2026/04/11-21:28:04.620767 7ff3bfbff6c0 Recovering log #1130
|
||||||
2026/02/28-22:59:53.742972 7f56e3fff6c0 Delete type=3 #1070
|
2026/04/11-21:28:04.630558 7ff3bfbff6c0 Delete type=3 #1128
|
||||||
2026/02/28-22:59:53.743061 7f56e3fff6c0 Delete type=0 #1072
|
2026/04/11-21:28:04.630621 7ff3bfbff6c0 Delete type=0 #1130
|
||||||
2026/03/01-01:08:46.313828 7f54e37ef6c0 Level-0 table #1077: started
|
2026/04/11-21:28:49.058278 7ff3bdbfb6c0 Level-0 table #1135: started
|
||||||
2026/03/01-01:08:46.313877 7f54e37ef6c0 Level-0 table #1077: 0 bytes OK
|
2026/04/11-21:28:49.058305 7ff3bdbfb6c0 Level-0 table #1135: 0 bytes OK
|
||||||
2026/03/01-01:08:46.320973 7f54e37ef6c0 Delete type=0 #1075
|
2026/04/11-21:28:49.095507 7ff3bdbfb6c0 Delete type=0 #1133
|
||||||
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/04/11-21:28:49.170373 7ff3bdbfb6c0 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,7 @@
|
|||||||
2026/02/28-17:23:52.769847 7f56f93fe6c0 Recovering log #1068
|
2026/04/11-21:19:06.155820 7ff3bfbff6c0 Recovering log #1126
|
||||||
2026/02/28-17:23:52.780583 7f56f93fe6c0 Delete type=3 #1066
|
2026/04/11-21:19:06.166134 7ff3bfbff6c0 Delete type=3 #1124
|
||||||
2026/02/28-17:23:52.780639 7f56f93fe6c0 Delete type=0 #1068
|
2026/04/11-21:19:06.166197 7ff3bfbff6c0 Delete type=0 #1126
|
||||||
2026/02/28-22:59:43.677524 7f54e37ef6c0 Level-0 table #1073: started
|
2026/04/11-21:27:57.031682 7ff3bdbfb6c0 Level-0 table #1131: started
|
||||||
2026/02/28-22:59:43.677620 7f54e37ef6c0 Level-0 table #1073: 0 bytes OK
|
2026/04/11-21:27:57.031756 7ff3bdbfb6c0 Level-0 table #1131: 0 bytes OK
|
||||||
2026/02/28-22:59:43.684329 7f54e37ef6c0 Delete type=0 #1071
|
2026/04/11-21:27:57.038391 7ff3bdbfb6c0 Delete type=0 #1129
|
||||||
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/04/11-21:27:57.057035 7ff3bdbfb6c0 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)
|
|
||||||
|
|||||||
BIN
packs/boonsflawscreatures/MANIFEST-001132
Normal file
@@ -1 +1 @@
|
|||||||
MANIFEST-001074
|
MANIFEST-001132
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
2026/02/28-22:59:53.759689 7f56f8bfd6c0 Recovering log #1072
|
2026/04/11-21:28:04.644730 7ff3bfbff6c0 Recovering log #1130
|
||||||
2026/02/28-22:59:53.770229 7f56f8bfd6c0 Delete type=3 #1070
|
2026/04/11-21:28:04.655618 7ff3bfbff6c0 Delete type=3 #1128
|
||||||
2026/02/28-22:59:53.770305 7f56f8bfd6c0 Delete type=0 #1072
|
2026/04/11-21:28:04.655815 7ff3bfbff6c0 Delete type=0 #1130
|
||||||
2026/03/01-01:08:46.327327 7f54e37ef6c0 Level-0 table #1077: started
|
2026/04/11-21:28:49.132705 7ff3bdbfb6c0 Level-0 table #1135: started
|
||||||
2026/03/01-01:08:46.327354 7f54e37ef6c0 Level-0 table #1077: 0 bytes OK
|
2026/04/11-21:28:49.132747 7ff3bdbfb6c0 Level-0 table #1135: 0 bytes OK
|
||||||
2026/03/01-01:08:46.333262 7f54e37ef6c0 Delete type=0 #1075
|
2026/04/11-21:28:49.170220 7ff3bdbfb6c0 Delete type=0 #1133
|
||||||
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/04/11-21:28:49.170391 7ff3bdbfb6c0 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,7 @@
|
|||||||
2026/02/28-17:23:52.796426 7f56f9bff6c0 Recovering log #1068
|
2026/04/11-21:19:06.179631 7ff3bebfd6c0 Recovering log #1126
|
||||||
2026/02/28-17:23:52.805920 7f56f9bff6c0 Delete type=3 #1066
|
2026/04/11-21:19:06.189451 7ff3bebfd6c0 Delete type=3 #1124
|
||||||
2026/02/28-17:23:52.805973 7f56f9bff6c0 Delete type=0 #1068
|
2026/04/11-21:19:06.189498 7ff3bebfd6c0 Delete type=0 #1126
|
||||||
2026/02/28-22:59:43.711333 7f54e37ef6c0 Level-0 table #1073: started
|
2026/04/11-21:27:57.051143 7ff3bdbfb6c0 Level-0 table #1131: started
|
||||||
2026/02/28-22:59:43.711370 7f54e37ef6c0 Level-0 table #1073: 0 bytes OK
|
2026/04/11-21:27:57.051164 7ff3bdbfb6c0 Level-0 table #1131: 0 bytes OK
|
||||||
2026/02/28-22:59:43.717336 7f54e37ef6c0 Delete type=0 #1071
|
2026/04/11-21:27:57.056960 7ff3bdbfb6c0 Delete type=0 #1129
|
||||||
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/04/11-21:27:57.057062 7ff3bdbfb6c0 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)
|
|
||||||
|
|||||||
BIN
packs/careers/MANIFEST-001132
Normal file
@@ -1 +1 @@
|
|||||||
MANIFEST-001072
|
MANIFEST-001130
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
2026/02/28-22:59:53.948768 7f56f93fe6c0 Recovering log #1070
|
2026/04/11-21:28:04.822069 7ff3bebfd6c0 Recovering log #1128
|
||||||
2026/02/28-22:59:53.958702 7f56f93fe6c0 Delete type=3 #1068
|
2026/04/11-21:28:04.831801 7ff3bebfd6c0 Delete type=3 #1126
|
||||||
2026/02/28-22:59:53.958781 7f56f93fe6c0 Delete type=0 #1070
|
2026/04/11-21:28:04.831849 7ff3bebfd6c0 Delete type=0 #1128
|
||||||
2026/03/01-01:08:46.425514 7f54e37ef6c0 Level-0 table #1075: started
|
2026/04/11-21:28:49.681591 7ff3bdbfb6c0 Level-0 table #1133: started
|
||||||
2026/03/01-01:08:46.425561 7f54e37ef6c0 Level-0 table #1075: 0 bytes OK
|
2026/04/11-21:28:49.681658 7ff3bdbfb6c0 Level-0 table #1133: 0 bytes OK
|
||||||
2026/03/01-01:08:46.431671 7f54e37ef6c0 Delete type=0 #1073
|
2026/04/11-21:28:49.718700 7ff3bdbfb6c0 Delete type=0 #1131
|
||||||
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/04/11-21:28:49.761295 7ff3bdbfb6c0 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,7 @@
|
|||||||
2026/02/28-17:23:52.970603 7f56f9bff6c0 Recovering log #1066
|
2026/04/11-21:19:06.351355 7ff3bfbff6c0 Recovering log #1124
|
||||||
2026/02/28-17:23:52.981835 7f56f9bff6c0 Delete type=3 #1064
|
2026/04/11-21:19:06.361887 7ff3bfbff6c0 Delete type=3 #1122
|
||||||
2026/02/28-17:23:52.981888 7f56f9bff6c0 Delete type=0 #1066
|
2026/04/11-21:19:06.361938 7ff3bfbff6c0 Delete type=0 #1124
|
||||||
2026/02/28-22:59:43.785498 7f54e37ef6c0 Level-0 table #1071: started
|
2026/04/11-21:27:57.154739 7ff3bdbfb6c0 Level-0 table #1129: started
|
||||||
2026/02/28-22:59:43.785523 7f54e37ef6c0 Level-0 table #1071: 0 bytes OK
|
2026/04/11-21:27:57.154770 7ff3bdbfb6c0 Level-0 table #1129: 0 bytes OK
|
||||||
2026/02/28-22:59:43.792317 7f54e37ef6c0 Delete type=0 #1069
|
2026/04/11-21:27:57.160975 7ff3bdbfb6c0 Delete type=0 #1127
|
||||||
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/04/11-21:27:57.175182 7ff3bdbfb6c0 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)
|
|
||||||
|
|||||||
BIN
packs/effets-exemples/MANIFEST-001130
Normal file
0
packs/equipment/001135.log
Normal file
@@ -1 +1 @@
|
|||||||
MANIFEST-001075
|
MANIFEST-001133
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
2026/02/28-22:59:53.798832 7f56f9bff6c0 Recovering log #1073
|
2026/04/11-21:28:04.683176 7ff3bebfd6c0 Recovering log #1131
|
||||||
2026/02/28-22:59:53.809449 7f56f9bff6c0 Delete type=3 #1071
|
2026/04/11-21:28:04.693337 7ff3bebfd6c0 Delete type=3 #1129
|
||||||
2026/02/28-22:59:53.809533 7f56f9bff6c0 Delete type=0 #1073
|
2026/04/11-21:28:04.693387 7ff3bebfd6c0 Delete type=0 #1131
|
||||||
2026/03/01-01:08:46.340100 7f54e37ef6c0 Level-0 table #1078: started
|
2026/04/11-21:28:49.233539 7ff3bdbfb6c0 Level-0 table #1136: started
|
||||||
2026/03/01-01:08:46.340139 7f54e37ef6c0 Level-0 table #1078: 0 bytes OK
|
2026/04/11-21:28:49.233570 7ff3bdbfb6c0 Level-0 table #1136: 0 bytes OK
|
||||||
2026/03/01-01:08:46.346846 7f54e37ef6c0 Delete type=0 #1076
|
2026/04/11-21:28:49.271356 7ff3bdbfb6c0 Delete type=0 #1134
|
||||||
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/04/11-21:28:49.305506 7ff3bdbfb6c0 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,7 @@
|
|||||||
2026/02/28-17:23:52.834261 7f56f9bff6c0 Recovering log #1069
|
2026/04/11-21:19:06.215905 7ff3be3fc6c0 Recovering log #1127
|
||||||
2026/02/28-17:23:52.843912 7f56f9bff6c0 Delete type=3 #1067
|
2026/04/11-21:19:06.225729 7ff3be3fc6c0 Delete type=3 #1125
|
||||||
2026/02/28-17:23:52.843969 7f56f9bff6c0 Delete type=0 #1069
|
2026/04/11-21:19:06.225801 7ff3be3fc6c0 Delete type=0 #1127
|
||||||
2026/02/28-22:59:43.704672 7f54e37ef6c0 Level-0 table #1074: started
|
2026/04/11-21:27:57.070299 7ff3bdbfb6c0 Level-0 table #1132: started
|
||||||
2026/02/28-22:59:43.704745 7f54e37ef6c0 Level-0 table #1074: 0 bytes OK
|
2026/04/11-21:27:57.070342 7ff3bdbfb6c0 Level-0 table #1132: 0 bytes OK
|
||||||
2026/02/28-22:59:43.711212 7f54e37ef6c0 Delete type=0 #1072
|
2026/04/11-21:27:57.076462 7ff3bdbfb6c0 Delete type=0 #1130
|
||||||
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/04/11-21:27:57.082540 7ff3bdbfb6c0 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)
|
|
||||||
|
|||||||
BIN
packs/equipment/MANIFEST-001133
Normal file
0
packs/equipment/lost/001081.log
Normal file
0
packs/equipment/lost/001110.log
Normal file
0
packs/fightoptions/001134.log
Normal file
@@ -1 +1 @@
|
|||||||
MANIFEST-001074
|
MANIFEST-001132
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
2026/02/28-22:59:53.895577 7f56f8bfd6c0 Recovering log #1072
|
2026/04/11-21:28:04.771459 7ff3bebfd6c0 Recovering log #1130
|
||||||
2026/02/28-22:59:53.906749 7f56f8bfd6c0 Delete type=3 #1070
|
2026/04/11-21:28:04.782419 7ff3bebfd6c0 Delete type=3 #1128
|
||||||
2026/02/28-22:59:53.906807 7f56f8bfd6c0 Delete type=0 #1072
|
2026/04/11-21:28:04.782481 7ff3bebfd6c0 Delete type=0 #1130
|
||||||
2026/03/01-01:08:46.391890 7f54e37ef6c0 Level-0 table #1077: started
|
2026/04/11-21:28:49.490812 7ff3bdbfb6c0 Level-0 table #1135: started
|
||||||
2026/03/01-01:08:46.391936 7f54e37ef6c0 Level-0 table #1077: 0 bytes OK
|
2026/04/11-21:28:49.490847 7ff3bdbfb6c0 Level-0 table #1135: 0 bytes OK
|
||||||
2026/03/01-01:08:46.398187 7f54e37ef6c0 Delete type=0 #1075
|
2026/04/11-21:28:49.523118 7ff3bdbfb6c0 Delete type=0 #1133
|
||||||
2026/03/01-01:08:46.417834 7f54e37ef6c0 Manual compaction at level-0 from '!items!AoT2c0af4lY6aBsx' @ 72057594037927935 : 1 .. '!items!vGydqADwTsHZ9B3j' @ 0 : 0; will stop at (end)
|
2026/04/11-21:28:49.606517 7ff3bdbfb6c0 Manual compaction at level-0 from '!items!AoT2c0af4lY6aBsx' @ 72057594037927935 : 1 .. '!items!vGydqADwTsHZ9B3j' @ 0 : 0; will stop at (end)
|
||||||
2026/03/01-01:08:46.417875 7f54e37ef6c0 Manual compaction at level-1 from '!items!AoT2c0af4lY6aBsx' @ 72057594037927935 : 1 .. '!items!vGydqADwTsHZ9B3j' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
2026/02/28-17:23:52.920377 7f56e3fff6c0 Recovering log #1068
|
2026/04/11-21:19:06.302307 7ff3bfbff6c0 Recovering log #1126
|
||||||
2026/02/28-17:23:52.930570 7f56e3fff6c0 Delete type=3 #1066
|
2026/04/11-21:19:06.312721 7ff3bfbff6c0 Delete type=3 #1124
|
||||||
2026/02/28-17:23:52.930642 7f56e3fff6c0 Delete type=0 #1068
|
2026/04/11-21:19:06.312775 7ff3bfbff6c0 Delete type=0 #1126
|
||||||
2026/02/28-22:59:43.758590 7f54e37ef6c0 Level-0 table #1073: started
|
2026/04/11-21:27:57.121860 7ff3bdbfb6c0 Level-0 table #1131: started
|
||||||
2026/02/28-22:59:43.758628 7f54e37ef6c0 Level-0 table #1073: 0 bytes OK
|
2026/04/11-21:27:57.121898 7ff3bdbfb6c0 Level-0 table #1131: 0 bytes OK
|
||||||
2026/02/28-22:59:43.764731 7f54e37ef6c0 Delete type=0 #1071
|
2026/04/11-21:27:57.127875 7ff3bdbfb6c0 Delete type=0 #1129
|
||||||
2026/02/28-22:59:43.785330 7f54e37ef6c0 Manual compaction at level-0 from '!items!AoT2c0af4lY6aBsx' @ 72057594037927935 : 1 .. '!items!vGydqADwTsHZ9B3j' @ 0 : 0; will stop at (end)
|
2026/04/11-21:27:57.147924 7ff3bdbfb6c0 Manual compaction at level-0 from '!items!AoT2c0af4lY6aBsx' @ 72057594037927935 : 1 .. '!items!vGydqADwTsHZ9B3j' @ 0 : 0; will stop at (end)
|
||||||
2026/02/28-22:59:43.785372 7f54e37ef6c0 Manual compaction at level-1 from '!items!AoT2c0af4lY6aBsx' @ 72057594037927935 : 1 .. '!items!vGydqADwTsHZ9B3j' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||