Compare commits

..

31 Commits

Author SHA1 Message Date
uberwald 78e5d29e2f Corrections sur armes/armures
Release Creation / build (release) Successful in 47s
2026-06-14 22:18:12 +02:00
uberwald 41bde6dc02 COrrection sur fiches de simples
Release Creation / build (release) Successful in 43s
2026-06-03 20:21:38 +02:00
uberwald b0265a7089 Foundryv14 migration
Release Creation / build (release) Successful in 54s
2026-04-01 22:30:02 +02:00
uberwald dbd8352d42 Correction compendiums armes
Release Creation / build (release) Successful in 1m6s
2026-03-05 21:16:06 +01:00
uberwald 9aaf5dbe93 Ajout compendiums ? 2026-03-05 20:49:54 +01:00
uberwald b407f6e8c0 Migration complétée vers appv2
Release Creation / build (release) Successful in 1m14s
2026-02-28 12:14:21 +01:00
uberwald aecc15d8b9 Migration complétée vers appv2 2026-02-28 12:14:01 +01:00
uberwald a2b712b78d Diverses corrections + ajouts armes en compendiums
Release Creation / build (release) Successful in 1m53s
2026-02-26 13:30:53 +01:00
uberwald fc6bb7a4b1 CSS rework et autres améliorations
Release Creation / build (release) Successful in 46s
2026-02-12 23:08:51 +01:00
uberwald f26130d208 CSS rework et autres améliorations 2026-02-12 23:05:22 +01:00
uberwald 39da08d4cb CSS rework et autres améliorations 2026-02-12 23:04:37 +01:00
uberwald e639b6ae3e Fix rollData = 1
Release Creation / build (release) Successful in 3m36s
2025-12-01 17:57:19 +01:00
uberwald 8c247a8981 Echec automatique sur 1
Release Creation / build (release) Successful in 49s
2025-11-21 21:36:27 +01:00
uberwald a09e1a1d95 Les compétences de base ne peuvent être supprimées
Release Creation / build (release) Successful in 47s
2025-11-02 18:30:20 +01:00
uberwald 787f88873a Les compétences de base ne peuvent être supprimées 2025-11-02 18:29:46 +01:00
uberwald ac481e0dd9 Various minot fixes
Release Creation / build (release) Successful in 1m18s
2025-10-30 20:24:24 +00:00
uberwald 375622d900 Add welcome message 2025-10-17 15:31:32 +02:00
uberwald 3bc055cc1f Add welcome message 2025-10-17 15:28:15 +02:00
uberwald c97b7a4889 Correction sur blessures et actions restantes
Release Creation / build (release) Successful in 53s
2025-10-16 22:59:32 +02:00
uberwald 5d13500838 Fix sur combat + mains gauche
Release Creation / build (release) Successful in 43s
2025-09-24 16:43:52 +02:00
uberwald d21515e1e3 Fix sur combat + mains gauche 2025-09-24 16:43:40 +02:00
uberwald 78ef009465 Fix sur combat + mains gauche 2025-09-24 16:42:08 +02:00
uberwald e794611bf3 Gestion assistée pour les actions
Release Creation / build (release) Successful in 46s
2025-09-24 15:11:58 +02:00
uberwald 529a62045e Gestion assistée pour les actions 2025-09-24 15:09:00 +02:00
uberwald d462d22a0a Manye enhancements for combat
Release Creation / build (release) Successful in 42s
2025-09-18 17:26:02 +02:00
uberwald 710ee54531 Manye enhancements for combat 2025-09-18 17:24:42 +02:00
uberwald 7994aa7db4 Fix savoir lors de la creation de perso
Release Creation / build (release) Successful in 1m30s
2025-09-08 23:47:19 +02:00
uberwald 5176b4ce87 Amelioration histoire creation de perso, CSS bouton et genre de la providence
Release Creation / build (release) Successful in 56s
2025-07-20 11:21:08 +02:00
uberwald 3d6f195fc2 Educcation fix + CSS v13
Release Creation / build (release) Successful in 43s
2025-07-02 23:08:34 +02:00
uberwald 3693d68c24 Correction sur les compétences de base
Release Creation / build (release) Successful in 1m0s
2025-06-04 15:29:32 +02:00
uberwald 16ccd2f3e1 Foundry v13 migration 2025-05-09 10:28:22 +02:00
130 changed files with 7281 additions and 3262 deletions
+21 -10
View File
@@ -11,42 +11,53 @@ jobs:
- run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner." - run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner."
#- uses: actions/checkout@v3 #- uses: actions/checkout@v3
- uses: RouxAntoine/checkout@v3.5.4 - uses: https://github.com/RouxAntoine/checkout@v3.5.4
# 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: https://github.com/battila7/get-version-action@v2
# Substitute the Manifest and Download URLs in the module.json # Substitute the Manifest and Download URLs in the module.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: https://github.com/microsoft/variable-substitution@v1
with: with:
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/${{gitea.repository}} url: https://www.uberwald.me/gitea/${{gitea.repository}}
manifest: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/latest/system.json manifest: https://www.uberwald.me/gitea/public/fvtt-te-deum/releases/download/latest/system.json
download: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-te-deum-${{github.event.release.tag_name}}.zip download: https://www.uberwald.me/gitea/public/fvtt-te-deum/releases/download/${{github.event.release.tag_name}}/fvtt-te-deum.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: |
apt update -y apt update -y
apt install -y zip apt install -y zip
- run: zip -r ./fvtt-te-deum-${{github.event.release.tag_name}}.zip system.json template.json README.md LICENSE.txt assets/ fonts/ images/ lang/ modules/ styles/ packs/ templates/ te-deum.mjs - run: zip -r ./fvtt-te-deum.zip system.json README.md LICENSE.txt assets/ fonts/ images/ lang/ modules/ styles/ packs/ templates/
- name: setup go - name: setup go
uses: https://github.com/actions/setup-go@v4 uses: https://github.com/actions/setup-go@v4
with: with:
go-version: '>=1.20.1' go-version: ">=1.20.1"
- name: Use Go Action - name: Use Go Action
id: use-go-action id: use-go-action
uses: https://gitea.com/actions/release-action@main uses: https://gitea.com/actions/release-action@main
with: with:
files: |- files: |-
./fvtt-te-deum-${{github.event.release.tag_name}}.zip ./fvtt-te-deum.zip
system.json system.json
api_key: '${{secrets.ALLOW_PUSH_RELEASE}}' 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: 'fvtt-te-deum'
version: ${{github.event.release.tag_name}}
manifest: 'https://www.uberwald.me/gitea/public/fvtt-te-deum/releases/download/latest/system.json'
notes: 'https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-te-deum.zip'
compatibility-minimum: '13'
compatibility-verified: '13'
+54
View File
@@ -0,0 +1,54 @@
# Dependencies
node_modules/
package-lock.json
# Build outputs
styles/tedeum.css
styles/*.css.map
# IDE & Editor files
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
# System files
Thumbs.db
desktop.ini
# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
*.log
# Temporary files
*.tmp
*.temp
.cache/
# Environment variables
.env
.env.local
# Optional: Uncomment if you want to ignore pack database files
# These are usually committed for systems, but can be regenerated
# packs/**/*.ldb
# packs/**/LOG
# packs/**/LOG.old
# packs/**/MANIFEST-*
# packs/**/CURRENT
# Compiled source
dist/
build/
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
+4
View File
@@ -1,3 +1,7 @@
# 13.0.0
- Support de Foundry v13
# 12.0.23 # 12.0.23
- Correction sur les jets réussie en tir - Correction sur les jets réussie en tir
+8 -16
View File
@@ -1,25 +1,17 @@
var gulp = require('gulp'); var gulp = require('gulp');
var less = require('gulp-less');
var postcss = require('gulp-postcss'); var postcss = require('gulp-postcss');
var autoprefixer = require('autoprefixer'); var autoprefixer = require('autoprefixer');
var cssnext = require('postcss-preset-env');
var precss = require('precss');
gulp.task('css', function () { gulp.task('css', function () {
return gulp.src('./less/*.less')
var processors = [ .pipe(less())
autoprefixer, .pipe(postcss([autoprefixer]))
cssnext,
precss
];
return gulp.src('./postcss/*.css')
.pipe(postcss(processors))
.pipe(gulp.dest('./styles')); .pipe(gulp.dest('./styles'));
}); });
gulp.task('watch', function () {
gulp.watch('./less/*.less', gulp.series('css'));
});
function watchUpdates() { gulp.task('default', gulp.series('css'));
gulp.watch('./postcss/*.css', css);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

+469
View File
@@ -0,0 +1,469 @@
.editor {
border: 2;
height: 100%;
padding: 0 3px;
}
.medium-editor {
border: 2;
height: 240px;
max-height: 240px;
overflow-y: auto;
overflow-x: hidden;
padding: 0 3px;
prose-mirror, .editor, .editor-content, .ProseMirror {
overflow: hidden;
height: auto;
}
}
.small-editor {
border: 2;
height: 120px;
max-height: 120px;
overflow-y: auto;
overflow-x: hidden;
padding: 0 3px;
prose-mirror, .editor, .editor-content, .ProseMirror {
overflow: hidden;
height: auto;
}
}
.questionnaire-reponse {
max-width: 42rem;
margin-left: 1rem;
}
.questionnaire-element {
margin-top: 0.5rem;
}
// Style unifié pour tous les inputs et selects (fiches acteur, item, roll dialogs)
.fvtt-te-deum {
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="submit"]):not([type="image"]):not([type="file"]),
select {
background: rgba(248, 245, 238, 0.95);
color: rgba(19, 18, 18, 0.95);
border: 1px solid rgba(139, 115, 85, 0.35);
border-radius: 3px;
padding: 0.15rem 0.3rem;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
&:hover {
border-color: rgba(139, 115, 85, 0.65);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}
&:focus {
outline: none;
border-color: rgba(139, 115, 85, 0.85);
box-shadow: 0 0 0 2px rgba(139, 115, 85, 0.2);
}
&:disabled {
color: rgba(19, 18, 18, 0.4);
background: rgba(220, 216, 205, 0.6);
border-color: rgba(139, 115, 85, 0.15);
}
}
textarea {
background: rgba(248, 245, 238, 0.95);
color: rgba(19, 18, 18, 0.95);
border: 1px solid rgba(139, 115, 85, 0.35);
border-radius: 3px;
padding: 0.2rem 0.4rem;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
&:hover {
border-color: rgba(139, 115, 85, 0.65);
}
&:focus {
outline: none;
border-color: rgba(139, 115, 85, 0.85);
box-shadow: 0 0 0 2px rgba(139, 115, 85, 0.2);
}
}
}
.fvtt-te-deum.window-app .window-content,
.fvtt-te-deum.application .window-content,
.fvtt-te-deum.window-app.sheet .window-content .sheet-body,
.fvtt-te-deum.application.sheet .window-content .sheet-body {
font-size: 0.8rem;
background: rgba(226, 226, 222, 0.95);
color: rgba(19, 18, 18, 0.95);
}
// Améliorations pour les fiches d'items
.item-form {
.sheet-header {
background: linear-gradient(
135deg,
rgba(226, 226, 222, 0.95) 0%,
rgba(240, 235, 225, 0.9) 100%
);
padding: 0.8rem;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
border: 1px solid rgba(139, 115, 85, 0.3);
margin-bottom: 0.5rem;
h1.charname input {
// Voir règles haute-spécificité charname ci-dessous
}
}
.sheet-body {
ul {
list-style: none;
padding: 0;
margin: 0;
li.flexrow {
background: rgba(255, 255, 255, 0.3);
padding: 0.4rem 0.6rem;
margin: 0.3rem 0;
border-radius: 4px;
border-left: 3px solid rgba(139, 115, 85, 0.3);
transition: all 0.2s ease;
&:hover {
background: rgba(255, 255, 255, 0.5);
border-left-color: rgba(139, 115, 85, 0.6);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
}
}
h3 {
background: linear-gradient(
135deg,
rgba(196, 186, 166, 0.6) 0%,
rgba(226, 226, 222, 0.5) 100%
);
padding: 0.4rem 0.6rem;
margin: 0.8rem 0 0.4rem 0;
border-radius: 4px;
border-left: 4px solid rgba(139, 115, 85, 0.6);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
font-family: MailartRubberstamp;
font-size: 1.1rem;
color: #3d3a2e;
}
input[type="checkbox"] {
width: 18px;
height: 18px;
cursor: pointer;
}
}
}
// Champ "name" — règles haute-spécificité (spec 0,6,2 / 0,7,2) pour surcharger les règles génériques d'input
// Fiche acteur : font-size 3rem
.fvtt-te-deum.application .window-content .sheet-header h1.charname input[name="name"],
.fvtt-te-deum.window-app .window-content .sheet-header h1.charname input[name="name"] {
font-family: "GreatPrimer";
font-size: 3rem;
background: transparent;
border: none;
border-bottom: 2px solid rgba(139, 115, 85, 0.4);
color: rgba(50, 35, 15, 0.95);
width: 100%;
height: 100%;
margin: 0;
letter-spacing: 0.05em;
transition: border-color 0.2s ease;
&:hover {
border-width: 2px;
border-color: rgba(139, 115, 85, 0.7);
}
&:focus {
border-bottom-color: rgba(139, 115, 85, 0.9);
outline: none;
}
}
// Fiche item : même style mais font-size plus petit
.fvtt-te-deum.application .window-content .item-form .sheet-header h1.charname input[name="name"],
.fvtt-te-deum.window-app .window-content .item-form .sheet-header h1.charname input[name="name"] {
font-size: 1.6rem;
height: auto;
}
.fvtt-te-deum .sheet-body {
padding: 0.25rem 0.5rem;
&:after {
content: "";
display: block;
clear: both;
}
}
.fvtt-te-deum nav {
&.tabs {
.item {
z-index: 2;
position: relative;
opacity: 1;
color: rgba(29, 28, 31);
padding: 0 0.25rem;
&:after {
content: "";
position: absolute;
top: 0;
right: 0;
height: 2rem;
width: 1px;
}
}
}
}
.select-diff {
display: inline-block;
text-align: left;
width: 50px;
}
.fvtt-te-deum.window-app.sheet .window-content .carac-value,
.fvtt-te-deum.application.sheet .window-content .carac-value,
.fvtt-te-deum.window-app.sheet .window-content .competence-xp,
.fvtt-te-deum.application.sheet .window-content .competence-xp {
margin: 0.05rem;
flex-basis: 3rem;
text-align: center;
}
.fvtt-te-deum h1,
.fvtt-te-deum h2,
.fvtt-te-deum h3,
.fvtt-te-deum h4 {
font-weight: bold;
color: rgba(19, 18, 18, 0.95);
}
.fvtt-te-deum .malus-sante {
font-size: 0.88rem;
font-weight: normal;
}
.fvtt-te-deum .malus-sante-active {
color: rgba(200, 80, 10, 0.95);
font-weight: bold;
}
.fvtt-te-deum ul,
.fvtt-te-deum ol {
margin: 0;
padding: 0;
}
.fvtt-te-deum ul,
.fvtt-te-deum li {
list-style-type: none;
}
.header-fields {
li {
margin: 0;
padding: 0;
}
}
.alterne-list {
& > .list-item {
&:hover {
background: rgba(226, 226, 222, 0.4);
transform: translateX(2px);
}
&:nth-child(even) {
background: rgba(240, 235, 225, 0.3);
}
&:nth-child(odd) {
background: rgba(250, 245, 235, 0.2);
}
}
}
.specialisation-label {
font-size: 0.8rem;
}
.carac-label,
.attr-label {
font-weight: bold;
}
.list-item {
margin: 0.125rem;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
border-radius: 0.3rem;
padding: 0.3rem 0.4rem;
flex: 1 1 5rem;
border: 1px solid rgba(139, 115, 85, 0.15);
transition: all 0.2s ease;
&:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
border-color: rgba(139, 115, 85, 0.3);
background: rgba(255, 255, 255, 0.3);
}
}
.list-item-shadow {
background: linear-gradient(
135deg,
rgba(170, 168, 167, 0.25) 0%,
rgba(200, 195, 185, 0.2) 100%
);
flex-grow: 0;
flex-wrap: nowrap;
justify-content: flex-start;
border-left: 3px solid rgba(139, 115, 85, 0.3);
}
.list-item-shadow2 {
background: linear-gradient(
135deg,
rgba(87, 60, 32, 0.2) 0%,
rgba(120, 90, 60, 0.15) 100%
);
flex-grow: 0;
flex-wrap: nowrap;
justify-content: flex-start;
border-left: 3px solid rgba(87, 60, 32, 0.4);
}
.item-display-show {
display: block;
}
.item-display-hide {
display: none;
}
.item-quantite {
margin-left: 0.5rem;
}
.list-item-margin1 {
margin-left: 1rem;
}
.list-item-margin2 {
margin-left: 2rem;
}
.list-item-margin3 {
margin-left: 3rem;
}
.list-item-margin4 {
margin-left: 4rem;
}
.sheet-competence-img {
width: 24px;
max-width: 24px;
height: 24px;
max-height: 24px;
flex-grow: 0;
margin-right: 0.25rem;
border-radius: 3px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
border: 1px solid rgba(139, 115, 85, 0.3);
}
.competence-column {
flex-direction: column;
align-content: flex-start;
justify-content: flex-start;
flex-grow: 0;
flex-basis: 1;
}
.competence-header {
align-content: flex-start;
justify-content: flex-start;
font-weight: bold;
flex-grow: 0;
}
.comp-li {
max-width: 8rem;
width: 8rem;
}
.description-label {
flex-grow: 2;
margin-left: 4px;
}
.status-header-label {
margin-left: 2px;
}
.roll-dialog-label {
margin: 4px 0;
min-width: 96px;
}
.short-label {
flex-grow: 1;
}
.keyword-label {
font-size: 0.85rem;
}
.item-sheet-label {
flex-grow: 1;
}
.item-text-long-line {
flex-grow: 3;
}
.score-label {
flex-grow: 2;
align-content: center;
}
.attribut-value,
.carac-value {
flex-grow: 0;
flex-basis: 64px;
margin-right: 4px;
margin-left: 4px;
}
.sante-value,
.competence-value {
flex-grow: 0;
flex-basis: 2rem;
margin-right: 0.25rem;
margin-left: 0.25rem;
}
.description-value {
flex-grow: 0;
flex-basis: 4rem;
margin-right: 0.25rem;
margin-left: 0.25rem;
}
.small-label {
margin-top: 5px;
}
+235
View File
@@ -0,0 +1,235 @@
.fvtt-te-deum.window-app,
.fvtt-te-deum.application {
text-align: justify;
font-size: 16px;
letter-spacing: 1px;
&.sheet {
.window-content {
margin: 0;
padding: 0;
font-family: "GreatPrimer";
.sheet-header {
color: rgba(19, 18, 18, 0.95);
background: rgba(226, 226, 222, 0.95);
}
.tooltip {
&:hover {
.tooltiptext {
top: 2rem;
left: 2rem;
margin: 0;
padding: 0.25rem;
}
}
}
}
}
}
.fvtt-te-deum.sheet header.sheet-header h1 input,
.window-app .window-header,
.application .window-header,
#actors .directory-list,
#navigation #scene-list .scene.nav-item {
font-size: 1rem;
}
.fvtt-te-deum.sheet {
nav {
&.sheet-tabs,
&.tabs {
font-size: 0.8rem;
font-size: 1.2rem;
font-weight: bold;
height: 3rem;
flex: 0 0 3rem;
margin: 0;
padding: 0 0 0 0.25rem;
text-align: center;
line-height: 1.5rem;
border-top: 0 none;
border-bottom: 0 none;
background:
linear-gradient(rgba(226, 226, 222, 0.5), rgba(226, 226, 222, 0.5)),
url("../images/ui/frise_bottom_01.webp");
background-repeat: no-repeat;
background-size: 100% 100%;
z-index: 1;
}
}
header {
&.sheet-header {
.profile-img {
-o-object-fit: cover;
object-fit: cover;
-o-object-position: 50% 0;
object-position: 50% 0;
margin: 0.5rem 0 0.5rem 0.5rem;
padding: 0;
}
.flex-compteurs {
text-align: right;
}
.resource-content {
width: 2rem;
}
}
}
.tab[data-tab] {
padding: 0;
}
li {
margin: 0.2rem;
padding: 0.15rem;
}
}
.fvtt-te-deum.window-app input,
.fvtt-te-deum.application input,
.fvtt-te-deum .item-form,
.fvtt-te-deum.sheet header.sheet-header .flex-group-center.flex-compteurs,
.fvtt-te-deum.sheet header.sheet-header .flex-group-center.flex-fatigue,
.fvtt-te-deum select,
.fvtt-te-deum button,
.item-checkbox,
#sidebar,
#players,
#navigation #nav-toggle {
font-size: 0.8rem;
}
.window-header {
background: rgba(0, 0, 0, 0.75);
}
.strong-text {
font-weight: bold;
}
.fvtt-te-deum .tabs .item.active,
.fvtt-te-deum .blessures-list li ul li:first-child:hover,
.fvtt-te-deum a:hover {
text-shadow: 1px 0px 0px #ff6600;
}
.rollable:hover,
.rollable:focus {
color: #000;
text-shadow: 0 0 10px red;
cursor: pointer;
}
li.folder > .folder-header h3 {
color: #aaa;
}
.fvtt-te-deum table {
border: 1px solid #7a7971;
}
.grid,
.grid-2col {
display: grid;
grid-column: span 2 / span 2;
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-gap: 10px;
grid-gap: 10px;
gap: 10px;
margin: 10px 0;
padding: 0;
}
.grid-3col {
grid-column: span 3 / span 3;
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.grid-4col {
grid-column: span 4 / span 4;
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.grid-5col {
grid-column: span 5 / span 5;
grid-template-columns: repeat(5, minmax(0, 1fr));
}
.grid-6col {
grid-column: span 5 / span 5;
grid-template-columns: repeat(5, minmax(0, 1fr));
}
.grid-7col {
grid-column: span 7 / span 7;
grid-template-columns: repeat(7, minmax(0, 1fr));
}
.grid-8col {
grid-column: span 8 / span 8;
grid-template-columns: repeat(8, minmax(0, 1fr));
}
.grid-9col {
grid-column: span 9 / span 9;
grid-template-columns: repeat(9, minmax(0, 1fr));
}
.grid-10col {
grid-column: span 10 / span 10;
grid-template-columns: repeat(10, minmax(0, 1fr));
}
.grid-11col {
grid-column: span 11 / span 11;
grid-template-columns: repeat(11, minmax(0, 1fr));
}
.grid-12col {
grid-column: span 12 / span 12;
grid-template-columns: repeat(12, minmax(0, 1fr));
}
.flex-group-center,
.flex-group-left,
.flex-group-right {
justify-content: center;
align-items: center;
text-align: center;
padding: 5px;
}
.flex-group-left {
justify-content: flex-start;
text-align: left;
}
.flex-group-right {
justify-content: flex-end;
text-align: right;
}
.flex-center {
align-items: center;
justify-content: center;
text-align: center;
}
.table-create-actor {
font-size: 0.8rem;
}
.flex-between {
justify-content: space-between;
}
.flex-shrink {
flex: "flex-shrink";
}
+581
View File
@@ -0,0 +1,581 @@
.chat-message-header {
background: linear-gradient(
135deg,
rgba(226, 226, 222, 0.95) 0%,
rgba(196, 186, 166, 0.9) 100%
);
font-size: 0.9rem;
min-height: 26px;
text-align: center;
vertical-align: middle;
display: flex;
align-items: center;
justify-content: center;
border-bottom: 2px solid rgba(139, 115, 85, 0.6);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
padding: 0.1rem 0.3rem;
border-radius: 6px 6px 0 0;
}
.chat-message .message-header .flavor-text,
.chat-message .message-header .whisper-to {
font-size: 0.9rem;
}
.chat-result-text {
font-weight: bold;
font-family: GreatPrimer;
font-size: 1.1rem;
color: rgba(80, 50, 15, 0.95);
padding: 0 0 0.1rem 0;
line-height: 1.3;
border-bottom: 1px solid rgba(139, 115, 85, 0.4);
display: block;
margin-bottom: 0.2rem;
letter-spacing: 0.03em;
}
.chat-actor-name {
font-weight: bold;
font-family: GreatPrimer;
font-size: 1.1rem;
color: rgba(80, 50, 15, 0.95);
line-height: 1;
letter-spacing: 0.03em;
margin: 0;
padding: 0;
}
.chat-actor-name-opposition {
font-weight: bold;
font-family: GreatPrimer;
font-size: 1.1rem;
color: rgba(80, 50, 15, 0.95);
padding: 0.1rem 0.3rem;
letter-spacing: 0.03em;
}
.chat-result-success {
color: #2d5016;
background: linear-gradient(
135deg,
rgba(144, 238, 144, 0.3),
rgba(107, 186, 107, 0.25)
);
padding: 0.25rem 0.6rem;
border-radius: 4px;
border-left: 3px solid #4a7c2c;
display: inline-block;
margin: 0.15rem 0;
box-shadow: 0 1px 3px rgba(45, 80, 22, 0.2);
font-weight: bold;
}
.chat-result-failure {
color: #7a1a1a;
background: linear-gradient(
135deg,
rgba(255, 160, 160, 0.3),
rgba(205, 120, 120, 0.25)
);
padding: 0.25rem 0.6rem;
border-radius: 4px;
border-left: 3px solid #a82020;
display: inline-block;
margin: 0.15rem 0;
box-shadow: 0 1px 3px rgba(122, 26, 26, 0.2);
font-weight: bold;
}
.chat-img {
width: 64px;
height: 64px;
}
.chat-command-img {
border: 0px;
width: 32px;
height: 32px;
transition:
transform 0.2s ease,
box-shadow 0.2s ease;
border-radius: 4px;
&:hover {
transform: scale(1.1);
box-shadow: 0 3px 8px rgba(255, 102, 0, 0.4);
}
}
.chat-result-column {
min-width: 70%;
width: 70%;
}
.roll-dialog-header {
background: linear-gradient(
135deg,
rgba(226, 226, 222, 0.95) 0%,
rgba(196, 186, 166, 0.9) 100%
);
min-height: 48px;
padding: 0.4rem 0.6rem;
border-radius: 6px 6px 0 0;
border-bottom: 2px solid rgba(139, 115, 85, 0.6);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
.actor-icon {
width: 40px;
height: 40px;
border-radius: 50%;
border: 2px solid rgba(139, 115, 85, 0.5);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.dialog-roll-title {
font-family: GreatPrimer;
font-size: 1.1rem;
margin: 0;
color: #3d3a2e;
text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.5);
}
}
.actor-icon {
width: 28px;
height: 28px;
padding: 1px;
border-radius: 50%;
border: 2px solid rgba(139, 115, 85, 0.5);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
flex-shrink: 0;
margin-right: 0.4rem;
}
.padding-dice {
padding-top: 0.2rem;
padding-bottom: 0.2rem;
}
.dice-image {
box-sizing: border-box;
border: none;
border-radius: 0;
max-width: 100%;
}
.dice-image-reroll {
background-color: rgba(115, 224, 115, 0.25);
border-color: #011d33;
box-sizing: border-box;
border: 1px;
border-radius: 0%;
max-width: 100%;
}
.chat-dice {
width: 15%;
height: 15%;
font-size: 15px;
padding: 10px;
padding-bottom: 20px;
padding-top: 0.2rem;
padding-bottom: 0.2rem;
}
.div-center {
align-self: center;
}
.chat-message {
background: rgba(240, 235, 225, 0.95);
font-size: 0.9rem;
border-radius: 8px;
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15);
border: 1px solid rgba(139, 115, 85, 0.3);
&.whisper {
background: rgba(220, 220, 210, 0.85);
border: 2px solid #545469;
box-shadow: 0 3px 10px rgba(84, 84, 105, 0.3);
}
.chat-icon {
border: 0;
padding: 2px 6px 2px 2px;
float: left;
width: 64px;
height: 64px;
}
}
.ability-icon {
border: 0;
padding: 2px 2px 2px 2px;
max-width: 32px;
max-height: 32px;
width: auto;
height: auto;
}
.small-ability-icon {
border: 0;
padding: 2px 2px 2px 2px;
max-width: 16px;
max-height: 16px;
width: auto;
height: auto;
}
.combat-icon {
border: 0;
padding: 2px 2px 2px 2px;
max-width: 24px;
max-height: 24px;
width: auto;
height: auto;
}
#sidebar-tabs {
flex: 0 0 32px;
box-sizing: border-box;
margin: 0 0 5px;
border-bottom: 1px solid rgba(0, 0, 0, 0);
box-shadow: inset 0 0 2rem rgba(0, 0, 0, 0.5);
& > .item {
&.active {
border: 1px solid rgba(114, 98, 72, 1);
background: rgba(30, 25, 20, 0.75);
box-shadow: 0 0 6px inset rgba(114, 98, 72, 1);
}
}
}
#controls .scene-control,
#controls .control-tool {
box-shadow: 0 0 3px #000;
margin: 0 0 8px;
border-radius: 0;
background: rgba(30, 25, 20, 1);
background-origin: padding-box;
border-image-width: 4px;
border-image-outset: 0px;
}
#controls .scene-control.active,
#controls .control-tool.active,
#controls .scene-control:hover,
#controls .control-tool:hover {
background: rgba(72, 46, 28, 1);
background-origin: padding-box;
border-image-width: 4px;
border-image-outset: 0px;
box-shadow: 0 0 3px #ff6400;
}
#hotbar {
#action-bar {
#macro-list {
border: 1px solid rgba(72, 46, 28, 1);
box-shadow: 2px 2px 5px #000000;
}
.macro {
border-image: url(img/ui/bg_control.jpg) 21 repeat;
border-image-slice: 6 6 6 6 fill;
border-image-width: 6px 6px 6px 6px;
border-image-outset: 0px 0px 0px 0px;
border-radius: 0px;
}
}
.bar-controls {
background: rgba(30, 25, 20, 1);
border: 1px solid rgba(72, 46, 28, 1);
}
}
#players {
border-image-width: 4px;
border-image-outset: 0px;
background: rgba(30, 25, 20, 1);
}
#navigation {
#scene-list {
.scene {
&.nav-item {
background: rgba(30, 25, 20, 1);
background-origin: padding-box;
border-image-width: 4px;
border-image-outset: 0px;
&.active {
background: rgba(72, 46, 28, 1);
}
}
}
}
#nav-toggle {
background: rgba(30, 25, 20, 1);
background-origin: padding-box;
border-image-width: 4px;
border-image-outset: 0px;
}
}
#navigation #scene-list .scene.view,
#navigation #scene-list .scene.context {
background: rgba(72, 46, 28, 1);
background-origin: padding-box;
border-image-width: 4px;
border-image-outset: 0px;
box-shadow: 0 0 3px #ff6400;
}
.chat-card-button {
box-shadow: inset 0px 1px 0px 0px #a6827e;
background: linear-gradient(
to bottom,
rgba(33, 55, 74, 0.98824) 5%,
rgba(21, 40, 51, 0.67059) 100%
);
background-color: rgba(125, 93, 59, 0);
border-radius: 3px;
border: 2px ridge #846109;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-size: 0.8rem;
padding: 4px 12px 0px 12px;
text-decoration: none;
text-shadow: 0px 1px 0px #4d3534;
position: relative;
margin: 2px;
&:hover {
background: linear-gradient(to bottom, #800000 5%, #3e0101 100%);
background-color: red;
}
&:active {
position: relative;
top: 1px;
}
}
.plus-minus-button {
box-shadow: inset 0px 1px 0px 0px #a6827e;
background: linear-gradient(
to bottom,
rgba(33, 55, 74, 0.98824) 5%,
rgba(21, 40, 51, 0.67059) 100%
);
background-color: rgba(125, 93, 59, 0);
border-radius: 2px;
border: 1px ridge #846109;
display: inline-block;
cursor: pointer;
color: #ffffff;
margin: 2px 2px 2px 2px;
padding: 2px 2px 2px 2px;
text-decoration: none;
text-shadow: 0px 1px 0px #4d3534;
position: relative;
margin: 0px;
}
.plus-minus-button:hover,
.chat-card-button:hover {
background: linear-gradient(to bottom, #800000 5%, #3e0101 100%);
background-color: red;
}
.plus-minus-button:active,
.chat-card-button:active {
position: relative;
top: 1px;
}
.plus-minus {
font-size: 0.9rem;
font-weight: bold;
}
.ul-level1 {
padding-left: 2rem;
}
#pause {
font-size: 2rem;
& > h3 {
color: #ccc;
}
& > img {
content: url(../images/ui/logo_tedeum_pause.webp);
height: 200px;
width: 200px;
top: -200px;
left: calc(50% - 132px);
}
}
#logo {
content: url(../images/ui/logo_tedeum_pause.webp);
width: 100px;
height: 60px;
}
.dice-cell {
padding-left: 12px;
padding-right: 12px;
width: 60px;
text-align: center;
}
.dice-formula,
.dice-total {
height: 54px;
position: relative;
}
// Améliorations esthétiques pour les messages de chat
.chat-roll-details {
background: rgba(255, 255, 255, 0.4);
border-radius: 4px;
padding: 0.4rem 0.5rem;
margin: 0.25rem 0;
border: 1px solid rgba(139, 115, 85, 0.25);
ul {
margin: 0;
padding-left: 0.8rem;
li {
padding: 0.05rem 0;
line-height: 1.25;
strong {
color: rgba(70, 67, 49, 0.9);
}
}
}
}
.chat-roll-result-section {
background: linear-gradient(
135deg,
rgba(255, 250, 240, 0.6),
rgba(245, 240, 230, 0.5)
);
border-radius: 4px;
padding: 0.35rem;
margin: 0.2rem 0;
border: 2px solid rgba(139, 115, 85, 0.3);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
.chat-total-result {
font-size: 1rem;
font-weight: bold;
color: #3d3a2e;
text-align: center;
padding: 0.25rem;
background: rgba(226, 226, 222, 0.5);
border-radius: 4px;
margin-bottom: 0.25rem;
text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.5);
}
}
.chat-dice-formula {
display: inline-block;
background: rgba(139, 115, 85, 0.15);
padding: 0.15rem 0.4rem;
border-radius: 3px;
font-family: monospace;
font-size: 0.9em;
border: 1px solid rgba(139, 115, 85, 0.3);
color: #5a4a3a;
font-weight: 600;
}
.chat-difficulty-badge {
display: inline-block;
background: linear-gradient(
135deg,
rgba(180, 160, 130, 0.4),
rgba(160, 140, 110, 0.35)
);
padding: 0.15rem 0.5rem;
border-radius: 10px;
font-weight: bold;
border: 1px solid rgba(139, 115, 85, 0.4);
color: #4a3a2a;
font-size: 0.85em;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
}
.chat-info-badge {
display: inline-block;
background: rgba(100, 149, 237, 0.15);
padding: 0.15rem 0.4rem;
border-radius: 3px;
border-left: 2px solid rgba(70, 130, 180, 0.6);
margin: 0.08rem 0;
font-size: 0.8em;
color: #2c4a6a;
}
.chat-warning-badge {
display: inline-block;
background: rgba(255, 200, 100, 0.2);
padding: 0.15rem 0.4rem;
border-radius: 3px;
border-left: 2px solid rgba(218, 165, 32, 0.7);
margin: 0.08rem 0;
font-size: 0.8em;
color: #7a5a1a;
}
.chat-actions-bar {
display: flex;
justify-content: center;
gap: 0.3rem;
padding: 0.4rem;
background: rgba(226, 226, 222, 0.4);
border-top: 1px solid rgba(139, 115, 85, 0.25);
border-radius: 0 0 6px 6px;
margin-top: 0.25rem;
a {
transition: all 0.2s ease;
&:hover {
transform: translateY(-2px);
}
}
}
.chat-negative-dice {
display: inline-block;
background: linear-gradient(
135deg,
rgba(255, 100, 100, 0.2),
rgba(220, 80, 80, 0.15)
);
padding: 0.2rem 0.5rem;
border-radius: 4px;
border: 2px solid rgba(178, 34, 34, 0.4);
font-weight: bold;
color: #8b0000;
margin: 0.15rem 0;
box-shadow: 0 1px 3px rgba(178, 34, 34, 0.2);
}
+235
View File
@@ -0,0 +1,235 @@
.te-deum-roll-dialog {
.window-header {
border-radius: 10px 10px 0% 0%;
}
.window-content {
border-radius: 0% 0% 10px 10px;
}
}
.skill-roll-dialog {
background: linear-gradient(
135deg,
rgba(240, 235, 225, 0.98) 0%,
rgba(250, 245, 235, 0.95) 100%
);
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
border: 1px solid rgba(139, 115, 85, 0.3);
overflow: hidden;
.flexcol {
padding: 0.6rem 0.8rem;
gap: 0.4rem;
}
.flexrow {
margin: 0.3rem 0;
padding: 0.4rem 0.5rem;
background: rgba(255, 255, 255, 0.4);
border-radius: 4px;
border-left: 3px solid rgba(139, 115, 85, 0.3);
align-items: center;
gap: 0.5rem;
transition: all 0.2s ease;
&:hover {
background: rgba(255, 255, 255, 0.6);
border-left-color: rgba(139, 115, 85, 0.6);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
}
.roll-dialog-label {
font-family: GreatPrimer;
font-size: 0.85rem;
font-weight: 600;
color: #3d3a2e;
min-width: 140px;
&:first-child {
color: rgba(70, 67, 49, 0.9);
font-weight: 700;
}
}
input[type="checkbox"] {
width: 18px;
height: 18px;
cursor: pointer;
}
div {
margin-top: 4px;
margin-bottom: 4px;
}
.sheet-footer {
padding: 0.5rem 0.8rem;
gap: 0.5rem;
border-top: 1px solid rgba(139, 115, 85, 0.3);
margin-top: 0.5rem;
button {
flex: 1;
padding: 0.4rem 0.8rem;
border-radius: 4px;
font-family: "GreatPrimer";
font-size: 0.9rem;
cursor: pointer;
border: 1px solid rgba(139, 115, 85, 0.5);
background: linear-gradient(135deg, rgba(196, 186, 166, 0.8) 0%, rgba(226, 226, 222, 0.9) 100%);
color: rgba(50, 35, 15, 0.95);
transition: all 0.2s ease;
&:hover {
background: linear-gradient(135deg, rgba(196, 186, 166, 1) 0%, rgba(210, 205, 195, 1) 100%);
border-color: rgba(139, 115, 85, 0.8);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
}
}
}
}
.confront-dice {
border-width: 0px;
}
.bonus-spec {
max-width: 48px;
}
.confront-bonus-container {
position: relative;
flex-grow: 1;
text-align: center;
color: black;
}
.pool-list {
align-items: center;
justify-content: center;
}
.corps-combat-block {
position: relative;
width: 600px;
height: 600px;
}
.silhouette-combat-picture {
width: 250px;
max-width: 250px;
border: 0;
}
.silhouette-combat-block {
position: absolute;
background: white;
border-color: darkgray;
border-style: ridge;
border: 1;
width: 180px;
min-height: 84px;
height: auto;
margin: 0 auto;
font-size: 0.8rem;
align-self: center;
overflow: visible;
}
.silhouette-combat-space {
width: 60px;
min-width: 60px;
}
.center-content {
display: flex;
justify-content: center;
align-items: center;
}
.chat-message .message {
font-family: "GreatPrimer";
font-size: 0.9rem;
}
.fvtt-te-deum-character-creator {
/*background: rgba(226, 226, 222, 0.95);*/
font-family: "GreatPrimer";
font-size: 0.9rem;
.field-title {
font-weight: bold;
}
.form-group label {
color: rgba(30, 25, 15, 0.9);
}
.status-section {
display: block;
max-width: 34rem;
}
.creator-finished-section {
display: block;
max-width: 34rem;
text-align: center;
margin-bottom: 1rem;
}
.stage-main-details {
text-align: center;
margin-top: 1rem;
}
}
.grace-texte {
margin-top: 1rem;
}
.chat-welcome {
text-align: center;
}
.item-name-label {
min-width: 12rem;
}
.compendium-sidebar .directory-item.compendium.locked .compendium-name {
background: rgba(0, 0, 0, 0.1);
}
.compendium-sidebar .directory-item.compendium .compendium-name {
background: rgba(0, 0, 0, 0.1);
}
.compendium-sidebar .directory-item.compendium:hover .compendium-name {
text-shadow: 0 0 8px var(--color-shadow-primary);
background: rgba(0, 0, 0, 0.9);
}
.compendium-sidebar .directory-item.compendium .compendium-footer .source {
display: inline-block;
font-size: var(--font-size-12);
padding: 1px 0.5rem 0 0.25rem;
border-radius: 0 3px 0 0;
background: rgba(0, 0, 0, 0.1);
}
.tedeum-create-character {
align-self: anchor-center;
}
.message-chat-center {
text-align: center;
}
.welcome-message-h3 {
font-size: 1.2rem;
text-align: center;
margin-bottom: 0.5rem;
color: darkred;
}
+414
View File
@@ -0,0 +1,414 @@
.padd-right {
margin-right: 8px;
}
.padd-left {
margin-left: 8px;
}
.fortune-row {
flex-wrap: nowrap;
align-items: center;
gap: 0.4rem;
padding: 0.3rem 0.5rem;
margin-bottom: 0.5rem;
label {
flex: 0 0 auto;
min-width: unset;
font-weight: 600;
color: rgba(70, 67, 49, 0.9);
}
input {
flex: 0 0 auto;
}
}
.stack-left {
align-items: center;
flex-shrink: 1;
flex-grow: 0;
}
.packed-left {
white-space: nowrap;
flex-grow: 0;
}
.input-numeric-short {
width: 52px;
max-width: 52px;
flex-grow: 0;
flex-shrink: 0;
flex-basis: 52px;
margin-right: 0.15rem;
margin-left: 0.15rem;
}
.abilities-table {
align-content: flex-start;
}
.tokenhudext {
display: flex;
flex: 0 !important;
font-weight: 600;
&.left {
justify-content: flex-start;
flex-direction: column;
position: absolute;
top: 2.75rem;
right: 4rem;
}
&.right {
justify-content: flex-start;
flex-direction: column;
position: absolute;
top: 2.75rem;
left: 4rem;
}
}
.control-icon {
&.tokenhudicon {
width: -moz-fit-content;
width: fit-content;
height: -moz-fit-content;
height: fit-content;
min-width: 6rem;
flex-basis: auto;
padding: 0;
line-height: 1rem;
margin: 0.25rem;
&.right {
margin-left: 8px;
}
}
}
#token-hud {
.status-effects {
&.active {
z-index: 2;
}
}
}
.token-sheet {
.window-content {
.flexcol {
.sheet-tabs {
font-size: 0.8rem;
}
}
}
}
.item-checkbox {
height: 25px;
border: 1px solid rgba(115, 105, 83, 0.65098);
border-left: none;
font-weight: 500;
font-size: 1rem;
color: black;
padding-top: 5px;
margin-right: 0px;
width: 45px;
position: relative;
left: 0px;
text-align: center;
}
.skill-label {
font-size: 0.7rem;
}
.skill-good-checkbox {
max-height: 10px;
max-width: 10px;
}
.flex-actions-bar {
flex-grow: 2;
}
#sidebar {
font-size: 1rem;
background-color: #f5f5f5;
background-position: 0px 35px;
background-repeat: no-repeat;
background: rgba(226, 226, 222, 0.95);
color: rgba(19, 18, 18, 0.95);
&.collapsed {
height: 470px !important;
}
#sidebar-tabs {
i {
display: inline-block;
background-position: center;
background-size: cover;
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.75);
}
}
}
#sidebar-tabs > .collapsed,
#chat-controls .chat-control-icon {
color: rgba(19, 18, 18, 0.95);
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.75);
}
.sidebar-tab {
.directory-list {
.entity {
border-top: 1px rgba(0, 0, 0, 0.25);
border-bottom: 0 none;
padding: 0.25rem 0;
&:hover {
background: rgba(0, 0, 0, 0.05);
cursor: pointer;
}
}
}
}
.status-small-label {
font-size: 0.65rem;
}
.no-grow {
flex-grow: 1;
max-width: 32px;
}
.status-col-name {
max-width: 72px;
}
.img-no-border {
max-width: 48px;
max-height: 48px;
border: 0px;
}
.items-title-bg {
margin-top: 6px;
color: rgba(19, 18, 18, 0.95);
background: linear-gradient(
135deg,
rgba(196, 186, 166, 0.6) 0%,
rgba(226, 226, 222, 0.5) 100%
);
border-radius: 4px;
padding: 0.3rem 0.5rem;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
border-left: 4px solid rgba(139, 115, 85, 0.6);
h3 {
margin: 0;
padding: 0;
font-size: 1.15rem;
font-weight: 600;
color: rgba(19, 18, 18, 0.95);
}
}
.item-name-label-header-long2 {
flex-grow: 1;
max-width: 14rem;
min-width: 14rem;
}
.impact-box {
border-width: 2px;
border-color: #000000;
border-radius: 6px;
border: 2px ridge #443307;
margin: 4px;
padding: 4px;
}
.impact-title {
font-size: bold;
display: flex;
align-items: center;
justify-content: center;
margin-left: auto;
margin-right: auto;
text-align: center;
}
.items-title-text {
text-align: center;
font-family: MailartRubberstamp;
margin-left: 4px;
}
.lock-icon {
width: 16px;
height: 16px;
}
.item-sheet-img {
width: 64px;
height: 64px;
border: 2px solid rgba(139, 115, 85, 0.4);
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
object-fit: cover;
}
.item-name-img {
flex-grow: 1;
max-width: 2rem;
min-width: 2rem;
}
.item-field {
margin-top: 4px;
}
.item-field-xp {
margin-top: 4px;
min-width: 8rem;
max-width: 8rem;
}
.item-field-label-short {
flex-grow: 1;
max-width: 4rem;
min-width: 4rem;
}
.item-field-label-medium {
flex-grow: 1;
max-width: 6rem;
min-width: 6rem;
}
.item-field-label-long,
.item-name-label-long {
font-weight: 600;
color: rgba(70, 67, 49, 0.9);
min-width: 160px;
}
.item-field-skill {
flex-grow: 1;
max-width: 6.8rem;
min-width: 6.8rem;
}
.item-field-label-long {
flex-grow: 1;
max-width: 10rem;
min-width: 10rem;
}
.item-field-title-long {
flex-grow: 1;
max-width: 12rem;
min-width: 12rem;
}
.item-field-label-long14 {
flex-grow: 1;
max-width: 14rem;
min-width: 14rem;
color: rgba(70, 67, 49, 0.9);
font-size: 1.0rem;
font-weight: 600;
}
.carac-box {
background: linear-gradient(
135deg,
rgba(226, 226, 222, 0.4) 0%,
rgba(240, 235, 225, 0.3) 100%
);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
border-radius: 0.45rem;
padding: 0.3rem 0.5rem;
border: 1px solid rgba(139, 115, 85, 0.2);
transition: all 0.2s ease;
&:hover {
border-color: rgba(139, 115, 85, 0.4);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
}
}
.comp-box {
max-width: 16rem;
min-width: 16rem;
width: 16rem;
min-height: 1.6rem;
background: linear-gradient(
135deg,
rgba(250, 245, 235, 0.5) 0%,
rgba(255, 255, 255, 0.3) 100%
);
padding: 0.25rem 0.4rem;
margin: 0.15rem;
border-radius: 3px;
border-left: 2px solid rgba(139, 115, 85, 0.3);
transition: all 0.2s ease;
&:hover {
background: rgba(226, 226, 222, 0.4);
border-left-color: rgba(139, 115, 85, 0.6);
transform: translateX(2px);
}
}
.item-control-end {
align-self: flex-end;
}
.alternate-list {
margin-top: 4px;
flex-wrap: nowrap;
}
.item-filler {
flex-grow: 6;
flex-shrink: 7;
}
.item-controls-fixed {
min-width: 2rem;
max-width: 2rem;
}
.item-controls-fixed-full {
min-width: 3rem;
max-width: 3rem;
}
.item-left-pad {
margin-left: 4px;
}
.attribute-label {
font-weight: bold;
}
.flexrow-no-expand {
flex-grow: 0;
}
.item-input-small {
max-width: 16px;
max-height: 12px;
}
.character-summary-rollable {
text-decoration: underline;
}
+240
View File
@@ -0,0 +1,240 @@
.fvtt-te-deum.window-app.sheet .window-content,
.fvtt-te-deum.application.sheet .window-content {
overflow: hidden;
display: flex;
flex-direction: column;
}
// AppV2: le part wrapper et la section root du template doivent propager la hauteur
// Uniquement pour les fiches (.sheet) — les autres fenêtres (dialogs) gardent un layout block normal
.application.fvtt-te-deum.sheet .window-content > [data-application-part],
.application.fvtt-te-deum.sheet .window-content > [data-application-part] > section {
flex: 1 1 0;
min-height: 0;
display: flex;
flex-direction: column;
overflow: hidden;
}
.fvtt-te-deum {
display: flex;
flex-direction: column;
overflow: hidden;
.sheet-header {
flex: 0 0 auto;
overflow: hidden;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
margin-bottom: 10px;
background: linear-gradient(
135deg,
rgba(226, 226, 222, 0.95) 0%,
rgba(240, 235, 225, 0.9) 100%
);
padding: 0.3rem 0.8rem;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
border: 1px solid rgba(139, 115, 85, 0.3);
.profile-img {
flex: 0 0 128px;
width: 128px;
height: auto;
max-height: 128px;
margin-top: 0px;
margin-right: 10px;
-o-object-fit: cover;
object-fit: cover;
-o-object-position: 50% 0;
object-position: 50% 0;
border-width: 0px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
border: 2px solid rgba(139, 115, 85, 0.4);
}
.header-fields {
flex: 1;
}
h1 {
&.charname {
height: 50px;
padding: 0px;
margin: 5px 0;
border-bottom: 0;
}
}
.header-identity-fields {
flex-wrap: nowrap;
align-items: center;
gap: 0.3rem;
margin-top: 0.2rem;
input, select {
flex: 1 1 auto;
font-size: 0.75rem;
height: 1.6rem;
}
}
.header-identity-label {
flex: 0 0 auto;
font-size: 0.7rem;
font-weight: 600;
color: rgba(70, 67, 49, 0.9);
white-space: nowrap;
}
}
.sheet-tabs {
flex: 0;
font-family: "MailartRubberstamp";
font-size: 2.2rem;
}
.tox {
.tox-editor-container {
background: #fff;
}
.tox-edit-area {
padding: 0 8px;
}
}
.resource-label {
font-weight: bold;
text-transform: uppercase;
}
.tabs {
height: 40px;
border-top: 1px solid rgba(139, 115, 85, 0.4);
border-bottom: 1px solid rgba(139, 115, 85, 0.4);
background: linear-gradient(
180deg,
rgba(226, 226, 222, 0.5) 0%,
rgba(240, 235, 225, 0.3) 100%
);
color: #000000;
font-family: "GreatPrimer";
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
.item {
line-height: 40px;
font-weight: bold;
padding: 0 1rem;
transition: all 0.2s ease;
&:hover {
background: rgba(226, 226, 222, 0.6);
color: rgba(70, 67, 49, 0.9);
}
&.active {
text-decoration: underline;
text-shadow: none;
background: rgba(196, 186, 166, 0.4);
border-bottom: 3px solid rgba(139, 115, 85, 0.8);
}
}
}
.items-list {
list-style: none;
margin: 1px 0;
padding: 0;
overflow-y: auto;
.item-header {
font-weight: bold;
}
.item {
height: 30px;
line-height: 24px;
padding: 1px 0;
border-bottom: 1px solid #bbb;
.item-image {
flex: 0 0 24px;
margin-right: 5px;
}
img {
display: block;
}
}
.item-name {
margin: 0;
}
.item-controls {
flex: 0 0 86px;
text-align: right;
}
}
}
.profile-img-container {
margin-right: 0.2rem;
max-width: 140px;
width: 140px;
}
.button-img {
vertical-align: baseline;
width: 8%;
height: 8%;
max-height: 48px;
border-width: 0px;
border: 1px solid rgba(0, 0, 0, 0);
&:hover {
color: rgba(255, 255, 128, 0.7);
border: 1px solid rgba(255, 128, 0, 0.8);
cursor: pointer;
}
}
.button-effect-img {
vertical-align: baseline;
width: 16px;
max-height: 16px;
height: 16;
border-width: 0;
}
.small-button-container {
height: 16px;
width: 16px;
border: 0;
vertical-align: bottom;
}
.fvtt-te-deum .sheet-body {
flex: 1 1 0;
min-height: 0;
overflow: hidden;
font-size: 0.8rem;
font-family: "GreatPrimer";
}
.fvtt-te-deum .sheet-body .tab {
height: 100%;
overflow-y: auto;
font-size: 0.8rem;
font-family: "GreatPrimer";
}
.fvtt-te-deum .sheet-body .tab .editor {
height: 100%;
font-size: 0.8rem;
font-family: "GreatPrimer";
}
+7
View File
@@ -0,0 +1,7 @@
@import "variables";
@import "base";
@import "layout";
@import "actor-sheet";
@import "items";
@import "chat";
@import "dialogs";
+30
View File
@@ -0,0 +1,30 @@
@font-face {
font-family: "MailartRubberstamp";
src: url("../fonts/MailartRubberstamp-Regular.woff") format("woff");
font-family: "GreatPrimer";
src: url("../fonts/IM_FELL_Great_Primer_Roman.woff") format("woff");
}
// Variables LESS
@window-header-title-font-size: 1.3rem;
@window-header-title-font-weight: normal;
@window-header-title-color: #f5f5f5;
@major-button-font-size: 1.05rem;
@major-button-font-weight: normal;
@major-button-color: #dadada;
@tab-header-font-size: 1rem;
@tab-header-font-weight: 700;
@tab-header-color: #403f3e;
@tab-header-color-active: #4a0404;
@actor-input-font-size: 0.8rem;
@actor-input-font-weight: 500;
@actor-input-color: black;
@actor-label-font-size: 0.8rem;
@actor-label-font-weight: 700;
@actor-label-color: rgba(70, 67, 49, 0.76863);
@debug-background-color-red: rgba(255, 0, 0, 0.32941);
@debug-background-color-blue: rgba(29, 0, 255, 0.32941);
@debug-background-color-green: rgba(84, 255, 0, 0.32941);
@debug-box-shadow-red: inset 0 0 2px red;
@debug-box-shadow-blue: inset 0 0 2px blue;
@debug-box-shadow-green: inset 0 0 2px green;
+198 -147
View File
@@ -1,176 +1,227 @@
/** /**
* Extend the basic ActorSheet with some very simple modifications * Feuille de personnage Te Deum - AppV2
* @extends {ActorSheet}
*/ */
import { TeDeumUtility } from "../common/tedeum-utility.js"; import { TeDeumUtility } from "../common/tedeum-utility.js";
const { HandlebarsApplicationMixin } = foundry.applications.api
/* -------------------------------------------- */ /* -------------------------------------------- */
export class TeDeumActorPJSheet extends foundry.appv1.sheets.ActorSheet { export class TeDeumActorPJSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
constructor(options = {}) {
super(options)
this._sheetMode = this.constructor.SHEET_MODES.PLAY
}
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
/** @override */ /** @override */
static get defaultOptions() { static DEFAULT_OPTIONS = {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["fvtt-te-deum", "sheet", "actor"], classes: ["fvtt-te-deum", "sheet", "actor"],
template: "systems/fvtt-te-deum/templates/actors/actor-sheet.hbs", position: {
width: 860, width: 860,
height: 680, height: 680,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "skills" }], },
form: {
submitOnChange: true,
closeOnSubmit: false,
},
window: {
resizable: true,
},
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }], dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
editScore: true actions: {
}); editImage: TeDeumActorPJSheet.#onEditImage,
toggleSheet: TeDeumActorPJSheet.#onToggleSheet,
editItem: TeDeumActorPJSheet.#onEditItem,
deleteItem: TeDeumActorPJSheet.#onDeleteItem,
createItem: TeDeumActorPJSheet.#onCreateItem,
createBlessure: TeDeumActorPJSheet.#onCreateBlessure,
createCompetence: TeDeumActorPJSheet.#onCreateCompetence,
equipItem: TeDeumActorPJSheet.#onEquipItem,
modifyQuantity: TeDeumActorPJSheet.#onModifyQuantity,
rollCompetence: TeDeumActorPJSheet.#onRollCompetence,
rollArme: TeDeumActorPJSheet.#onRollArme,
rollDegats: TeDeumActorPJSheet.#onRollDegats,
},
}
/** @override */
static PARTS = {
sheet: {
template: "systems/fvtt-te-deum/templates/actors/actor-sheet.hbs",
},
}
tabGroups = { primary: "principal" }
get isEditMode() {
return this._sheetMode === this.constructor.SHEET_MODES.EDIT
}
get isPlayMode() {
return this._sheetMode === this.constructor.SHEET_MODES.PLAY
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { /** @override */
async _prepareContext() {
let formData = { const actor = this.document
return {
title: this.title, title: this.title,
id: this.actor.id, id: actor.id,
type: this.actor.type, type: actor.type,
img: this.actor.img, img: actor.img,
name: this.actor.name, name: actor.name,
editable: this.isEditable, editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked", cssClass: this.isEditable ? "editable" : "locked",
system: foundry.utils.duplicate(this.object.system), system: foundry.utils.duplicate(actor.system),
limited: this.object.limited, systemFields: actor.system.schema.fields,
competences: this.actor.getCompetences(), limited: actor.limited,
competences: actor.getCompetences(),
config: foundry.utils.duplicate(game.system.tedeum.config), config: foundry.utils.duplicate(game.system.tedeum.config),
armes: this.actor.getArmes(), armes: actor.getArmes(),
caracList: this.actor.prepareCaracteristiques(), caracList: actor.prepareCaracteristiques(),
providence: this.actor.prepareProvidence(), providence: actor.prepareProvidence(),
arbreCompetences: this.actor.prepareArbreCompetences(), arbreCompetences: actor.prepareArbreCompetences(),
equipements: this.actor.getEquipements(), equipements: actor.getEquipements(),
simples: this.actor.getSimples(), simples: actor.getSimples(),
armures: this.actor.getArmures(), armures: actor.getArmures(),
graces: this.actor.getGraces(), graces: actor.getGraces(),
blessures: this.actor.getBlessures(), blessures: actor.getBlessures(),
maladies: this.actor.getMaladies(), maladies: actor.getMaladies(),
poisons: this.actor.getPoisons(), poisons: actor.getPoisons(),
combat: this.actor.prepareCombat(), combat: actor.prepareCombat(),
bonusDegats: this.actor.getBonusDegats(), bonusDegats: actor.getBonusDegats(),
nbActions: this.actor.getNbActions(), nbActions: actor.getNbActions(),
initiative: this.actor.getInitiative(), initiative: actor.getInitiative(),
pointsArmuresLourdes: this.actor.getNbArmures(), pointsArmuresLourdes: actor.getNbArmures(),
nbArmuresLourdes: this.actor.getNbArmuresLourdesActuel(), nbArmuresLourdes: actor.getNbArmuresLourdesActuel(),
santeModifier: this.actor.getSanteModifier(), santeModifier: actor.getSanteModifier(),
educations: this.actor.getEducations(), educations: actor.getEducations(),
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.description, { async: true }), enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.description, { async: true }),
equipmentfree: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.equipmentfree, { async: true }), enrichedEquipmentFree: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.equipmentfree, { async: true }),
notes: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.notes, { async: true }), enrichedNotes: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.notes, { async: true }),
histoire: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.histoire, { async: true }), enrichedHistoire: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.histoire, { async: true }),
options: this.options, owner: actor.isOwner,
owner: this.document.isOwner, isEditMode: this.isEditMode,
editScore: this.options.editScore, isPlayMode: this.isPlayMode,
isGM: game.user.isGM isGM: game.user.isGM,
} }
this.formData = formData;
console.log("PC : ", formData, this.object);
return formData;
}
/* -------------------------------------------- */
/** @override */
activateListeners(html) {
super.activateListeners(html);
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
html.bind("keydown", function(e) { // Ignore Enter in actores sheet
if (e.keyCode === 13) return false;
});
// Update Inventory Item
html.find('.item-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item-id")
let itemId = li.data("item-id")
const item = this.actor.items.get( itemId );
item.sheet.render(true);
});
// Delete Inventory Item
html.find('.item-delete').click(ev => {
const li = $(ev.currentTarget).parents(".item-id")
TeDeumUtility.confirmDelete(this, li).catch("Error : No deletion confirmed")
})
html.find('.item-add').click(ev => {
let dataType = $(ev.currentTarget).data("type")
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouveau " + dataType, type: dataType }], { renderSheet: true })
})
html.find('.competence-add').click(ev => {
let dataType = $(ev.currentTarget).data("type")
let caracKey = $(ev.currentTarget).data("carac-key")
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvelle " + dataType, type: dataType, system: {caracteristique: caracKey} }], { renderSheet: true })
})
html.find('.subactor-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item");
let actorId = li.data("actor-id");
let actor = game.actors.get( actorId );
actor.sheet.render(true);
});
html.find('.subactor-delete').click(ev => {
const li = $(ev.currentTarget).parents(".item");
let actorId = li.data("actor-id");
this.actor.delSubActor(actorId);
});
html.find('.quantity-minus').click(event => {
const li = $(event.currentTarget).parents(".item");
this.actor.incDecQuantity( li.data("item-id"), -1 );
} );
html.find('.quantity-plus').click(event => {
const li = $(event.currentTarget).parents(".item");
this.actor.incDecQuantity( li.data("item-id"), +1 );
} );
html.find('.roll-competence').click((event) => {
let compId = $(event.currentTarget).data("comp-id")
this.actor.rollCompetence(compId)
});
html.find('.roll-arme').click((event) => {
const armeId = $(event.currentTarget).data("arme-id")
this.actor.rollArme(armeId)
});
html.find('.roll-degats').click((event) => {
const armeId = $(event.currentTarget).data("arme-id")
this.actor.rollDegatsArme(armeId)
});
html.find('.lock-unlock-sheet').click((event) => {
this.options.editScore = !this.options.editScore;
this.render(true);
});
html.find('.item-equip').click(ev => {
const li = $(ev.currentTarget).parents(".item");
this.actor.equipItem( li.data("item-id") );
this.render(true);
});
html.find('.update-field').change(ev => {
const fieldName = $(ev.currentTarget).data("field-name");
let value = Number(ev.currentTarget.value);
this.actor.update( { [`${fieldName}`]: value } );
});
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
setPosition(options = {}) { _onRender(context, options) {
const position = super.setPosition(options); super._onRender(context, options)
const sheetBody = this.element.find(".sheet-body");
const bodyHeight = position.height - 192; // Tab navigation
sheetBody.css("height", bodyHeight); const nav = this.element.querySelector('nav.tabs[data-group]')
return position; if (nav) {
const group = nav.dataset.group
const activeTab = this.tabGroups[group] || "principal"
nav.querySelectorAll('[data-tab]').forEach(link => {
const tab = link.dataset.tab
link.classList.toggle('active', tab === activeTab)
link.addEventListener('click', event => {
event.preventDefault()
this.tabGroups[group] = tab
this.render()
})
})
this.element.querySelectorAll(`[data-group="${group}"][data-tab]`).forEach(content => {
content.classList.toggle('active', content.dataset.tab === activeTab)
})
}
// Ignore Enter key in sheet inputs
this.element.addEventListener('keydown', e => {
if (e.keyCode === 13 && e.target.tagName !== 'TEXTAREA') e.preventDefault()
})
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ // #region Static action handlers
_updateObject(event, formData) {
// Update the Actor static async #onEditImage(event) {
return this.object.update(formData); const fp = new FilePicker({
type: "image",
current: this.document.img,
callback: path => this.document.update({ img: path }),
})
fp.browse()
} }
static async #onToggleSheet(event) {
this._sheetMode = this.isEditMode
? this.constructor.SHEET_MODES.PLAY
: this.constructor.SHEET_MODES.EDIT
this.render()
}
static async #onEditItem(event, target) {
const li = target.closest("[data-item-id]")
const item = this.actor.items.get(li?.dataset.itemId)
if (item) item.sheet.render(true)
}
static async #onDeleteItem(event, target) {
const li = target.closest("[data-item-id]")
await TeDeumUtility.confirmDelete(this, li)
}
static async #onCreateItem(event, target) {
const type = target.dataset.type
await this.actor.createEmbeddedDocuments('Item', [{ name: "Nouveau " + type, type }], { renderSheet: true })
}
static async #onCreateBlessure(event, target) {
const type = target.dataset.type
await this.actor.createEmbeddedDocuments('Item', [{
name: "Nouvelle " + type, type,
system: { typeBlessure: "estafilade", localisation: "corps", value: 0, appliquee: true, description: "" }
}], { renderSheet: true })
}
static async #onCreateCompetence(event, target) {
const type = target.dataset.type
const caracKey = target.dataset.caracKey
await this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvelle " + type, type, system: { caracteristique: caracKey } }], { renderSheet: true })
}
static async #onEquipItem(event, target) {
const li = target.closest("[data-item-id]")
if (!li?.dataset.itemId) return
await this.actor.equipItem(li.dataset.itemId)
}
static async #onModifyQuantity(event, target) {
const li = target.closest("[data-item-id]")
if (!li?.dataset.itemId) return
const item = this.actor.items.get(li.dataset.itemId)
if (!item) return
const delta = parseInt(target.dataset.qty) || 0
await this.actor.incDecQuantity(li.dataset.itemId, delta)
}
static async #onRollCompetence(event, target) {
const li = target.closest("[data-item-id]")
if (!li?.dataset.itemId) return
await this.actor.rollCompetence(li.dataset.itemId)
}
static async #onRollArme(event, target) {
const li = target.closest("[data-item-id]")
if (!li?.dataset.itemId) return
await this.actor.rollArme(li.dataset.itemId)
}
static async #onRollDegats(event, target) {
const li = target.closest("[data-item-id]")
if (!li?.dataset.itemId) return
await this.actor.rollDegatsArme(li.dataset.itemId)
}
// #endregion
} }
+147 -32
View File
@@ -65,14 +65,43 @@ export class TeDeumActor extends Actor {
super._preUpdate(changed, options, user); super._preUpdate(changed, options, user);
} }
/* -------------------------------------------- */
getCompetenceScore(compName) { getCompetenceScore(compName) {
let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == compName.toLowerCase()) let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == compName.toLowerCase())
if (competence) { if (competence) {
if (competence.system.isBase) {
return this.system.caracteristiques[competence.system.caracteristique].value
}
return competence.system.score return competence.system.score
} }
return 0 return 0
} }
/* -------------------------------------------- */
getMeilleureCompetenceMainGauche(comp) {
let compScore = this.getCompetenceScore(comp.name)
let mainGaucheScore = this.getCompetenceScore("main gauche")
if (mainGaucheScore < compScore) {
ui.notifications.info(`${this.name} : Utilisation de la compétence Main Gauche au lieu de ${comp.name}`)
let mainGaucheComp = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "main gauche")
if (!mainGaucheComp) {
// Create a fake competence object
mainGaucheComp = foundry.utils.duplicate(comp)
mainGaucheComp.name = "Main Gauche"
mainGaucheComp.system.isBase = false
mainGaucheComp.system.score = 0
mainGaucheComp.system.caracteristique = "adresse"
mainGaucheComp.system.description = "Compétence Main Gauche (automatique)"
mainGaucheComp.system.isMainGauche = true
return mainGaucheComp
} else {
return mainGaucheComp
}
} else {
return comp
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
_onUpdate(changed, options, userId) { _onUpdate(changed, options, userId) {
let updates = [] let updates = []
@@ -112,12 +141,6 @@ export class TeDeumActor extends Actor {
updates.push({ _id: initiative.id, "system.score": Number(newScore) }) updates.push({ _id: initiative.id, "system.score": Number(newScore) })
} }
let actionsTour = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "actions/tour")
newScore = this.getCommonBaseValue(this.system.caracteristiques.adresse.value)
if (actionsTour && actionsTour?.system.score != newScore) {
updates.push({ _id: actionsTour.id, "system.score": Number(newScore) })
}
let effort = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "effort") let effort = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "effort")
newScore = this.getCommonBaseValue(this.system.caracteristiques.puissance.value) newScore = this.getCommonBaseValue(this.system.caracteristiques.puissance.value)
if (effort && effort?.system.score != newScore) { if (effort && effort?.system.score != newScore) {
@@ -147,7 +170,7 @@ export class TeDeumActor extends Actor {
getCommonBaseValue(value) { getCommonBaseValue(value) {
return game.system.tedeum.config.COMMON_VALUE[value]?.value || 0 return game.system.tedeum.config.COMMON_VALUE[value]?.value || 0
} }
getInitiative() { getInitiativeValue() {
return game.system.tedeum.config.COMMON_VALUE[this.system.caracteristiques.adresse.value]?.value || 0 return game.system.tedeum.config.COMMON_VALUE[this.system.caracteristiques.adresse.value]?.value || 0
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -155,6 +178,24 @@ export class TeDeumActor extends Actor {
return game.system.tedeum.config.BONUS_DEGATS[this.system.caracteristiques.puissance.value] return game.system.tedeum.config.BONUS_DEGATS[this.system.caracteristiques.puissance.value]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getAttaqueBonusDegats(rollData = undefined) {
let base = game.system.tedeum.config.BONUS_DEGATS[this.system.caracteristiques.puissance.value].value
let additionalBonus = 0
if (rollData) {
// Spécificité armes naturelle avec gantelet
if (rollData?.arme?.system.specificites?.poing?.hasSpec && this.items.find(item => item.type == "armure" && item.name.toLowerCase() == "gantelet" && item.system.equipe)) {
additionalBonus += 1
rollData.gantelet = true
}
if (rollData.isChargeAPied) {
additionalBonus += this.getCompetenceScore("course")
} else if (rollData.isChargeACheval) {
additionalBonus += this.getCompetenceScore("equitation")
}
}
return base + additionalBonus
}
/* -------------------------------------------- */
getNbArmures() { getNbArmures() {
return game.system.tedeum.config.MAX_ARMURES_LOURDES[this.system.caracteristiques.puissance.value] return game.system.tedeum.config.MAX_ARMURES_LOURDES[this.system.caracteristiques.puissance.value]
} }
@@ -266,41 +307,105 @@ export class TeDeumActor extends Actor {
modTotal += blessDef.modifier modTotal += blessDef.modifier
} }
// Si le nombre de blessures est supérieur au score d'endurance, alors malus supplémentaire // Si le nombre de blessures est supérieur au score d'endurance, alors malus supplémentaire
let endurance = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "endurance") let enduranceScore = this.getCompetenceScore("endurance")
if (blessures.length > endurance.system.score) { if (blessures.length > enduranceScore) {
modTotal += -1 modTotal += -1
} }
return modTotal return modTotal
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async appliquerDegats(rollData) { async appliquerBlessure(blessureId, locId, comment = "") {
let combat = this.prepareCombat() let blessure = game.system.tedeum.config.blessures[blessureId]
rollData.defenderName = this.name if (!blessure) {
let touche = combat[rollData.loc.id].touche ui.notifications.warn("Type de blessure inconnu : " + blessureId)
if (rollData.degats > 0 && rollData.degats > touche) { console.error("Type de blessure inconnu : " + blessureId)
let diff = rollData.degats - touche return
for (let bId in game.system.tedeum.config.blessures) { }
let blessure = game.system.tedeum.config.blessures[bId]
if (diff >= blessure.degatsMin && diff <= blessure.degatsMax) {
// Create a new blessure object // Create a new blessure object
let blessureObj = { let blessureObj = {
name: blessure.label, name: blessure.label,
type: "blessure", type: "blessure",
system: { system: {
typeBlessure: bId, typeBlessure: blessureId,
localisation: locId || "maindroite",
value: blessure.value,
appliquee: true,
description: comment,
}
}
this.createEmbeddedDocuments('Item', [blessureObj]);
}
/* -------------------------------------------- */
getArmorDegatsModifier(rollData, combat) {
let loc = combat[rollData.loc.id]
// Sans armure
if (loc.armures.length == 0) {
return rollData.arme.system.degatsArmure.sansarmure
}
// Avec armure de cuir
if (loc.armures.find(a => a.system.typeArmure == "cuir")) {
return rollData.arme.system.degatsArmure.cuir
}
// Avec armure de maille
if (loc.armures.find(a => a.system.typeArmure == "maille")) {
return rollData.arme.system.degatsArmure.mailles
}
// Avec armure de plate
if (loc.armures.find(a => a.system.typeArmure == "plate")) {
return rollData.arme.system.degatsArmure.plates
}
return 0
}
/* -------------------------------------------- */
async appliquerDegats(rollData) {
let combat = this.prepareCombat()
rollData.defenderName = this.name
let touche = combat[rollData.loc.id].touche
let armorDegatModifier = this.getArmorDegatsModifier(rollData, combat)
rollData.degats += armorDegatModifier
rollData.armorDegatModifier = armorDegatModifier
let blessureId = "indemne"
if (rollData.degats > 0 && rollData.degats > touche) {
let diff = rollData.degats - touche
for (let bId in game.system.tedeum.config.blessures) {
let blessure = game.system.tedeum.config.blessures[bId]
if (diff >= blessure.degatsMin && diff <= blessure.degatsMax) {
if (rollData.isReussiteCritique) {
bId = game.system.tedeum.config.blessuresOrder[blessure.value + 1]
}
blessureId = bId
break
}
}
}
if (rollData.isReussiteCritique && blessureId == "indemne") { // Critical success without degats => lightest blessure
blessureId = "estafilade"
}
console.log("Appliquer dégats", rollData, combat, blessureId)
if (blessureId != "indemne") {
let blessure = game.system.tedeum.config.blessures[blessureId]
// Create a new blessure object
let blessureObj = {
name: blessure.label,
type: "blessure",
system: {
typeBlessure: blessureId,
localisation: rollData.loc.id, localisation: rollData.loc.id,
value: blessure.value,
appliquee: true, appliquee: true,
description: "Blessure infligée par un coup de " + rollData.arme.name + " de " + rollData.alias, description: "Blessure infligée par un coup de " + rollData.arme.name + " de " + rollData.alias,
} }
} }
rollData.blessure = blessureObj rollData.blessure = blessureObj
rollData.touche = touche
this.createEmbeddedDocuments('Item', [blessureObj]); this.createEmbeddedDocuments('Item', [blessureObj]);
} }
}
}
// Display the relevant chat message // Display the relevant chat message
let msg = await TeDeumUtility.createChatWithRollMode(rollData.alias, { let msg = await TeDeumUtility.createChatWithRollMode(rollData.alias, {
content: await renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-blessure-result.hbs`, rollData) content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-blessure-result.hbs`, rollData)
}) })
await msg.setFlag("world", "te-deum-rolldata", rollData) await msg.setFlag("world", "te-deum-rolldata", rollData)
} }
@@ -334,7 +439,7 @@ export class TeDeumActor extends Actor {
let providence = foundry.utils.deepClone(this.system.providence) let providence = foundry.utils.deepClone(this.system.providence)
providence.name = "Providence" providence.name = "Providence"
if (this.system.genre.toLowerCase() == "homme") { if (this.system.genre.toLowerCase() == "homme") {
providence.qualite = game.system.tedeum.config.providence[providence.value].labelH providence.qualite = game.system.tedeum.config.providence[providence.value].labelM
} else { } else {
providence.qualite = game.system.tedeum.config.providence[providence.value].labelF providence.qualite = game.system.tedeum.config.providence[providence.value].labelF
} }
@@ -382,6 +487,7 @@ export class TeDeumActor extends Actor {
xp = Math.max(xp + value, 0) xp = Math.max(xp + value, 0)
await this.update({ [`system.caracteristiques.${key}.experience`]: xp }) await this.update({ [`system.caracteristiques.${key}.experience`]: xp })
this.sheet?.render(true) this.sheet?.render(true)
ui.notifications.info(`+${value} XP en ${game.system.tedeum.config.caracteristiques[key].label}`)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -529,12 +635,16 @@ export class TeDeumActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
getInitiativeScore() { getInitiativeScore() {
let initiative = this.items.find(it => it.type == "competence" && it.name.toLowerCase() == "initiative") let initiative = this.getInitiativeValue()
if (initiative) { // Vérifie les armes avec bonus d'initiative
return initiative.system.score let armes = this.getArmes()
for (let arme of armes) {
if (arme.system.equipe && Number(arme.system.initiativeBonus) && Number(arme.system.initiativeBonus) != 0) {
ui.notifications.info("L'arme " + arme.name + " vous confère un bonus d'initiative de " + arme.system.initiativeBonus)
initiative += arme.system.initiativeBonus
} }
ui.notifications.warn("Impossible de trouver la compétence Initiative pour l'acteur " + this.name) }
return -1; return initiative
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -595,6 +705,7 @@ export class TeDeumActor extends Actor {
let rollData = this.getCommonCompetence(compId) let rollData = this.getCommonCompetence(compId)
rollData.mode = "competence" rollData.mode = "competence"
rollData.title = rollData.competence.name rollData.title = rollData.competence.name
rollData.compScore = rollData.competence.system.isBase ? this.system.caracteristiques[rollData.competence.system.caracteristique].value : rollData.competence.system.score
this.startRoll(rollData).catch("Error on startRoll") this.startRoll(rollData).catch("Error on startRoll")
} }
@@ -602,7 +713,7 @@ export class TeDeumActor extends Actor {
async rollDegatsArme(armeId) { async rollDegatsArme(armeId) {
let weapon = this.items.get(armeId) let weapon = this.items.get(armeId)
if (weapon) { if (weapon) {
let bDegats = 0 let bDegats = { value: 0 }
if (weapon.system.typeArme == "melee") { if (weapon.system.typeArme == "melee") {
bDegats = this.getBonusDegats() bDegats = this.getBonusDegats()
} }
@@ -617,7 +728,7 @@ export class TeDeumActor extends Actor {
rollData.degats = degatsRoll.total rollData.degats = degatsRoll.total
let msg = await TeDeumUtility.createChatWithRollMode(rollData.alias, { let msg = await TeDeumUtility.createChatWithRollMode(rollData.alias, {
content: await renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-degats-result.hbs`, rollData) content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-degats-result.hbs`, rollData)
}) })
await msg.setFlag("world", "te-deum-rolldata", rollData) await msg.setFlag("world", "te-deum-rolldata", rollData)
console.log("Rolldata result", rollData) console.log("Rolldata result", rollData)
@@ -653,9 +764,14 @@ export class TeDeumActor extends Actor {
let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == compName.toLowerCase()) let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == compName.toLowerCase())
if (competence) { if (competence) {
rollData.competence = competence rollData.competence = competence
rollData.compScore = rollData.competence.system.isBase ? this.system.caracteristiques[rollData.competence.system.caracteristique].value : rollData.competence.system.score
let c = foundry.utils.duplicate(this.system.caracteristiques[competence.system.caracteristique]) let c = foundry.utils.duplicate(this.system.caracteristiques[competence.system.caracteristique])
this.updateCarac(c, competence.system.caracteristique) this.updateCarac(c, competence.system.caracteristique)
rollData.carac = c rollData.carac = c
rollData.allongeLabel = game.system.tedeum.config.armeAllonges[weapon.system.allonge].label
rollData.allongeId = "courte"
rollData.allonges = foundry.utils.duplicate(game.system.tedeum.config.allonges[weapon.system.allonge])
} else { } else {
ui.notifications.warn("Impossible de trouver la compétence " + compName) ui.notifications.warn("Impossible de trouver la compétence " + compName)
return return
@@ -669,8 +785,7 @@ export class TeDeumActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async startRoll(rollData) { async startRoll(rollData) {
console.log("startRoll", rollData) console.log("startRoll", rollData)
let rollDialog = await TeDeumRollDialog.create(this, rollData) await TeDeumRollDialog.create(this, rollData)
rollDialog.render(true)
} }
} }
+49 -5
View File
@@ -6,13 +6,14 @@ export class TeDeumCharacterCreator {
async init() { async init() {
this.stages = {} this.stages = {}
this.currentStage = "origineSociale" this.currentStage = "origineSociale"
this.sex = undefined this.sexe = undefined
this.origineSociale = undefined this.origineSociale = undefined
this.religion = undefined this.religion = undefined
this.caracBonus = {} this.caracBonus = {}
this.competenceBonus = {} this.competenceBonus = {}
this.suiviReponses = [] this.suiviReponses = []
this.competences = TeDeumUtility.getCompetencesForDropDown() this.competences = TeDeumUtility.getCompetencesForDropDown()
this.choiceSummary = {}
for (let k in game.system.tedeum.config.caracteristiques) { for (let k in game.system.tedeum.config.caracteristiques) {
this.caracBonus[k] = { value: 0 } this.caracBonus[k] = { value: 0 }
@@ -39,6 +40,7 @@ export class TeDeumCharacterCreator {
} else { } else {
this.competenceBonus[compName].value += 1 this.competenceBonus[compName].value += 1
} }
this.choiceSummary[this.currentStage].competences[compName] = 1
} }
/*--------------------------------------------*/ /*--------------------------------------------*/
@@ -116,6 +118,7 @@ export class TeDeumCharacterCreator {
/*--------------------------------------------*/ /*--------------------------------------------*/
async askQuestionnaire(stage, context) { async askQuestionnaire(stage, context) {
context.subtitle = "Questionnaire" context.subtitle = "Questionnaire"
this.choiceSummary[this.currentStage].questionnaire = {}
for (let key in stage.system.questionnaire) { for (let key in stage.system.questionnaire) {
let question = stage.system.questionnaire[key] let question = stage.system.questionnaire[key]
@@ -170,13 +173,14 @@ export class TeDeumCharacterCreator {
let compName = context.competences[context.responseKey] || selectedResponse.compName let compName = context.competences[context.responseKey] || selectedResponse.compName
this.increaseCompetence(compName) this.increaseCompetence(compName)
this.suiviReponses.push({ etape: stage.name, question: question.question, reponse: selectedResponse.reponse, compName: compName }) this.suiviReponses.push({ key: this.currentStage, etape: stage.name, question: question.question, reponse: selectedResponse.reponse, compName: compName })
} }
} }
/*------------- -------------------------------*/ /*------------- -------------------------------*/
async askCompetences(stage, context) { async askCompetences(stage, context) {
context.subtitle = "Choix des Compétences" context.subtitle = "Choix des Compétences"
this.choiceSummary[this.currentStage].competences = {}
context.fixedCompetences = {} context.fixedCompetences = {}
context.selectCompetences = {} context.selectCompetences = {}
@@ -273,6 +277,10 @@ export class TeDeumCharacterCreator {
/*------------- -------------------------------*/ /*------------- -------------------------------*/
async askCarac(stage, context) { async askCarac(stage, context) {
context.subtitle = "Choix des Caractéristiques" context.subtitle = "Choix des Caractéristiques"
this.choiceSummary[this.currentStage] = {
caracBonus : {},
competences : {}
}
let selected = [] let selected = []
for (let i = 0; i < stage.system.nbChoixCarac; i++) { for (let i = 0; i < stage.system.nbChoixCarac; i++) {
@@ -312,6 +320,7 @@ export class TeDeumCharacterCreator {
} }
this.caracBonus[choiceResult.carac].value += 1 this.caracBonus[choiceResult.carac].value += 1
selected.push(choiceResult.carac) selected.push(choiceResult.carac)
this.choiceSummary[this.currentStage].caracBonus[choiceResult.carac] = 1
} }
} }
@@ -360,6 +369,12 @@ export class TeDeumCharacterCreator {
for (let key in this.origineSociale.caracteristiques) { for (let key in this.origineSociale.caracteristiques) {
this.caracBonus[key].value += this.origineSociale.caracteristiques[key] this.caracBonus[key].value += this.origineSociale.caracteristiques[key]
} }
this.choiceSummary['origineSociale'] = {
sexe: this.sexe,
religion: this.religion,
origineSociale: this.origineSociale.label,
caracBonus: this.caracBonus,
}
this.currentStage = "pouponniere" this.currentStage = "pouponniere"
} }
@@ -388,6 +403,7 @@ export class TeDeumCharacterCreator {
this.pouponniere = foundry.utils.duplicate(stage.items.find(item => item.id === choiceResult.selectedItem)) this.pouponniere = foundry.utils.duplicate(stage.items.find(item => item.id === choiceResult.selectedItem))
context.title = `La Pouponnière - ${this.pouponniere.name}` context.title = `La Pouponnière - ${this.pouponniere.name}`
TeDeumUtility.prepareEducationContent(this.pouponniere); TeDeumUtility.prepareEducationContent(this.pouponniere);
this.choiceSummary['pouponniere'] = {}
context.label = "Valider l'augmentation de caracteristique" context.label = "Valider l'augmentation de caracteristique"
await this.askCarac(this.pouponniere, context) await this.askCarac(this.pouponniere, context)
@@ -559,7 +575,7 @@ export class TeDeumCharacterCreator {
for (let compName in this.competenceBonus) { for (let compName in this.competenceBonus) {
let comp = actor.items.find( i => i.type == "competence" && i.name.toLowerCase() === compName.toLowerCase()) let comp = actor.items.find( i => i.type == "competence" && i.name.toLowerCase() === compName.toLowerCase())
if (comp) { if (comp) {
updateComp.push({ _id: comp._id, "system.score": this.competenceBonus[compName].value }) updateComp.push({ _id: comp._id, "system.score": comp.system.score + this.competenceBonus[compName].value })
} else { } else {
toAdd.push( compName) toAdd.push( compName)
} }
@@ -581,8 +597,36 @@ export class TeDeumCharacterCreator {
await actor.update({ [`system.fortune.${this.origineSociale.cagnotteUnit}`]: newArgent}) await actor.update({ [`system.fortune.${this.origineSociale.cagnotteUnit}`]: newArgent})
let histoire = "" let histoire = ""
for (let reponse of this.suiviReponses) { for ( let key in this.choiceSummary) {
histoire += `<p>${reponse.question}<br>${reponse.reponse} (${reponse.compName})</p>` let stageSummary = this.choiceSummary[key]
if (stageSummary.sexe) {
histoire += `<h3>Origine Sociale</h3>`
histoire += `<p>${stageSummary.sexe} - ${stageSummary.religion} - ${stageSummary.origineSociale}</p>`
} else {
histoire += `<h3>${game.system.tedeum.config.etapesEducation[key].label}</h3>`
}
if (stageSummary.caracBonus) {
histoire += `<p><strong>Caractéristiques : </strong><ul>`
for (let caracKey in stageSummary.caracBonus) {
histoire += `<li>${TeDeumUtility.upperFirst(caracKey)} +1</li>`
}
histoire += `</ul></p>`
}
if (stageSummary.competences) {
histoire += `<p><strong>Compétences : </strong><ul>`
for (let compName in stageSummary.competences) {
histoire += `<li>${TeDeumUtility.upperFirst(compName)} +1</li>`
}
histoire += `</ul></p>`
}
let questions = this.suiviReponses.filter( r => r.key === key)
if (questions.length > 0) {
histoire += `<p><strong>Réponses au questionnaire : </strong><ul>`
for (let question of questions) {
histoire += `<li>${question.question} : <i>${question.reponse}</i> (${TeDeumUtility.upperFirst(question.compName)}+1)</li>`
}
histoire += `</ul></p>`
}
} }
await actor.update({ "system.histoire": histoire}) await actor.update({ "system.histoire": histoire})
actor.render(true) actor.render(true)
+24
View File
@@ -10,12 +10,36 @@ export class TeDeumCombat extends Combat {
for (let cId of ids) { for (let cId of ids) {
const c = this.combatants.get(cId); const c = this.combatants.get(cId);
let initBonus = c.actor ? c.actor.getInitiativeScore(this.id, cId) : -1; let initBonus = c.actor ? c.actor.getInitiativeScore(this.id, cId) : -1;
console.log("Init Bonus : ", c.name, initBonus)
await this.updateEmbeddedDocuments("Combatant", [{ _id: cId, initiative: initBonus }]); await this.updateEmbeddedDocuments("Combatant", [{ _id: cId, initiative: initBonus }]);
} }
return this; return this;
} }
/* -------------------------------------------- */
async modifyAction(combatantId, delta, isMainGauche = false) {
let combatant = this.combatants.get(combatantId)
if (!combatant) return;
let ca = combatant.getFlag("world", "available-actions")
if (!ca) {
ca = { nbActions: 1, nbActionsMainGauche: 0 }
}
if (isMainGauche) {
ca.nbActionsMainGauche += delta
} else {
ca.nbActions += delta
}
if (ca.nbActionsMainGauche < 0) ca.nbActionsMainGauche = 0
if (ca.nbActions < 0) ca.nbActions = 0
console.log("Modify Action : ", combatant.name, ca)
if (game.user.isGM) {
await TeDeumUtility.updateCombatantActions(combatant, ca)
} else {
game.socket.emit("system.fvtt-te-deum", { msg: "msg_modify_combat_action", data: { combatantId: combatantId, ca: ca } })
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async checkTurnPosition() { static async checkTurnPosition() {
while (game.combat.turn > 0) { while (game.combat.turn > 0) {
+44 -27
View File
@@ -15,19 +15,35 @@ export const TEDEUM_CONFIG = {
{ value: 10 }, { value: 30 }, { value: 50 }], { value: 10 }, { value: 30 }, { value: 50 }],
LOCALISATION: { LOCALISATION: {
"pieddroit": { label: "Pied Droit", value: 1, locMod: 0, id: "pieddroit", nbArmure: 1, score: { min: 1, max: 1 }, coord: { top: 500, left: 0 } }, "pieddroit": { label: "Pied Droit", value: 1, locMod: 0, id: "pieddroit", categorie: "pied", nbArmure: 1, score: { min: 1, max: 1 }, coord: { top: 500, left: 0 } },
"jambedroite": { label: "Jambe Droite", value: 1, locMod: -1, id: "jambedroite", nbArmure: 1, score: { min: 3, max: 4 }, coord: { top: 400, left: 100 } }, "jambedroite": { label: "Jambe Droite", value: 1, locMod: -1, id: "jambedroite", categorie: "jambe", nbArmure: 1, score: { min: 3, max: 4 }, coord: { top: 400, left: 100 } },
"jambegauche": { label: "Jambe Gauche", value: 1, locMod: -1, id: "jambegauche", nbArmure: 1, score: { min: 5, max: 6 }, coord: { top: 400, left: 300 } }, "jambegauche": { label: "Jambe Gauche", value: 1, locMod: -1, id: "jambegauche", categorie: "jambe", nbArmure: 1, score: { min: 5, max: 6 }, coord: { top: 400, left: 300 } },
"piedgauche": { label: "Pied Gauche", value: 1, locMod: 0, id: "piedgauche", nbArmure: 1, score: { min: 2, max: 2 }, coord: { top: 500, left: 400 } }, "piedgauche": { label: "Pied Gauche", value: 1, locMod: 0, id: "piedgauche", categorie: "pied", nbArmure: 1, score: { min: 2, max: 2 }, coord: { top: 500, left: 400 } },
"maindroite": { label: "Main Droite", value: 1, locMod: 0, id: "maindroite", nbArmure: 1, score: { min: 7, max: 7 }, coord: { top: 0, left: 0 } }, "maindroite": { label: "Main Droite", value: 1, locMod: 0, id: "maindroite", categorie: "main", nbArmure: 1, score: { min: 7, max: 7 }, coord: { top: 0, left: 0 } },
"maingauche": { label: "Main Gauche", value: 1, locMod: 0, id: "maingauche", nbArmure: 1, score: { min: 8, max: 8 }, coord: { top: 0, left: 400 } }, "maingauche": { label: "Main Gauche", value: 1, locMod: 0, id: "maingauche", categorie: "main", nbArmure: 1, score: { min: 8, max: 8 }, coord: { top: 0, left: 400 } },
"brasdroit": { label: "Bras Droit", value: 1, locMod: -1, id: "brasdroit", nbArmure: 2, score: { min: 9, max: 10 }, coord: { top: 200, left: 0 } }, "brasdroit": { label: "Bras Droit", value: 1, locMod: -1, id: "brasdroit", categorie: "bras", nbArmure: 2, score: { min: 9, max: 10 }, coord: { top: 200, left: 0 } },
"brasgauche": { label: "Bras Gauche", value: 1, locMod: -1, id: "brasgauche", nbArmure: 2, score: { min: 11, max: 12 }, coord: { top: 200, left: 400 } }, "brasgauche": { label: "Bras Gauche", value: 1, locMod: -1, id: "brasgauche", categorie: "bras", nbArmure: 2, score: { min: 11, max: 12 }, coord: { top: 200, left: 400 } },
"corps": { label: "Corps", value: 1, id: "corps", locMod: -2, nbArmure: 2, score: { min: 13, max: 17 }, coord: { top: 200, left: 200 } }, "corps": { label: "Corps", value: 1, id: "corps", categorie: "corps", locMod: -2, nbArmure: 2, score: { min: 13, max: 17 }, coord: { top: 200, left: 200 } },
"tete": { label: "Tête", value: 1, id: "tete", locMod: -2, nbArmure: 2, score: { min: 18, max: 20 }, coord: { top: 0, left: 200 } }, "tete": { label: "Tête", value: 1, id: "tete", categorie: "tete", locMod: -2, nbArmure: 2, score: { min: 18, max: 20 }, coord: { top: 0, left: 200 } },
},
ATTAQUE_CIBLEES: {
"aucune": { label: "Aucune", id: "aucune", locMod: 0, description: "Attaque non ciblée" },
"pieddroit": { label: "Pied Droit", id: "pieddroit", locMod: 0, description: "Attaque ciblée sur le pied droit" },
"jambedroite": { label: "Jambe Droite", id: "jambedroite", locMod: -1, description: "Attaque ciblée sur la jambe droite" },
"jambegauche": { label: "Jambe Gauche", id: "jambegauche", locMod: -1, description: "Attaque ciblée sur la jambe gauche" },
"piedgauche": { label: "Pied Gauche", id: "piedgauche", locMod: 0, description: "Attaque ciblée sur le pied gauche" },
"maindroite": { label: "Main Droite", id: "maindroite", locMod: 0, description: "Attaque ciblée sur la main droite" },
"maingauche": { label: "Main Gauche", id: "maingauche", locMod: 0, description: "Attaque ciblée sur la main gauche" },
"brasdroit": { label: "Bras Droit", id: "brasdroit", locMod: -1, description: "Attaque ciblée sur le bras droit" },
"brasgauche": { label: "Bras Gauche", id: "brasgauche", locMod: -1, description: "Attaque ciblée sur le bras gauche" },
"corps": { label: "Corps", id: "corps", locMod: -2, description: "Attaque ciblée sur le corps" },
"tete": { label: "Tête", id: "tete", locMod: -2, description: "Attaque ciblée sur la tête" },
}, },
ARME_SPECIFICITE: { ARME_SPECIFICITE: {
"poing": { label: "Poings", id: "poing", melee: true, tir: false },
"pied": { label: "Pieds", id: "pied", melee: true, tir: false },
"encombrante": { label: "Encombrante", id: "encombrante", melee: true, tir: true }, "encombrante": { label: "Encombrante", id: "encombrante", melee: true, tir: true },
"maintiendistance": { label: "Maintien à distance", id: "maintiendistance", melee: true, tir: false }, "maintiendistance": { label: "Maintien à distance", id: "maintiendistance", melee: true, tir: false },
"coupassomant": { label: "Coup assomant", id: "coupassomant", melee: true, tir: false }, "coupassomant": { label: "Coup assomant", id: "coupassomant", melee: true, tir: false },
@@ -43,11 +59,11 @@ export const TEDEUM_CONFIG = {
}, },
ARME_PORTEES: { ARME_PORTEES: {
"brulepourpoint": { label: "Brûle-pourpoint", difficulty: "facile", id: "brulepourpoint" }, "brulepourpoint": { label: "Brûle-pourpoint (5)", difficulty: "facile", id: "brulepourpoint" },
"courte": { label: "Courte", difficulty: "pardefaut", id: "courte" }, "courte": { label: "Courte (7)", difficulty: "pardefaut", id: "courte" },
"moyenne": { label: "Moyenne", difficulty: "difficile", id: "moyenne" }, "moyenne": { label: "Moyenne (11)", difficulty: "difficile", id: "moyenne" },
"longue": { label: "Longue", difficulty: "perilleux", id: "longue" }, "longue": { label: "Longue (13)", difficulty: "perilleux", id: "longue" },
"extreme": { label: "Extrême", difficulty: "desespere", id: "extreme" }, "extreme": { label: "Extrême (15)", difficulty: "desespere", id: "extreme" },
}, },
genre: { genre: {
@@ -102,10 +118,10 @@ export const TEDEUM_CONFIG = {
adresse: { id: "adresse", value: "adresse", label: "Adresse", description: "Cette caractéristique correspond à la rapidité et la dextérité du personnage. Elle livre le nombre d'actions qu'un personnage peut accomplir en un tour de combat et permet d'évaluer les compétences de base Initiative & Course." }, adresse: { id: "adresse", value: "adresse", label: "Adresse", description: "Cette caractéristique correspond à la rapidité et la dextérité du personnage. Elle livre le nombre d'actions qu'un personnage peut accomplir en un tour de combat et permet d'évaluer les compétences de base Initiative & Course." },
}, },
allonges: { allonges: {
courte: { courte: { malus: 0 }, moyenne: { malus: -1 }, longue: { malus: -2 }, treslongue: { malus: 0, esquive: 2 } }, courte: { courte: { label: "Courte (0)", malus: 0 }, moyenne: { label: "Moyenne (-1)", malus: -1 }, longue: { label: "Longue (-2)", malus: -2 }, treslongue: { label: "Très longue (0, 2 Esquives)", malus: 0, esquive: 2 } },
moyenne: { courte: { malus: 0 }, moyenne: { malus: 0 }, longue: { malus: -1 }, treslongue: { malus: 0, esquive: 2 } }, moyenne: { courte: { label: "Courte (0)", malus: 0 }, moyenne: { label: "Moyenne (0)", malus: 0 }, longue: { label: "Longue (-1)", malus: -1 }, treslongue: { label: "Très longue (0, 2 Esquives)", malus: 0, esquive: 2 } },
longue: { courte: { malus: -2 }, moyenne: { malus: -1 }, longue: { malus: 0 }, treslongue: { malus: -1, esquive: 1 } }, longue: { courte: { label: "Courte (-2)", malus: -2 }, moyenne: { label: "Moyenne (-1)", malus: -1 }, longue: { label: "Longue (0)", malus: 0 }, treslongue: { label: "Très longue (-1, 2 Esquives)", malus: -1, esquive: 1 } },
treslongue: { courte: { malus: 0, esquive: 2 }, moyenne: { malus: 0, esquive: 2 }, longue: { malus: 0, esquive: 1 }, treslongue: { malus: 0 } }, treslongue: { courte: { label: "Courte (0, 2 Esquives)", malus: 0, esquive: 2 }, moyenne: { label: "Moyenne (0, 2 Esquives)", malus: 0, esquive: 2 }, longue: { label: "Longue (0, 1 Esquive)", malus: 0, esquive: 1 }, treslongue: { label: "Très longue (0)", malus: 0 } },
}, },
providence: [ providence: [
{ labelM: "Brebis égarée", labelF: "Brebis égarée", value: 0, diceValue: "0" }, { labelM: "Brebis égarée", labelF: "Brebis égarée", value: 0, diceValue: "0" },
@@ -152,13 +168,13 @@ export const TEDEUM_CONFIG = {
}, },
difficulte: { difficulte: {
aucune: { label: "Aucune", key: "aucune", value: 0 }, aucune: { label: "Aucune", key: "aucune", value: 0 },
routine: { label: "Routine", key: "routine", value: 3 }, routine: { label: "Routine (3)", key: "routine", value: 3 },
facile: { label: "Facile", key: "facile", value: 5 }, facile: { label: "Facile (5)", key: "facile", value: 5 },
pardefaut: { label: "Par Défaut", key: "pardefaut", value: 7 }, pardefaut: { label: "Par Défaut (7)", key: "pardefaut", value: 7 },
malaise: { label: "Malaisé", key: "malaise", value: 9 }, malaise: { label: "Malaisé (9)", key: "malaise", value: 9 },
difficile: { label: "Difficile", key: "difficile", value: 11 }, difficile: { label: "Difficile (11)", key: "difficile", value: 11 },
perilleux: { label: "Perilleux", key: "perilleux", value: 13 }, perilleux: { label: "Perilleux (13)", key: "perilleux", value: 13 },
desespere: { label: "Désespéré", key: "desespere", value: 15 } desespere: { label: "Désespéré (15)", key: "desespere", value: 15 }
}, },
monnaie: { monnaie: {
denier: { label: "Deniers", id: "denier", value: 1 }, denier: { label: "Deniers", id: "denier", value: 1 },
@@ -195,13 +211,14 @@ export const TEDEUM_CONFIG = {
{ value: "1", label: "+1 niveau" }, { value: "1", label: "+1 niveau" },
{ value: "2", label: "+2 niveaux" } { value: "2", label: "+2 niveaux" }
], ],
blessuresOrder: ["indemne", "estafilade", "plaie", "plaiebeante", "plaieatroce", "tuenet", "tuenet", "tuenet", "tuenet", "tuenet"],
blessures: { blessures: {
indemne: { value: 0, label: "Indemne", key: "indemne", degatsMax: -1, count: 0, modifier: 0 }, indemne: { value: 0, label: "Indemne", key: "indemne", degatsMax: -1, count: 0, modifier: 0 },
estafilade: { value: 1, label: "Estafilade", key: "estafilade", degatsMin: 0, degatsMax: 2, count: 1, modifier: 0 }, estafilade: { value: 1, label: "Estafilade", key: "estafilade", degatsMin: 0, degatsMax: 2, count: 1, modifier: 0 },
plaie: { value: 2, label: "Plaie", key: "plaie", degatsMin: 3, degatsMax: 4, count: 1, modifier: -1 }, plaie: { value: 2, label: "Plaie", key: "plaie", degatsMin: 3, degatsMax: 4, count: 1, modifier: -1 },
plaiebeante: { value: 3, label: "Plaie béante", key: "plaiebeante", degatsMin: 5, degatsMax: 6, count: 1, modifier: -2 }, plaiebeante: { value: 3, label: "Plaie béante", key: "plaiebeante", degatsMin: 5, degatsMax: 6, count: 1, modifier: -2 },
plaieatroce: { value: 4, label: "Plaie atroce", key: "plaieatroce", degatsMin: 7, degatsMax: 8, count: 1, horsCombat: true, modifier: -12 }, plaieatroce: { value: 4, label: "Plaie atroce", key: "plaieatroce", degatsMin: 7, degatsMax: 8, count: 1, horsCombat: true, modifier: -12 },
tunenet: { value: 5, label: "Tué net", key: "tuenet", degatsMin: 9, degatsMax: 100, count: 1, horsCombat: true, mort: true, modifier: -12 } tuenet: { value: 5, label: "Tué net", key: "tuenet", degatsMin: 9, degatsMax: 100, count: 1, horsCombat: true, mort: true, modifier: -100 }
}, },
virulence: { virulence: {
aucune: { label: "Aucune", value: "aucune", modifier: 0 }, aucune: { label: "Aucune", value: "aucune", modifier: 0 },
+258 -33
View File
@@ -1,6 +1,8 @@
/* -------------------------------------------- */ /* -------------------------------------------- */
/* -------------------------------------------- */ /* -------------------------------------------- */
const ECRYME_WELCOME_MESSAGE_URL = "https://www.uberwald.me/gitea/public/fvtt-te-deum/raw/branch/main/welcome-message-tedeum.html"
export class TeDeumUtility { export class TeDeumUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -12,13 +14,19 @@ export class TeDeumUtility {
CONFIG.JournalEntry.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp" CONFIG.JournalEntry.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp"
CONFIG.Macro.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp" CONFIG.Macro.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp"
CONFIG.Adventure.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp" CONFIG.Adventure.compendiumBanner = "systems/fvtt-te-deum/images/ui/compendium_banner.webp"
}
Hooks.on('renderChatLog', (log, html, data) => TeDeumUtility.chatListeners(html)); static installHooks() {
Hooks.on('renderChatMessageHTML', (message, html) => {
TeDeumUtility.chatListeners(html);
TeDeumUtility.onRenderChatMessage(message, html);
});
Hooks.on("renderActorDirectory", (app, html, data) => { Hooks.on("renderActorDirectory", (app, html, data) => {
if (game.user.can('ACTOR_CREATE')) { if (game.user.can('ACTOR_CREATE')) {
const button = document.createElement('button'); const button = document.createElement('button');
button.style.width = '90%'; button.style.width = '60%';
button.classList.add('tedeum-create-character');
button.innerHTML = 'Créer un Personnage' button.innerHTML = 'Créer un Personnage'
button.addEventListener('click', () => { button.addEventListener('click', () => {
let cr = new game.system.tedeum.TeDeumCharacterCreator(); let cr = new game.system.tedeum.TeDeumCharacterCreator();
@@ -27,7 +35,47 @@ export class TeDeumUtility {
$(html).find('.header-actions').after(button) $(html).find('.header-actions').after(button)
} }
}) })
//Hooks.on("getChatLogEntryContext", (html, options) => TeDeumUtility.chatMenuManager(html, options));
Hooks.on("combatStart", async (combat, updateData, options) => {
this.resetCombatActions(combat)
});
Hooks.on("combatRound", (combat, updateData, updateOptions) => {
// List all actors related to combatant
if (game.user.isGM) {
this.resetCombatActions(combat)
}
})
Hooks.on("getCombatTrackerContextOptions", (html, options) => {
console.log("Get Combat Tracker Context", html, options)
this.pushCombatOptions(html, options);
});
}
/* -------------------------------------------- */
static pushCombatOptions(html, options) {
options.push({ name: "Actions +1", condition: true, icon: '<i class="fas fa-plus"></i>', callback: target => { game.combat.modifyAction($(target).data('combatant-id'), 1); } })
options.push({ name: "Actions -1", condition: true, icon: '<i class="fas fa-minus"></i>', callback: target => { game.combat.modifyAction($(target).data('combatant-id'), -1); } })
options.push({ name: "Actions MG +1", condition: true, icon: '<i class="fas fa-plus"></i>', callback: target => { game.combat.modifyAction($(target).data('combatant-id'), 1, true); } })
options.push({ name: "Actions MG -1", condition: true, icon: '<i class="fas fa-minus"></i>', callback: target => { game.combat.modifyAction($(target).data('combatant-id'), -1, true); } })
}
/* -------------------------------------------- */
static async resetCombatActions(combat) {
if (game.user.isGM) {
for (let c of combat.combatants) {
let actor = game.actors.get(c.actorId)
if (actor) {
let nbActions = actor.getNbActions()?.value || 0
let isMainGauche = (actor.getCompetenceScore("Main gauche") > 0)
let nbActionsMainGauche = isMainGauche ? nbActions : 0
await c.setFlag("world", "available-actions", { nbActions, nbActionsMainGauche })
await c.update({ name: `${c.token.name} (${nbActions} / ${nbActionsMainGauche})` })
}
}
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -99,6 +147,14 @@ export class TeDeumUtility {
} }
return value return value
}) })
// Handle v12 removal of this helper
Handlebars.registerHelper('select', function (selected, options) {
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
const rgx = new RegExp(' value=[\"\']' + escapedValue + '[\"\']');
const html = options.fn(this);
return html.replace(rgx, "$& selected");
});
// Load compendium data // Load compendium data
const competences = await TeDeumUtility.loadCompendium("fvtt-te-deum.competences") const competences = await TeDeumUtility.loadCompendium("fvtt-te-deum.competences")
@@ -126,14 +182,24 @@ export class TeDeumUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static welcomeMessage() { static welcomeMessage() {
if (game.user.isGM) { if (game.user.isGM) {
// Try to fetch the welcome message from the github repo "welcome-message-ecryme.html"
fetch(ECRYME_WELCOME_MESSAGE_URL)
.then(response => response.text())
.then(html => {
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user.id,
whisper: [game.user.id], whisper: [game.user.id],
content: `<div id="chat-welcome welcome-message-tedeum"><span class="rdd-roll-part"> content: html
<strong>Bienvenu dans Te Deum Pour Un Massacre !</strong> });
<div class="chat-welcome">Ce système vous est proposé par Open Sesame Games.<br> })
Vous trouverez de l'aide dans @UUID[Compendium.fvtt-te-deum.aides.JournalEntry.uNwJgi4kXBCiZmAH]{Aide pour Te Deum}<br> .catch(error => {
ainsi que sur le Discord de Foundry FR : https://discord.gg/pPSDNJk</div>` }); console.error("Error fetching welcome message:", error);
ChatMessage.create({
user: game.user.id,
whisper: [game.user.id],
content: "<b>Bienvenue dans Ecryme RPG !</b><br>Visitez le site officiel pour plus d'informations."
});
});
} }
} }
@@ -200,7 +266,7 @@ export class TeDeumUtility {
return actor return actor
} }
/* -------------------------------------------- */ /* -------------------------------------------- */ /* -------------------------------------------- */
static async manageOpposition(rollData) { static async manageOpposition(rollData) {
if (!this.currentOpposition) { if (!this.currentOpposition) {
// Store rollData as current GM opposition // Store rollData as current GM opposition
@@ -209,18 +275,36 @@ export class TeDeumUtility {
} else { } else {
// Perform the opposition // Perform the opposition
let isAttackWinner = true let isAttackWinner = true
let rWinner = this.currentOpposition let rWinner, rLooser
let rLooser = rollData if (this.currentOpposition.total <= rollData.total) {
if (rWinner.total < rLooser.total) { rWinner = foundry.utils.duplicate(rollData)
rWinner = rollData rLooser = foundry.utils.duplicate(this.currentOpposition)
rLooser = this.currentOpposition
isAttackWinner = false isAttackWinner = false
} else {
rWinner = foundry.utils.duplicate(this.currentOpposition)
rLooser = foundry.utils.duplicate(rollData)
isAttackWinner = true
} }
this.currentOpposition = undefined // Reset opposition this.currentOpposition = undefined // Reset opposition
let oppositionData = { let oppositionData = {
winner: rWinner, winner: rWinner,
looser: rLooser looser: rLooser
} }
// Update difficulty
rWinner.difficulty = rLooser.total
rLooser.difficulty = rWinner.total
await this.computeResults(rWinner)
await this.computeResults(rLooser)
// Auto XP management when opposed
if (rWinner.isReussiteCritique) {
let actor = this.getActorFromRollData(rWinner)
actor.modifyXP(rWinner.carac.key, 1)
}
if (rLooser.isEchecCritique) {
let actor = this.getActorFromRollData(rLooser)
actor.modifyXP(rLooser.carac.key, 1)
}
let msg = await this.createChatWithRollMode(rollData.alias, { let msg = await this.createChatWithRollMode(rollData.alias, {
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-opposition-result.hbs`, oppositionData) content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-opposition-result.hbs`, oppositionData)
}) })
@@ -228,20 +312,39 @@ export class TeDeumUtility {
// Si le gagnant est l'attaquant, appliquer les dégats sur la victime // Si le gagnant est l'attaquant, appliquer les dégats sur la victime
if (isAttackWinner && rWinner.isSuccess && rWinner.mode == "arme" && rWinner.arme?.system.typeArme == "melee" && rWinner.defenderTokenId) { if (isAttackWinner && rWinner.isSuccess && rWinner.mode == "arme" && rWinner.arme?.system.typeArme == "melee" && rWinner.defenderTokenId) {
this.appliquerDegats(rWinner) await this.appliquerDegats(rWinner)
} }
console.log("Rolldata result", rollData) console.log("Opposition result", rollData, isAttackWinner, oppositionData)
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */ /* -------------------------------------------- */
static getTokenActorFromId(tokenId) {
for (let scene of game.scenes) {
const tokenDoc = scene.tokens.get(tokenId)
if (tokenDoc) return tokenDoc.actor
}
return null
}
/* -------------------------------------------- */
static async appliquerDegats(rollData) { static async appliquerDegats(rollData) {
await this.processAttaqueMelee(rollData) await this.processAttaqueMelee(rollData)
let defenderToken = canvas.tokens.placeables.find(t => t.id == rollData.defenderTokenId) let defenderActor = this.getTokenActorFromId(rollData.defenderTokenId)
if (defenderToken) { if (defenderActor) {
let actor = defenderToken.actor if (game.user.isGM || defenderActor.isOwner) {
await actor.appliquerDegats(rollData) await defenderActor.appliquerDegats(rollData)
} else {
// Send a socket message — seul le premier MJ actif le traitera
game.socket.emit("system.fvtt-te-deum", { name: "msg_apply_damage", data: { rollData } });
}
// Attaque naturelle avec dégats inférieur à -2
if ((rollData?.arme?.system.specificites?.poing?.hasSpec || rollData?.arme?.system.specificites?.pied?.hasSpec) && rollData.degats < -2) {
let attacker = this.getActorFromRollData(rollData)
attacker.appliquerBlessure("estafilade", "maindroite", "Contusion suite à une attaque naturelle")
ui.notifications.info(`${attacker.name} subit 1 contusion en infligeant ${rollData.degats} dégâts à mains nues`)
}
} else { } else {
ui.notifications.error("Impossible de trouver la cible de l'attaque, aucun degats appliqué") ui.notifications.error("Impossible de trouver la cible de l'attaque, aucun degats appliqué")
} }
@@ -266,6 +369,25 @@ export class TeDeumUtility {
TeDeumUtility.appliquerDegats(rollData, messageId) TeDeumUtility.appliquerDegats(rollData, messageId)
} }
}) })
$(html).on("click", '.chat-command-gain-xp', async event => {
let messageId = TeDeumUtility.findChatMessageId(event.currentTarget)
let message = game.messages.get(messageId)
let rollData = message.getFlag("world", "te-deum-rolldata")
if (rollData) {
let actor = TeDeumUtility.getActorFromRollData(rollData)
actor.modifyXP(rollData.carac.key, 1)
event.currentTarget.style.display = 'none'; // feedback immédiat local
await message.setFlag("world", "te-deum-xp-used", true) // sync tous les clients
}
})
}
/* -------------------------------------------- */
static onRenderChatMessage(message, html) {
if (message.getFlag("world", "te-deum-xp-used")) {
const btn = html.querySelector('.chat-command-gain-xp');
if (btn) btn.style.display = 'none';
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -275,7 +397,17 @@ export class TeDeumUtility {
'systems/fvtt-te-deum/templates/actors/editor-notes-gm.hbs', 'systems/fvtt-te-deum/templates/actors/editor-notes-gm.hbs',
'systems/fvtt-te-deum/templates/items/partial-item-nav.hbs', 'systems/fvtt-te-deum/templates/items/partial-item-nav.hbs',
'systems/fvtt-te-deum/templates/items/partial-item-description.hbs', 'systems/fvtt-te-deum/templates/items/partial-item-description.hbs',
'systems/fvtt-te-deum/templates/dialogs/partial-creator-status.hbs' 'systems/fvtt-te-deum/templates/dialogs/partial-creator-status.hbs',
'systems/fvtt-te-deum/templates/items/item-arme-sheet.hbs',
'systems/fvtt-te-deum/templates/items/item-armure-sheet.hbs',
'systems/fvtt-te-deum/templates/items/item-blessure-sheet.hbs',
'systems/fvtt-te-deum/templates/items/item-competence-sheet.hbs',
'systems/fvtt-te-deum/templates/items/item-education-sheet.hbs',
'systems/fvtt-te-deum/templates/items/item-equipement-sheet.hbs',
'systems/fvtt-te-deum/templates/items/item-grace-sheet.hbs',
'systems/fvtt-te-deum/templates/items/item-maladie-sheet.hbs',
'systems/fvtt-te-deum/templates/items/item-origine-sheet.hbs',
'systems/fvtt-te-deum/templates/items/item-simple-sheet.hbs',
] ]
return foundry.applications.handlebars.loadTemplates(templatePaths); return foundry.applications.handlebars.loadTemplates(templatePaths);
} }
@@ -360,6 +492,28 @@ export class TeDeumUtility {
chatMsg.setFlag("world", "tedeum-rolldata", rollData) chatMsg.setFlag("world", "tedeum-rolldata", rollData)
} }
} }
if (msg.name == "msg_modify_combat_action") {
if (game.user.isGM) {
let { combatantId, ca } = msg.data
let combatant = game.combat.combatants.get(combatantId)
if (combatant) {
console.log("sock - Modify Combat Action : ", combatant.name, ca)
await TeDeumUtility.updateCombatantActions(combatant, ca)
}
}
}
if (msg.name == "msg_apply_damage") {
const firstGM = game.users.find(u => u.isGM && u.active)
if (game.user === firstGM) {
let rollData = msg.data.rollData
let defenderActor = TeDeumUtility.getTokenActorFromId(rollData.defenderTokenId)
if (defenderActor) {
await defenderActor.appliquerDegats(rollData)
} else {
ui.notifications.error("Impossible de trouver la cible de l'attaque, aucun degats appliqué")
}
}
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -445,9 +599,11 @@ export class TeDeumUtility {
} }
if (rollData.diceSum == 1) { if (rollData.diceSum == 1) {
let critiqueRoll = await new Roll(rollData.carac.negativeDice) let critiqueRoll = await new Roll(rollData.carac.negativeDice)
rollData.isSuccess = false
await critiqueRoll.evaluate() await critiqueRoll.evaluate()
await this.showDiceSoNice(critiqueRoll, game.settings.get("core", "rollMode")) await this.showDiceSoNice(critiqueRoll, game.settings.get("core", "rollMode"))
rollData.critiqueRoll = foundry.utils.duplicate(critiqueRoll) rollData.critiqueRoll = foundry.utils.duplicate(critiqueRoll)
rollData.critiqueTotal = critiqueRoll.total
if (critiqueRoll.total > rollData.competence.system.score) { if (critiqueRoll.total > rollData.competence.system.score) {
rollData.isEchecCritique = true rollData.isEchecCritique = true
} }
@@ -476,9 +632,18 @@ export class TeDeumUtility {
if (rollData.isMouvement) { if (rollData.isMouvement) {
localModifier -= 1 localModifier -= 1
} }
if (rollData.arme && rollData.allongeId) {
localModifier += rollData.allonges[rollData.allongeId].malus
rollData.allongeMalus = rollData.allonges[rollData.allongeId].malus
rollData.nbEsquives = rollData.allonges[rollData.allongeId]?.esquive || 0
}
if (rollData.attaqueCiblee && rollData.attaqueCiblee != "aucune") {
localModifier -= 1
rollData.loc = foundry.utils.duplicate(game.system.tedeum.config.LOCALISATION[rollData.attaqueCiblee])
}
let diceBase = this.modifyDice(rollData.carac.dice, localModifier + Number(rollData.bonusMalus) + rollData.santeModifier) let diceBase = this.modifyDice(rollData.carac.dice, localModifier + Number(rollData.bonusMalus) + rollData.santeModifier)
if (!diceBase) return; if (!diceBase) return;
diceFormula = diceBase + "x + " + rollData.competence.system.score diceFormula = diceBase + "x + " + rollData.compScore
} }
if (rollData.enableProvidence) { if (rollData.enableProvidence) {
diceFormula += " + " + rollData.providence.dice diceFormula += " + " + rollData.providence.dice
@@ -488,9 +653,12 @@ export class TeDeumUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getLocalisation(rollData) { static async getLocalisation(rollData) {
let locRoll = await new Roll("1d20").roll() let locRoll
if (rollData.loc) {
locRoll = await new Roll(String(rollData.loc.score.min)).roll()
} else {
locRoll = await new Roll("1d20").roll()
await this.showDiceSoNice(locRoll, game.settings.get("core", "rollMode")) await this.showDiceSoNice(locRoll, game.settings.get("core", "rollMode"))
rollData.locRoll = foundry.utils.duplicate(locRoll)
for (let key in game.system.tedeum.config.LOCALISATION) { for (let key in game.system.tedeum.config.LOCALISATION) {
let loc = game.system.tedeum.config.LOCALISATION[key] let loc = game.system.tedeum.config.LOCALISATION[key]
if (locRoll.total >= loc.score.min && locRoll.total <= loc.score.max) { if (locRoll.total >= loc.score.min && locRoll.total <= loc.score.max) {
@@ -499,13 +667,16 @@ export class TeDeumUtility {
} }
} }
} }
rollData.locRoll = foundry.utils.duplicate(locRoll)
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async processAttaqueMelee(rollData) { static async processAttaqueMelee(rollData) {
await this.getLocalisation(rollData) await this.getLocalisation(rollData)
let actor = game.actors.get(rollData.actorId) let actor = game.actors.get(rollData.actorId)
let bDegats = actor.getBonusDegats() let bDegats = actor.getAttaqueBonusDegats(rollData)
let degatsRoll = await new Roll(rollData.arme.system.degats + "+" + bDegats.value).roll() rollData.degatsFormula = rollData.arme.system.degats + "+" + bDegats
let degatsRoll = await new Roll(rollData.degatsFormula).roll()
await this.showDiceSoNice(degatsRoll, game.settings.get("core", "rollMode")) await this.showDiceSoNice(degatsRoll, game.settings.get("core", "rollMode"))
rollData.degatsRoll = foundry.utils.duplicate(degatsRoll) rollData.degatsRoll = foundry.utils.duplicate(degatsRoll)
rollData.degats = degatsRoll.total rollData.degats = degatsRoll.total
@@ -521,12 +692,51 @@ export class TeDeumUtility {
await this.getLocalisation(rollData) await this.getLocalisation(rollData)
// Now the degats // Now the degats
let degatsRoll = await new Roll(rollData.arme.system.degats).roll() let degatsRoll = await new Roll(rollData.arme.system.degats).roll()
await this.showDiceSoNice(rollData.locRoll, game.settings.get("core", "rollMode")) await this.showDiceSoNice(degatsRoll, game.settings.get("core", "rollMode"))
rollData.degatsRoll = foundry.utils.duplicate(degatsRoll) rollData.degatsRoll = foundry.utils.duplicate(degatsRoll)
rollData.degats = degatsRoll.total rollData.degats = degatsRoll.total
} }
} }
/* -------------------------------------------- */
static async updateCombatantActions(combatant, ca) {
await combatant.setFlag("world", "available-actions", ca)
await combatant.update({ name: `${combatant.token.name} (${ca.nbActions} / ${ca.nbActionsMainGauche})` })
}
/* -------------------------------------------- */
static async manageCombatActions(actor, rollData) {
let combat = game.combats.active
if (!combat) return;
let combatant = combat.getCombatantByActor(actor)
if (!combatant) return;
let ca = combatant.getFlag("world", "available-actions")
if (!ca) return;
if (rollData.mode == "arme" && rollData.isMainGauche) {
if (ca.nbActionsMainGauche > 0) {
ca.nbActionsMainGauche -= 1
ca.nbActions = Math.max(ca.nbActions - 1, 0)
} else {
ui.notifications.error(`${actor.name} n'a plus d'actions disponibles à la main gauche pour ce round`)
}
}
if (ca.nbActions > 0) {
ca.nbActions -= 1
} else {
ui.notifications.error(`${actor.name} n'a plus d'actions disponibles pour ce round`)
}
console.log("Manage combat actions 1", actor.name, combatant)
if (game.user.isGM) {
await this.updateCombatantActions(combatant, ca)
} else {
// Send a socket message
game.socket.emit("system.fvtt-te-deum", { name: "msg_modify_combat_action", data: { combatantId: combatant.id, ca } });
}
rollData.hasActions = true
rollData.remainingActions = ca.nbActions
rollData.remainingActionsMainGauche = ca.nbActionsMainGauche
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async rollTeDeum(rollData) { static async rollTeDeum(rollData) {
@@ -536,6 +746,18 @@ export class TeDeumUtility {
rollData.difficulty = "pardefaut" rollData.difficulty = "pardefaut"
} }
rollData.difficulty = game.system.tedeum.config.difficulte[rollData.difficulty].value rollData.difficulty = game.system.tedeum.config.difficulte[rollData.difficulty].value
// Compute the real competence score
if (rollData.competence) {
if (rollData.isMainGauche) {
rollData.competence = actor.getMeilleureCompetenceMainGauche(rollData.competence)
}
if (rollData.competence.system.isBase) {
rollData.compScore = actor.system.caracteristiques[rollData.competence.system.caracteristique].value
} else {
rollData.compScore = rollData.competence.system.score
}
}
let diceFormula = this.computeRollFormula(rollData, actor) let diceFormula = this.computeRollFormula(rollData, actor)
if (!diceFormula) return; if (!diceFormula) return;
console.log("RollData", rollData, diceFormula) console.log("RollData", rollData, diceFormula)
@@ -552,6 +774,8 @@ export class TeDeumUtility {
await this.processAttaqueDistance(rollData) await this.processAttaqueDistance(rollData)
await this.manageCombatActions(actor, rollData)
let msg = await this.createChatWithRollMode(rollData.alias, { let msg = await this.createChatWithRollMode(rollData.alias, {
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-generic-result.hbs`, rollData) content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-te-deum/templates/chat/chat-generic-result.hbs`, rollData)
}) })
@@ -562,10 +786,6 @@ export class TeDeumUtility {
if (rollData.enableProvidence) { if (rollData.enableProvidence) {
actor.modifyProvidence(-1) actor.modifyProvidence(-1)
} }
// Manage XP
if (rollData.isReussiteCritique || rollData.isEchecCritique) {
actor.modifyXP(rollData.carac.key, 1)
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -683,7 +903,7 @@ export class TeDeumUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async confirmDelete(actorSheet, li) { static async confirmDelete(actorSheet, li) {
let itemId = li.data("item-id"); let itemId = li.dataset ? li.dataset.itemId : li.data("item-id");
let msgTxt = "<p>Etes vous certain de supprimer cet item ?"; let msgTxt = "<p>Etes vous certain de supprimer cet item ?";
let buttons = { let buttons = {
delete: { delete: {
@@ -691,7 +911,12 @@ export class TeDeumUtility {
label: "Oui, aucun souci", label: "Oui, aucun souci",
callback: () => { callback: () => {
actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]); actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]);
if (li.slideUp) {
li.slideUp(200, () => actorSheet.render(false)); li.slideUp(200, () => actorSheet.render(false));
} else {
li.style.display = "none";
actorSheet.render(false);
}
} }
}, },
cancel: { cancel: {
+1 -1
View File
@@ -37,7 +37,7 @@ export class TeDeumArmeSchema extends foundry.abstract.TypeDataModel {
schema.competenceRecharge = new fields.StringField({ required: false, choices: ["aucune", "archerie", "arquebusade"], initial: "aucune", blank: true }); schema.competenceRecharge = new fields.StringField({ required: false, choices: ["aucune", "archerie", "arquebusade"], initial: "aucune", blank: true });
schema.valeurEchecCritique = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 }); schema.valeurEchecCritique = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 });
schema.initiativeBonus = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }); schema.initiativeBonus = new fields.NumberField({ ...requiredInteger, initial: 0 });
schema.degats = new fields.StringField({ required: false, blank: true, initial: "0" }); schema.degats = new fields.StringField({ required: false, blank: true, initial: "0" });
schema.degatscrosse = new fields.StringField({ required: false, blank: true, initial: "0" }); schema.degatscrosse = new fields.StringField({ required: false, blank: true, initial: "0" });
+1
View File
@@ -5,6 +5,7 @@ export class TeDeumBlessureSchema extends foundry.abstract.TypeDataModel {
const schema = {}; const schema = {};
schema.typeBlessure = new fields.StringField({ required: true, choices: ["indemne", "estafilade", "plaie", "plaiebeante", "plaieatroce", "tuenet"], initial: "estafilade" }); schema.typeBlessure = new fields.StringField({ required: true, choices: ["indemne", "estafilade", "plaie", "plaiebeante", "plaieatroce", "tuenet"], initial: "estafilade" });
schema.value = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
schema.localisation = new fields.StringField({ required: true, choices: ["piedgauche", "pieddroit", "jambegauche", "jambedroite", "maingauche", "maindroite", "brasgauche", "brasdroit", "tete", "corps"], initial: "corps" }); schema.localisation = new fields.StringField({ required: true, choices: ["piedgauche", "pieddroit", "jambegauche", "jambedroite", "maingauche", "maindroite", "brasgauche", "brasdroit", "tete", "corps"], initial: "corps" });
schema.description = new fields.HTMLField({ required: true, blank: true }); schema.description = new fields.HTMLField({ required: true, blank: true });
+1 -1
View File
@@ -51,7 +51,7 @@ export class TeDeumEducationSchema extends foundry.abstract.TypeDataModel {
reponse: new fields.StringField({ required: true, blank: true, initial: "" }), reponse: new fields.StringField({ required: true, blank: true, initial: "" }),
compName: new fields.StringField({ required: true, blank: true, initial: "" }), compName: new fields.StringField({ required: true, blank: true, initial: "" }),
toSelect: new fields.BooleanField({ initial: false }), toSelect: new fields.BooleanField({ initial: false }),
compList: new fields.SchemaField(Array.fromRange(10, 1).reduce((comps, i) => { compList: new fields.SchemaField(Array.fromRange(16, 1).reduce((comps, i) => {
comps[`comp${i}`] = new fields.SchemaField({ comps[`comp${i}`] = new fields.SchemaField({
compName: new fields.StringField({ required: true, blank: true, initial: "" }), compName: new fields.StringField({ required: true, blank: true, initial: "" }),
}); });
+2 -1
View File
@@ -1,7 +1,8 @@
export class TeDeumMaladieSchema extends foundry.abstract.TypeDataModel { export class TeDeumSimpleSchema extends foundry.abstract.TypeDataModel {
static defineSchema() { static defineSchema() {
const fields = foundry.data.fields; const fields = foundry.data.fields;
const requiredInteger = { required: true, nullable: false, integer: true }; const requiredInteger = { required: true, nullable: false, integer: true };
const requiredDouble = { required: true, nullable: false, integer: false };
const schema = {}; const schema = {};
schema.difficulteEndurance = new fields.StringField({required:true, initial:"aucun"}); schema.difficulteEndurance = new fields.StringField({required:true, initial:"aucun"});
+68 -52
View File
@@ -1,87 +1,103 @@
import { TeDeumUtility } from "../common/tedeum-utility.js"; import { TeDeumUtility } from "../common/tedeum-utility.js";
export class TeDeumRollDialog extends Dialog { const { HandlebarsApplicationMixin } = foundry.applications.api
/* -------------------------------------------- */
export class TeDeumRollDialog extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) {
static DEFAULT_OPTIONS = {
classes: ["fvtt-te-deum", "te-deum-roll-dialog"],
window: { title: "Lancer !", resizable: false },
position: { width: 540 },
actions: {
roll: TeDeumRollDialog.#onRoll,
cancel: TeDeumRollDialog.#onCancel,
}
}
static PARTS = {
content: { template: "systems/fvtt-te-deum/templates/dialogs/roll-dialog-generic.hbs" }
}
/* -------------------------------------------- */
constructor(actor, rollData, options = {}) {
super(options)
this.actor = actor
this.rollData = rollData
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async create(actor, rollData) { static async create(actor, rollData) {
const dialog = new TeDeumRollDialog(actor, rollData)
let options = { classes: ["tedeum-roll-dialog"], width: 540, height: 'fit-content', 'z-index': 99999 } dialog.render(true)
let html = await renderTemplate('systems/fvtt-te-deum/templates/dialogs/roll-dialog-generic.hbs', rollData); return dialog
return new TeDeumRollDialog(actor, rollData, html, options);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
constructor(actor, rollData, html, options, close = undefined) { async _prepareContext() {
let conf = { return { ...this.rollData }
title: "Lancer !",
content: html,
buttons: {
roll: {
icon: '<i class="fas fa-check"></i>',
label: "Lancer",
callback: () => { this.roll() }
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Annuler",
callback: () => { this.close() }
}
},
close: close
}
super(conf, options);
this.actor = actor;
this.rollData = rollData;
}
/* -------------------------------------------- */
roll() {
TeDeumUtility.rollTeDeum(this.rollData)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async refreshDialog() { async refreshDialog() {
const content = await renderTemplate("systems/fvtt-te-deum/templates/dialogs/roll-dialog-generic.hbs", this.rollData) this.render()
this.data.content = content
this.render(true)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
activateListeners(html) { static #onRoll(event, target) {
super.activateListeners(html); TeDeumUtility.rollTeDeum(this.rollData)
this.close()
let dialog = this;
function onLoad() {
} }
$(function () { onLoad(); });
html.find('#bonusMalusPerso').change((event) => { /* -------------------------------------------- */
static #onCancel(event, target) {
this.close()
}
/* -------------------------------------------- */
_onRender(context, options) {
super._onRender(context, options)
const html = this.element
html.querySelector('#bonusMalusPerso')?.addEventListener('change', (event) => {
this.rollData.bonusMalusPerso = Number(event.currentTarget.value) this.rollData.bonusMalusPerso = Number(event.currentTarget.value)
}) })
html.find('#roll-difficulty').change((event) => { html.querySelector('#roll-allonge')?.addEventListener('change', (event) => {
this.rollData.allongeId = event.currentTarget.value
})
html.querySelector('#roll-main-gauche')?.addEventListener('change', (event) => {
this.rollData.isMainGauche = event.currentTarget.checked
})
html.querySelector('#roll-difficulty')?.addEventListener('change', (event) => {
this.rollData.difficulty = String(event.currentTarget.value) || "pardefaut" this.rollData.difficulty = String(event.currentTarget.value) || "pardefaut"
}) })
html.find('#roll-bonus-malus').change((event) => { html.querySelector('#roll-attaque-ciblee')?.addEventListener('change', (event) => {
this.rollData.attaqueCiblee = event.currentTarget.value || "0"
})
html.querySelector('#roll-bonus-malus')?.addEventListener('change', (event) => {
this.rollData.bonusMalus = event.currentTarget.value || "0" this.rollData.bonusMalus = event.currentTarget.value || "0"
}) })
html.find('#roll-enable-providence').change((event) => { html.querySelector('#roll-enable-providence')?.addEventListener('change', (event) => {
this.rollData.enableProvidence = event.currentTarget.checked this.rollData.enableProvidence = event.currentTarget.checked
}) })
html.find('#roll-portee-tir').change((event) => { html.querySelector('#roll-portee-tir')?.addEventListener('change', (event) => {
this.rollData.porteeTir = event.currentTarget.value this.rollData.porteeTir = event.currentTarget.value
this.rollData.difficulty = game.system.tedeum.config.ARME_PORTEES[this.rollData.porteeTir].difficulty this.rollData.difficulty = game.system.tedeum.config.ARME_PORTEES[this.rollData.porteeTir].difficulty
this.rollData.porteeLabel = game.system.tedeum.config.ARME_PORTEES[this.rollData.porteeTir].label this.rollData.porteeLabel = game.system.tedeum.config.ARME_PORTEES[this.rollData.porteeTir].label
this.refreshDialog()
}) })
html.find('#roll-tir-viser').change((event) => { html.querySelector('#roll-tir-viser')?.addEventListener('change', (event) => {
this.rollData.isViser = event.currentTarget.checked this.rollData.isViser = event.currentTarget.checked
}) })
html.find('#roll-tir-mouvement').change((event) => { html.querySelector('#roll-tir-mouvement')?.addEventListener('change', (event) => {
this.rollData.isMouvement = event.currentTarget.checked this.rollData.isMouvement = event.currentTarget.checked
}) })
html.querySelector('#roll-charge-a-pied')?.addEventListener('change', (event) => {
this.rollData.isChargeAPied = event.currentTarget.checked
})
html.querySelector('#roll-charge-a-cheval')?.addEventListener('change', (event) => {
this.rollData.isChargeACheval = event.currentTarget.checked
})
} }
} }
+118 -137
View File
@@ -1,173 +1,154 @@
import { TeDeumUtility } from "../common/tedeum-utility.js"; import { TeDeumUtility } from "../common/tedeum-utility.js";
const { HandlebarsApplicationMixin } = foundry.applications.api
/** /**
* Extend the basic ItemSheet with some very simple modifications * Feuille d'item Te Deum - AppV2
* @extends {ItemSheet}
*/ */
export class TeDeumItemSheet extends foundry.appv1.sheets.ItemSheet { export class TeDeumItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
/** @override */ /** @override */
static get defaultOptions() { static DEFAULT_OPTIONS = {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["fvtt-te-deum", "sheet", "item"], classes: ["fvtt-te-deum", "sheet", "item"],
template: "systems/fvtt-te-deum/templates/item-sheet.hbs", position: {
dragDrop: [{ dragSelector: null, dropSelector: null }],
width: 620, width: 620,
height: 580, height: 580,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }] },
}); form: {
submitOnChange: true,
closeOnSubmit: false,
},
window: {
resizable: true,
},
actions: {
editImage: TeDeumItemSheet.#onEditImage,
postItem: TeDeumItemSheet.#onPostItem,
deleteSubitem: TeDeumItemSheet.#onDeleteSubitem,
viewSubitem: TeDeumItemSheet.#onViewSubitem,
},
} }
/* -------------------------------------------- */ // Static PARTS pointing to the dynamic wrapper template
_getHeaderButtons() { static PARTS = {
let buttons = super._getHeaderButtons(); sheet: { template: "systems/fvtt-te-deum/templates/items/item-sheet.hbs" },
// Add "Post to chat" button
// We previously restricted this to GM and editable items only. If you ever find this comment because it broke something: eh, sorry!
buttons.unshift(
{
class: "post",
icon: "fas fa-comment",
onclick: ev => { }
})
return buttons
} }
/* -------------------------------------------- */ tabGroups = { primary: "description" }
async getData() {
let formData = { /* -------------------------------------------- */
/** @override */
async _prepareContext() {
const item = this.document
const TextEditor = foundry.applications.ux.TextEditor.implementation
const enrich = async (val) => val !== undefined ? await TextEditor.enrichHTML(val ?? "", { async: true }) : ""
const context = {
title: this.title, title: this.title,
id: this.id, id: item.id,
type: this.object.type, type: item.type,
img: this.object.img, img: item.img,
name: this.object.name, name: item.name,
editable: this.isEditable, editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked", cssClass: this.isEditable ? "editable" : "locked",
system: foundry.utils.duplicate(this.object.system), system: foundry.utils.duplicate(item.system),
systemFields: item.system.schema.fields,
config: foundry.utils.duplicate(game.system.tedeum.config), config: foundry.utils.duplicate(game.system.tedeum.config),
competences: TeDeumUtility.getCompetencesForDropDown(), competences: TeDeumUtility.getCompetencesForDropDown(),
limited: this.object.limited, limited: item.limited,
options: this.options, owner: item.isOwner,
owner: this.document.isOwner, enrichedDescription: await enrich(item.system.description),
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.description, { async: true }), enrichedTransmission: await enrich(item.system.transmission),
notes: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.notes, { async: true }), enrichedSymptomes: await enrich(item.system.symptomes),
isGM: game.user.isGM enrichedComplications: await enrich(item.system.complications),
enrichedVertus: await enrich(item.system.vertus),
enrichedToxicite: await enrich(item.system.toxicite),
isGM: game.user.isGM,
itemPartialName: `systems/fvtt-te-deum/templates/items/item-${item.type}-sheet.hbs`,
} }
if (item.type === "education") {
if (this.object.type == "education") { TeDeumUtility.prepareEducationContent(context)
TeDeumUtility.prepareEducationContent(formData);
} }
return context
this.options.editable = !(this.object.origin == "embeddedItem");
console.log("ITEM DATA", formData, this);
return formData;
}
/* -------------------------------------------- */
_getHeaderButtons() {
let buttons = super._getHeaderButtons();
buttons.unshift({
class: "post",
icon: "fas fa-comment",
onclick: ev => this.postItem()
});
return buttons
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
postItem() { /** @override */
let chatData = duplicate(this.item) _onRender(context, options) {
super._onRender(context, options)
// Tab navigation
const nav = this.element.querySelector('nav.tabs[data-group]')
if (nav) {
const group = nav.dataset.group
const activeTab = this.tabGroups[group] || "description"
nav.querySelectorAll('[data-tab]').forEach(link => {
const tab = link.dataset.tab
link.classList.toggle('active', tab === activeTab)
link.addEventListener('click', event => {
event.preventDefault()
this.tabGroups[group] = tab
this.render()
})
})
this.element.querySelectorAll(`[data-group="${group}"][data-tab]`).forEach(content => {
content.classList.toggle('active', content.dataset.tab === activeTab)
})
}
// Ignore Enter key in inputs
this.element.addEventListener('keydown', e => {
if (e.keyCode === 13 && e.target.tagName !== 'TEXTAREA') e.preventDefault()
})
}
// #region Static action handlers
static async #onEditImage(event, target) {
const fp = new FilePicker({
type: "image",
current: this.document.img,
callback: path => this.document.update({ img: path }),
})
fp.browse()
}
static async #onPostItem(event, target) {
const chatData = foundry.utils.duplicate(this.item)
if (this.actor) { if (this.actor) {
chatData.actor = { id: this.actor.id }; chatData.actor = { id: this.actor.id }
} }
// Don't post any image for the item (which would leave a large gap) if the default image is used if (chatData.img?.includes("/blank.png")) {
if (chatData.img.includes("/blank.png")) { chatData.img = null
chatData.img = null;
} }
// JSON object for easy creation chatData.jsondata = JSON.stringify({ compendium: "postedItem", payload: chatData })
chatData.jsondata = JSON.stringify( const html = await foundry.applications.handlebars.renderTemplate(
{ 'systems/fvtt-te-deum/templates/post-item.html', chatData
compendium: "postedItem", )
payload: chatData, ChatMessage.create(TeDeumUtility.chatDataSetup(html))
});
renderTemplate('systems/fvtt-te-deum/templates/post-item.html', chatData).then(html => {
let chatOptions = TeDeumUtility.chatDataSetup(html);
ChatMessage.create(chatOptions)
});
} }
/* -------------------------------------------- */ static async #onDeleteSubitem(event, target) {
async viewSubitem(ev) { const field = target.dataset.type
let levelIndex = Number($(ev.currentTarget).parents(".item").data("level-index")) const idx = parseInt(target.dataset.index)
let choiceIndex = Number($(ev.currentTarget).parents(".item").data("choice-index")) const oldArray = this.document.system[field]
let featureId = $(ev.currentTarget).parents(".item").data("feature-id") if (Array.isArray(oldArray) && oldArray[idx]?.name !== 'None') {
const newArray = oldArray.filter((_, i) => i !== idx)
let itemData = this.object.system.levels[levelIndex].choices[choiceIndex].features[featureId] this.document.update({ [`system.${field}`]: newArray })
if (itemData.name != 'None') {
let item = await Item.create(itemData, { temporary: true });
item.system.origin = "embeddedItem";
new TeDeumItemSheet(item).render(true);
} }
} }
/* -------------------------------------------- */ static async #onViewSubitem(event, target) {
async deleteSubitem(ev) { const li = target.closest(".item")
let field = $(ev.currentTarget).data('type'); const levelIndex = parseInt(li?.dataset.levelIndex)
let idx = Number($(ev.currentTarget).data('index')); const choiceIndex = parseInt(li?.dataset.choiceIndex)
let oldArray = this.object.system[field]; const featureId = li?.dataset.featureId
let itemData = this.object.system[field][idx]; const itemData = this.document.system.levels?.[levelIndex]?.choices?.[choiceIndex]?.features?.[featureId]
if (itemData.name != 'None') { if (itemData?.name !== 'None') {
let newArray = []; const item = await Item.create(itemData, { temporary: true })
for (let i = 0; i < oldArray.length; i++) { item.system.origin = "embeddedItem"
if (i != idx) { new TeDeumItemSheet(item).render(true)
newArray.push(oldArray[i]);
}
}
this.object.update({ [`system.${field}`]: newArray });
} }
} }
/* -------------------------------------------- */ // #endregion
/** @override */
activateListeners(html) {
super.activateListeners(html);
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
// Update Inventory Item
html.find('.item-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item");
const item = this.object.options.actor.getOwnedItem(li.data("item-id"));
item.sheet.render(true);
});
html.find('.delete-subitem').click(ev => {
this.deleteSubitem(ev);
});
// Update Inventory Item
html.find('.item-delete').click(ev => {
const li = $(ev.currentTarget).parents(".item");
let itemId = li.data("item-id");
let itemType = li.data("item-type");
});
}
/* -------------------------------------------- */
get template() {
let type = this.item.type;
return `systems/fvtt-te-deum/templates/items/item-${type}-sheet.hbs`
}
/* -------------------------------------------- */
/** @override */
_updateObject(event, formData) {
return this.object.update(formData)
}
} }
+5
View File
@@ -21,6 +21,7 @@ import { TeDeumEducationSchema } from "./data/tedeum-schema-education.js";
import { TeDeumGraceSchema } from "./data/tedeum-schema-grace.js"; import { TeDeumGraceSchema } from "./data/tedeum-schema-grace.js";
import { TeDeumBlessureSchema } from "./data/tedeum-schema-blessure.js"; import { TeDeumBlessureSchema } from "./data/tedeum-schema-blessure.js";
import { TeDeumMaladieSchema } from "./data/tedeum-schema-maladie.js"; import { TeDeumMaladieSchema } from "./data/tedeum-schema-maladie.js";
import { TeDeumSimpleSchema } from "./data/tedeum-schema-simple.js";
import { TeDeumItem } from "./items/tedeum-item.js"; import { TeDeumItem } from "./items/tedeum-item.js";
import { TeDeumItemSheet } from "./items/tedeum-item-sheet.js"; import { TeDeumItemSheet } from "./items/tedeum-item-sheet.js";
@@ -78,6 +79,7 @@ Hooks.once("init", async function () {
grace: TeDeumGraceSchema, grace: TeDeumGraceSchema,
blessure: TeDeumBlessureSchema, blessure: TeDeumBlessureSchema,
maladie: TeDeumMaladieSchema, maladie: TeDeumMaladieSchema,
simple: TeDeumSimpleSchema,
}; };
console.log("TeDeum RPG | Ready"); console.log("TeDeum RPG | Ready");
@@ -90,6 +92,8 @@ Hooks.once("init", async function () {
foundry.documents.collections.Items.registerSheet("fvtt-te-deum", TeDeumItemSheet, { makeDefault: true }); foundry.documents.collections.Items.registerSheet("fvtt-te-deum", TeDeumItemSheet, { makeDefault: true });
TeDeumUtility.init() TeDeumUtility.init()
TeDeumUtility.installHooks()
}); });
@@ -98,6 +102,7 @@ Hooks.once("init", async function () {
/* -------------------------------------------- */ /* -------------------------------------------- */
Hooks.once("ready", function () { Hooks.once("ready", function () {
// User warning // User warning
if (!game.user.isGM && game.user.character == undefined) { if (!game.user.isGM && game.user.character == undefined) {
ui.notifications.info("Attention ! Aucun personnage relié au joueur !"); ui.notifications.info("Attention ! Aucun personnage relié au joueur !");
+21
View File
@@ -0,0 +1,21 @@
{
"name": "fvtt-te-deum",
"version": "1.0.0",
"description": "Système Te Deum pour FoundryVTT",
"private": true,
"scripts": {
"build:css": "gulp css",
"watch:css": "gulp watch"
},
"devDependencies": {
"gulp": "^4.0.2",
"gulp-less": "^5.0.0",
"less": "^4.2.0",
"autoprefixer": "^10.4.20",
"gulp-postcss": "^9.0.1",
"postcss": "^8.4.49"
},
"keywords": ["foundry-vtt", "te-deum"],
"author": "",
"license": "ISC"
}
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000099 MANIFEST-000265
+11 -14
View File
@@ -1,14 +1,11 @@
2025/05/09-10:15:41.735148 7fbe907f86c0 Recovering log #97 2026/06/14-22:10:30.024223 7f29d57ec6c0 Delete type=3 #1
2025/05/09-10:15:41.791781 7fbe907f86c0 Delete type=3 #95 2026/06/14-22:15:04.330144 7f29d4feb6c0 Level-0 table #268: started
2025/05/09-10:15:41.791840 7fbe907f86c0 Delete type=0 #97 2026/06/14-22:15:04.330179 7f29d4feb6c0 Level-0 table #268: 0 bytes OK
2025/05/09-10:26:09.013435 7fbe8fbff6c0 Level-0 table #102: started 2026/06/14-22:15:04.336647 7f29d4feb6c0 Delete type=0 #266
2025/05/09-10:26:09.031920 7fbe8fbff6c0 Level-0 table #102: 3728 bytes OK 2026/06/14-22:15:04.355855 7f29d4feb6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 25 : 1
2025/05/09-10:26:09.069119 7fbe8fbff6c0 Delete type=0 #100 2026/06/14-22:15:04.355863 7f29d4feb6c0 Compacting 1@0 + 0@1 files
2025/05/09-10:26:09.069442 7fbe8fbff6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 25 : 1 2026/06/14-22:15:04.359383 7f29d4feb6c0 Generated table #269@0: 5 keys, 3728 bytes
2025/05/09-10:26:09.069450 7fbe8fbff6c0 Compacting 1@0 + 1@1 files 2026/06/14-22:15:04.359390 7f29d4feb6c0 Compacted 1@0 + 0@1 files => 3728 bytes
2025/05/09-10:26:09.093063 7fbe8fbff6c0 Generated table #103@0: 5 keys, 3728 bytes 2026/06/14-22:15:04.365637 7f29d4feb6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/05/09-10:26:09.093094 7fbe8fbff6c0 Compacted 1@0 + 1@1 files => 3728 bytes 2026/06/14-22:15:04.365709 7f29d4feb6c0 Delete type=2 #236
2025/05/09-10:26:09.137637 7fbe8fbff6c0 compacted to: files[ 0 1 0 0 0 0 0 ] 2026/06/14-22:15:04.366103 7f29d4feb6c0 Manual compaction at level-0 from '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 25 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)
2025/05/09-10:26:09.137778 7fbe8fbff6c0 Delete type=2 #72
2025/05/09-10:26:09.137982 7fbe8fbff6c0 Delete type=2 #102
2025/05/09-10:26:09.254090 7fbe8fbff6c0 Manual compaction at level-0 from '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 25 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)
+4 -7
View File
@@ -1,7 +1,4 @@
2025/04/20-09:24:48.041836 7fa413fff6c0 Recovering log #93 2026/06/14-22:10:29.945743 7f29d57ec6c0 Log #263: 0 ops saved to Table #264 OK
2025/04/20-09:24:48.069770 7fa413fff6c0 Delete type=3 #91 2026/06/14-22:10:29.945859 7f29d57ec6c0 Archiving /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/aides/000263.log: OK
2025/04/20-09:24:48.069934 7fa413fff6c0 Delete type=0 #93 2026/06/14-22:10:29.946391 7f29d57ec6c0 Table #236: 5 entries OK
2025/04/20-09:25:06.962777 7fa4127fc6c0 Level-0 table #98: started 2026/06/14-22:10:29.957432 7f29d57ec6c0 **** Repaired leveldb /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/aides; recovered 1 files; 3728 bytes. Some data may have been lost. ****
2025/04/20-09:25:06.962842 7fa4127fc6c0 Level-0 table #98: 0 bytes OK
2025/04/20-09:25:06.970328 7fa4127fc6c0 Delete type=0 #96
2025/04/20-09:25:06.988174 7fa4127fc6c0 Manual compaction at level-0 from '!journal!uNwJgi4kXBCiZmAH' @ 72057594037927935 : 1 .. '!journal.pages!uNwJgi4kXBCiZmAH.onhNU0mXhOpdNZJF' @ 0 : 0; will stop at (end)
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000202 MANIFEST-000343
+12 -14
View File
@@ -1,14 +1,12 @@
2025/05/09-10:15:41.297396 7fbe90ff96c0 Recovering log #200 2026/06/14-22:10:29.401624 7f29d67ee6c0 Delete type=3 #1
2025/05/09-10:15:41.362108 7fbe90ff96c0 Delete type=3 #198 2026/06/14-22:15:04.191842 7f29d4feb6c0 Level-0 table #346: started
2025/05/09-10:15:41.362318 7fbe90ff96c0 Delete type=0 #200 2026/06/14-22:15:04.196321 7f29d4feb6c0 Level-0 table #346: 10049 bytes OK
2025/05/09-10:26:08.357066 7fbe8fbff6c0 Level-0 table #205: started 2026/06/14-22:15:04.202907 7f29d4feb6c0 Delete type=0 #344
2025/05/09-10:26:08.362656 7fbe8fbff6c0 Level-0 table #205: 30743 bytes OK 2026/06/14-22:15:04.231108 7f29d4feb6c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at '!items!mClyfwAAlxIE8p8I' @ 79 : 1
2025/05/09-10:26:08.375920 7fbe8fbff6c0 Delete type=0 #203 2026/06/14-22:15:04.231117 7f29d4feb6c0 Compacting 2@0 + 0@1 files
2025/05/09-10:26:08.439160 7fbe8fbff6c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at '!items!wxIHkrq98eQ3cOvp' @ 73 : 1 2026/06/14-22:15:04.234993 7f29d4feb6c0 Generated table #347@0: 38 keys, 31577 bytes
2025/05/09-10:26:08.439169 7fbe8fbff6c0 Compacting 1@0 + 1@1 files 2026/06/14-22:15:04.235022 7f29d4feb6c0 Compacted 2@0 + 0@1 files => 31577 bytes
2025/05/09-10:26:08.445806 7fbe8fbff6c0 Generated table #206@0: 38 keys, 31247 bytes 2026/06/14-22:15:04.242154 7f29d4feb6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/05/09-10:26:08.445836 7fbe8fbff6c0 Compacted 1@0 + 1@1 files => 31247 bytes 2026/06/14-22:15:04.242265 7f29d4feb6c0 Delete type=2 #280
2025/05/09-10:26:08.458685 7fbe8fbff6c0 compacted to: files[ 0 1 0 0 0 0 0 ] 2026/06/14-22:15:04.242389 7f29d4feb6c0 Delete type=2 #346
2025/05/09-10:26:08.458808 7fbe8fbff6c0 Delete type=2 #197 2026/06/14-22:15:04.252717 7f29d4feb6c0 Manual compaction at level-0 from '!items!mClyfwAAlxIE8p8I' @ 79 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)
2025/05/09-10:26:08.458974 7fbe8fbff6c0 Delete type=2 #205
2025/05/09-10:26:08.486140 7fbe8fbff6c0 Manual compaction at level-0 from '!items!wxIHkrq98eQ3cOvp' @ 73 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)
+4 -7
View File
@@ -1,7 +1,4 @@
2025/04/20-09:24:47.881295 7fa412ffd6c0 Recovering log #195 2026/06/14-22:10:29.316470 7f29d67ee6c0 Log #341: 0 ops saved to Table #342 OK
2025/04/20-09:24:47.897306 7fa412ffd6c0 Delete type=3 #193 2026/06/14-22:10:29.316570 7f29d67ee6c0 Archiving /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/armes/000341.log: OK
2025/04/20-09:24:47.897426 7fa412ffd6c0 Delete type=0 #195 2026/06/14-22:10:29.317477 7f29d67ee6c0 Table #280: 38 entries OK
2025/04/20-09:25:06.915266 7fa4127fc6c0 Level-0 table #201: started 2026/06/14-22:10:29.328533 7f29d67ee6c0 **** Repaired leveldb /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/armes; recovered 1 files; 31247 bytes. Some data may have been lost. ****
2025/04/20-09:25:06.915317 7fa4127fc6c0 Level-0 table #201: 0 bytes OK
2025/04/20-09:25:06.922256 7fa4127fc6c0 Delete type=0 #199
2025/04/20-09:25:06.929081 7fa4127fc6c0 Manual compaction at level-0 from '!folders!InCQeTRdT5jXMX82' @ 72057594037927935 : 1 .. '!items!wxIHkrq98eQ3cOvp' @ 0 : 0; will stop at (end)
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000201 MANIFEST-000368
+12 -14
View File
@@ -1,14 +1,12 @@
2025/05/09-10:15:41.365049 7fbe917fa6c0 Recovering log #199 2026/06/14-22:10:29.488552 7f29d5fed6c0 Delete type=3 #1
2025/05/09-10:15:41.456977 7fbe917fa6c0 Delete type=3 #197 2026/06/14-22:15:04.181343 7f29d4feb6c0 Level-0 table #371: started
2025/05/09-10:15:41.457096 7fbe917fa6c0 Delete type=0 #199 2026/06/14-22:15:04.184864 7f29d4feb6c0 Level-0 table #371: 1530 bytes OK
2025/05/09-10:26:08.314346 7fbe8fbff6c0 Level-0 table #204: started 2026/06/14-22:15:04.191733 7f29d4feb6c0 Delete type=0 #369
2025/05/09-10:26:08.321855 7fbe8fbff6c0 Level-0 table #204: 11921 bytes OK 2026/06/14-22:15:04.221018 7f29d4feb6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at '!items!TxdelREyg5zZw0Ro' @ 61 : 1
2025/05/09-10:26:08.334418 7fbe8fbff6c0 Delete type=0 #202 2026/06/14-22:15:04.221028 7f29d4feb6c0 Compacting 2@0 + 0@1 files
2025/05/09-10:26:08.402084 7fbe8fbff6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at '!items!ufvhWG5V8pX0qrtR' @ 54 : 1 2026/06/14-22:15:04.224643 7f29d4feb6c0 Generated table #372@0: 29 keys, 12429 bytes
2025/05/09-10:26:08.402106 7fbe8fbff6c0 Compacting 1@0 + 1@1 files 2026/06/14-22:15:04.224665 7f29d4feb6c0 Compacted 2@0 + 0@1 files => 12429 bytes
2025/05/09-10:26:08.407755 7fbe8fbff6c0 Generated table #205@0: 29 keys, 12111 bytes 2026/06/14-22:15:04.230738 7f29d4feb6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/05/09-10:26:08.407809 7fbe8fbff6c0 Compacted 1@0 + 1@1 files => 12111 bytes 2026/06/14-22:15:04.230826 7f29d4feb6c0 Delete type=2 #339
2025/05/09-10:26:08.419957 7fbe8fbff6c0 compacted to: files[ 0 1 0 0 0 0 0 ] 2026/06/14-22:15:04.231043 7f29d4feb6c0 Delete type=2 #371
2025/05/09-10:26:08.420095 7fbe8fbff6c0 Delete type=2 #174 2026/06/14-22:15:04.252710 7f29d4feb6c0 Manual compaction at level-0 from '!items!TxdelREyg5zZw0Ro' @ 61 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)
2025/05/09-10:26:08.420237 7fbe8fbff6c0 Delete type=2 #204
2025/05/09-10:26:08.486117 7fbe8fbff6c0 Manual compaction at level-0 from '!items!ufvhWG5V8pX0qrtR' @ 54 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)
+4 -7
View File
@@ -1,7 +1,4 @@
2025/04/20-09:24:47.903860 7fa413fff6c0 Recovering log #195 2026/06/14-22:10:29.406858 7f29d5fed6c0 Log #366: 0 ops saved to Table #367 OK
2025/04/20-09:24:47.919442 7fa413fff6c0 Delete type=3 #193 2026/06/14-22:10:29.406947 7f29d5fed6c0 Archiving /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/armures/000366.log: OK
2025/04/20-09:24:47.919592 7fa413fff6c0 Delete type=0 #195 2026/06/14-22:10:29.412084 7f29d5fed6c0 Table #339: 29 entries OK
2025/04/20-09:25:06.908159 7fa4127fc6c0 Level-0 table #200: started 2026/06/14-22:10:29.431548 7f29d5fed6c0 **** Repaired leveldb /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/armures; recovered 1 files; 12276 bytes. Some data may have been lost. ****
2025/04/20-09:25:06.908228 7fa4127fc6c0 Level-0 table #200: 0 bytes OK
2025/04/20-09:25:06.915011 7fa4127fc6c0 Delete type=0 #198
2025/04/20-09:25:06.929064 7fa4127fc6c0 Manual compaction at level-0 from '!folders!2wTJBj3dicRKzNOE' @ 72057594037927935 : 1 .. '!items!ufvhWG5V8pX0qrtR' @ 0 : 0; will stop at (end)
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000198 MANIFEST-000366
+11 -14
View File
@@ -1,14 +1,11 @@
2025/05/09-10:15:41.212131 7fbe907f86c0 Recovering log #196 2026/06/14-22:10:29.310885 7f29d6fef6c0 Delete type=3 #1
2025/05/09-10:15:41.294357 7fbe907f86c0 Delete type=3 #194 2026/06/14-22:15:04.174554 7f29d4feb6c0 Level-0 table #369: started
2025/05/09-10:15:41.294415 7fbe907f86c0 Delete type=0 #196 2026/06/14-22:15:04.174857 7f29d4feb6c0 Level-0 table #369: 0 bytes OK
2025/05/09-10:26:08.334569 7fbe8fbff6c0 Level-0 table #201: started 2026/06/14-22:15:04.181253 7f29d4feb6c0 Delete type=0 #367
2025/05/09-10:26:08.342225 7fbe8fbff6c0 Level-0 table #201: 38203 bytes OK 2026/06/14-22:15:04.209527 7f29d4feb6c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at '!items!yx4k7lQHGcom99mk' @ 237 : 1
2025/05/09-10:26:08.356875 7fbe8fbff6c0 Delete type=0 #199 2026/06/14-22:15:04.209537 7f29d4feb6c0 Compacting 1@0 + 0@1 files
2025/05/09-10:26:08.420303 7fbe8fbff6c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at '!items!yx4k7lQHGcom99mk' @ 237 : 1 2026/06/14-22:15:04.213691 7f29d4feb6c0 Generated table #370@0: 115 keys, 38139 bytes
2025/05/09-10:26:08.420310 7fbe8fbff6c0 Compacting 1@0 + 1@1 files 2026/06/14-22:15:04.213711 7f29d4feb6c0 Compacted 1@0 + 0@1 files => 38139 bytes
2025/05/09-10:26:08.426825 7fbe8fbff6c0 Generated table #202@0: 116 keys, 38485 bytes 2026/06/14-22:15:04.220652 7f29d4feb6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/05/09-10:26:08.426858 7fbe8fbff6c0 Compacted 1@0 + 1@1 files => 38485 bytes 2026/06/14-22:15:04.220864 7f29d4feb6c0 Delete type=2 #337
2025/05/09-10:26:08.438808 7fbe8fbff6c0 compacted to: files[ 0 1 0 0 0 0 0 ] 2026/06/14-22:15:04.252699 7f29d4feb6c0 Manual compaction at level-0 from '!items!yx4k7lQHGcom99mk' @ 237 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at (end)
2025/05/09-10:26:08.438945 7fbe8fbff6c0 Delete type=2 #171
2025/05/09-10:26:08.439090 7fbe8fbff6c0 Delete type=2 #201
2025/05/09-10:26:08.486130 7fbe8fbff6c0 Manual compaction at level-0 from '!items!yx4k7lQHGcom99mk' @ 237 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at (end)
+4 -7
View File
@@ -1,7 +1,4 @@
2025/04/20-09:24:47.857871 7fa4137fe6c0 Recovering log #192 2026/06/14-22:10:28.958293 7f29d6fef6c0 Log #364: 0 ops saved to Table #365 OK
2025/04/20-09:24:47.873833 7fa4137fe6c0 Delete type=3 #190 2026/06/14-22:10:28.958391 7f29d6fef6c0 Archiving /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/competences/000364.log: OK
2025/04/20-09:24:47.873948 7fa4137fe6c0 Delete type=0 #192 2026/06/14-22:10:28.961207 7f29d6fef6c0 Table #337: 115 entries OK
2025/04/20-09:25:06.901277 7fa4127fc6c0 Level-0 table #197: started 2026/06/14-22:10:28.974149 7f29d6fef6c0 **** Repaired leveldb /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/competences; recovered 1 files; 38139 bytes. Some data may have been lost. ****
2025/04/20-09:25:06.901384 7fa4127fc6c0 Level-0 table #197: 0 bytes OK
2025/04/20-09:25:06.907939 7fa4127fc6c0 Delete type=0 #195
2025/04/20-09:25:06.929038 7fa4127fc6c0 Manual compaction at level-0 from '!folders!4OPhigzcPv46qbWW' @ 72057594037927935 : 1 .. '!items!yx4k7lQHGcom99mk' @ 0 : 0; will stop at (end)
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000210 MANIFEST-000378
+11 -14
View File
@@ -1,14 +1,11 @@
2025/05/09-10:15:41.459323 7fbe907f86c0 Recovering log #208 2026/06/14-22:10:29.572918 7f29d57ec6c0 Delete type=3 #1
2025/05/09-10:15:41.503379 7fbe907f86c0 Delete type=3 #206 2026/06/14-22:15:04.252921 7f29d4feb6c0 Level-0 table #381: started
2025/05/09-10:15:41.503446 7fbe907f86c0 Delete type=0 #208 2026/06/14-22:15:04.252975 7f29d4feb6c0 Level-0 table #381: 0 bytes OK
2025/05/09-10:26:08.376101 7fbe8fbff6c0 Level-0 table #213: started 2026/06/14-22:15:04.259425 7f29d4feb6c0 Delete type=0 #379
2025/05/09-10:26:08.388425 7fbe8fbff6c0 Level-0 table #213: 263867 bytes OK 2026/06/14-22:15:04.282981 7f29d4feb6c0 Manual compaction at level-0 from '!folders!9PQi3Lv54rpcxavo' @ 72057594037927935 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at '!items!zGlRtP7zSnkjuuue' @ 510 : 1
2025/05/09-10:26:08.401652 7fbe8fbff6c0 Delete type=0 #211 2026/06/14-22:15:04.282992 7f29d4feb6c0 Compacting 1@0 + 0@1 files
2025/05/09-10:26:08.459044 7fbe8fbff6c0 Manual compaction at level-0 from '!folders!9PQi3Lv54rpcxavo' @ 72057594037927935 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at '!items!zGlRtP7zSnkjuuue' @ 510 : 1 2026/06/14-22:15:04.290938 7f29d4feb6c0 Generated table #382@0: 71 keys, 264301 bytes
2025/05/09-10:26:08.459053 7fbe8fbff6c0 Compacting 1@0 + 1@1 files 2026/06/14-22:15:04.290959 7f29d4feb6c0 Compacted 1@0 + 0@1 files => 264301 bytes
2025/05/09-10:26:08.472966 7fbe8fbff6c0 Generated table #214@0: 71 keys, 264215 bytes 2026/06/14-22:15:04.297753 7f29d4feb6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/05/09-10:26:08.472996 7fbe8fbff6c0 Compacted 1@0 + 1@1 files => 264215 bytes 2026/06/14-22:15:04.297871 7f29d4feb6c0 Delete type=2 #349
2025/05/09-10:26:08.485587 7fbe8fbff6c0 compacted to: files[ 0 1 0 0 0 0 0 ] 2026/06/14-22:15:04.329889 7f29d4feb6c0 Manual compaction at level-0 from '!items!zGlRtP7zSnkjuuue' @ 510 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at (end)
2025/05/09-10:26:08.485765 7fbe8fbff6c0 Delete type=2 #205
2025/05/09-10:26:08.485988 7fbe8fbff6c0 Delete type=2 #213
2025/05/09-10:26:08.486148 7fbe8fbff6c0 Manual compaction at level-0 from '!items!zGlRtP7zSnkjuuue' @ 510 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at (end)
+4 -7
View File
@@ -1,7 +1,4 @@
2025/04/20-09:24:47.923568 7fa418ffa6c0 Recovering log #203 2026/06/14-22:10:29.493618 7f29d57ec6c0 Log #376: 0 ops saved to Table #377 OK
2025/04/20-09:24:47.940475 7fa418ffa6c0 Delete type=3 #201 2026/06/14-22:10:29.493742 7f29d57ec6c0 Archiving /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/education/000376.log: OK
2025/04/20-09:24:47.940632 7fa418ffa6c0 Delete type=0 #203 2026/06/14-22:10:29.496413 7f29d57ec6c0 Table #349: 71 entries OK
2025/04/20-09:25:06.922414 7fa4127fc6c0 Level-0 table #209: started 2026/06/14-22:10:29.511862 7f29d57ec6c0 **** Repaired leveldb /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/education; recovered 1 files; 264301 bytes. Some data may have been lost. ****
2025/04/20-09:25:06.922447 7fa4127fc6c0 Level-0 table #209: 0 bytes OK
2025/04/20-09:25:06.928838 7fa4127fc6c0 Delete type=0 #207
2025/04/20-09:25:06.929095 7fa4127fc6c0 Manual compaction at level-0 from '!folders!9PQi3Lv54rpcxavo' @ 72057594037927935 : 1 .. '!items!zGlRtP7zSnkjuuue' @ 0 : 0; will stop at (end)
Binary file not shown.
Binary file not shown.
View File
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000201 MANIFEST-000367
+11 -14
View File
@@ -1,14 +1,11 @@
2025/05/09-10:15:41.507118 7fbe91ffb6c0 Recovering log #199 2026/06/14-22:10:29.652898 7f29d6fef6c0 Delete type=3 #1
2025/05/09-10:15:41.563016 7fbe91ffb6c0 Delete type=3 #197 2026/06/14-22:15:04.266316 7f29d4feb6c0 Level-0 table #370: started
2025/05/09-10:15:41.563136 7fbe91ffb6c0 Delete type=0 #199 2026/06/14-22:15:04.266344 7f29d4feb6c0 Level-0 table #370: 0 bytes OK
2025/05/09-10:26:08.486247 7fbe8fbff6c0 Level-0 table #204: started 2026/06/14-22:15:04.273013 7f29d4feb6c0 Delete type=0 #368
2025/05/09-10:26:08.492712 7fbe8fbff6c0 Level-0 table #204: 20052 bytes OK 2026/06/14-22:15:04.309352 7f29d4feb6c0 Manual compaction at level-0 from '!items!17mjvwS8R3B6LloG' @ 72057594037927935 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at '!items!zUYIVOuFpRur9aAR' @ 109 : 1
2025/05/09-10:26:08.521869 7fbe8fbff6c0 Delete type=0 #202 2026/06/14-22:15:04.309362 7f29d4feb6c0 Compacting 1@0 + 0@1 files
2025/05/09-10:26:08.657886 7fbe8fbff6c0 Manual compaction at level-0 from '!items!17mjvwS8R3B6LloG' @ 72057594037927935 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at '!items!zUYIVOuFpRur9aAR' @ 109 : 1 2026/06/14-22:15:04.313192 7f29d4feb6c0 Generated table #371@0: 49 keys, 20052 bytes
2025/05/09-10:26:08.657901 7fbe8fbff6c0 Compacting 1@0 + 1@1 files 2026/06/14-22:15:04.313211 7f29d4feb6c0 Compacted 1@0 + 0@1 files => 20052 bytes
2025/05/09-10:26:08.675906 7fbe8fbff6c0 Generated table #205@0: 49 keys, 20052 bytes 2026/06/14-22:15:04.319393 7f29d4feb6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/05/09-10:26:08.675933 7fbe8fbff6c0 Compacted 1@0 + 1@1 files => 20052 bytes 2026/06/14-22:15:04.319493 7f29d4feb6c0 Delete type=2 #338
2025/05/09-10:26:08.712163 7fbe8fbff6c0 compacted to: files[ 0 1 0 0 0 0 0 ] 2026/06/14-22:15:04.329912 7f29d4feb6c0 Manual compaction at level-0 from '!items!zUYIVOuFpRur9aAR' @ 109 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at (end)
2025/05/09-10:26:08.712328 7fbe8fbff6c0 Delete type=2 #196
2025/05/09-10:26:08.712603 7fbe8fbff6c0 Delete type=2 #204
2025/05/09-10:26:08.869429 7fbe8fbff6c0 Manual compaction at level-0 from '!items!zUYIVOuFpRur9aAR' @ 109 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at (end)
+4 -7
View File
@@ -1,7 +1,4 @@
2025/04/20-09:24:47.948681 7fa4137fe6c0 Recovering log #194 2026/06/14-22:10:29.580134 7f29d6fef6c0 Log #365: 0 ops saved to Table #366 OK
2025/04/20-09:24:47.965382 7fa4137fe6c0 Delete type=3 #192 2026/06/14-22:10:29.580261 7f29d6fef6c0 Archiving /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/graces/000365.log: OK
2025/04/20-09:24:47.965487 7fa4137fe6c0 Delete type=0 #194 2026/06/14-22:10:29.582004 7f29d6fef6c0 Table #338: 49 entries OK
2025/04/20-09:25:06.935620 7fa4127fc6c0 Level-0 table #200: started 2026/06/14-22:10:29.594386 7f29d6fef6c0 **** Repaired leveldb /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/graces; recovered 1 files; 20052 bytes. Some data may have been lost. ****
2025/04/20-09:25:06.935652 7fa4127fc6c0 Level-0 table #200: 0 bytes OK
2025/04/20-09:25:06.942921 7fa4127fc6c0 Delete type=0 #198
2025/04/20-09:25:06.956261 7fa4127fc6c0 Manual compaction at level-0 from '!items!17mjvwS8R3B6LloG' @ 72057594037927935 : 1 .. '!items!zUYIVOuFpRur9aAR' @ 0 : 0; will stop at (end)
Binary file not shown.
Binary file not shown.
View File
View File
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000201 MANIFEST-000367
+11 -14
View File
@@ -1,14 +1,11 @@
2025/05/09-10:15:41.566104 7fbe917fa6c0 Recovering log #199 2026/06/14-22:10:29.753879 7f29d57ec6c0 Delete type=3 #1
2025/05/09-10:15:41.607068 7fbe917fa6c0 Delete type=3 #197 2026/06/14-22:15:04.203040 7f29d4feb6c0 Level-0 table #370: started
2025/05/09-10:15:41.607127 7fbe917fa6c0 Delete type=0 #199 2026/06/14-22:15:04.203069 7f29d4feb6c0 Level-0 table #370: 0 bytes OK
2025/05/09-10:26:08.522102 7fbe8fbff6c0 Level-0 table #204: started 2026/06/14-22:15:04.209414 7f29d4feb6c0 Delete type=0 #368
2025/05/09-10:26:08.533326 7fbe8fbff6c0 Level-0 table #204: 11517 bytes OK 2026/06/14-22:15:04.242440 7f29d4feb6c0 Manual compaction at level-0 from '!items!1icaxIywAwDXQcMz' @ 72057594037927935 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at '!items!ysGehYm1VkMWrI22' @ 71 : 1
2025/05/09-10:26:08.560180 7fbe8fbff6c0 Delete type=0 #202 2026/06/14-22:15:04.242446 7f29d4feb6c0 Compacting 1@0 + 0@1 files
2025/05/09-10:26:08.712861 7fbe8fbff6c0 Manual compaction at level-0 from '!items!1icaxIywAwDXQcMz' @ 72057594037927935 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at '!items!ysGehYm1VkMWrI22' @ 71 : 1 2026/06/14-22:15:04.246114 7f29d4feb6c0 Generated table #371@0: 17 keys, 11517 bytes
2025/05/09-10:26:08.712889 7fbe8fbff6c0 Compacting 1@0 + 1@1 files 2026/06/14-22:15:04.246131 7f29d4feb6c0 Compacted 1@0 + 0@1 files => 11517 bytes
2025/05/09-10:26:08.728740 7fbe8fbff6c0 Generated table #205@0: 17 keys, 11517 bytes 2026/06/14-22:15:04.252512 7f29d4feb6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/05/09-10:26:08.728771 7fbe8fbff6c0 Compacted 1@0 + 1@1 files => 11517 bytes 2026/06/14-22:15:04.252602 7f29d4feb6c0 Delete type=2 #338
2025/05/09-10:26:08.762648 7fbe8fbff6c0 compacted to: files[ 0 1 0 0 0 0 0 ] 2026/06/14-22:15:04.252724 7f29d4feb6c0 Manual compaction at level-0 from '!items!ysGehYm1VkMWrI22' @ 71 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at (end)
2025/05/09-10:26:08.762817 7fbe8fbff6c0 Delete type=2 #196
2025/05/09-10:26:08.762965 7fbe8fbff6c0 Delete type=2 #204
2025/05/09-10:26:08.869440 7fbe8fbff6c0 Manual compaction at level-0 from '!items!ysGehYm1VkMWrI22' @ 71 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at (end)
+4 -7
View File
@@ -1,7 +1,4 @@
2025/04/20-09:24:47.972234 7fa412ffd6c0 Recovering log #194 2026/06/14-22:10:29.658579 7f29d57ec6c0 Log #365: 0 ops saved to Table #366 OK
2025/04/20-09:24:47.989602 7fa412ffd6c0 Delete type=3 #192 2026/06/14-22:10:29.658709 7f29d57ec6c0 Archiving /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/maladies/000365.log: OK
2025/04/20-09:24:47.989720 7fa412ffd6c0 Delete type=0 #194 2026/06/14-22:10:29.664972 7f29d57ec6c0 Table #338: 17 entries OK
2025/04/20-09:25:06.929262 7fa4127fc6c0 Level-0 table #200: started 2026/06/14-22:10:29.687510 7f29d57ec6c0 **** Repaired leveldb /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/maladies; recovered 1 files; 11517 bytes. Some data may have been lost. ****
2025/04/20-09:25:06.929306 7fa4127fc6c0 Level-0 table #200: 0 bytes OK
2025/04/20-09:25:06.935454 7fa4127fc6c0 Delete type=0 #198
2025/04/20-09:25:06.956241 7fa4127fc6c0 Manual compaction at level-0 from '!items!1icaxIywAwDXQcMz' @ 72057594037927935 : 1 .. '!items!ysGehYm1VkMWrI22' @ 0 : 0; will stop at (end)
Binary file not shown.
Binary file not shown.
View File
View File
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000138 MANIFEST-000305
+12 -14
View File
@@ -1,14 +1,12 @@
2025/05/09-10:15:41.675033 7fbe91ffb6c0 Recovering log #136 2026/06/14-22:10:29.936915 7f29d6fef6c0 Delete type=3 #1
2025/05/09-10:15:41.730910 7fbe91ffb6c0 Delete type=3 #134 2026/06/14-22:15:04.273128 7f29d4feb6c0 Level-0 table #308: started
2025/05/09-10:15:41.730997 7fbe91ffb6c0 Delete type=0 #136 2026/06/14-22:15:04.276527 7f29d4feb6c0 Level-0 table #308: 1499 bytes OK
2025/05/09-10:26:08.601281 7fbe8fbff6c0 Level-0 table #141: started 2026/06/14-22:15:04.282847 7f29d4feb6c0 Delete type=0 #306
2025/05/09-10:26:08.620048 7fbe8fbff6c0 Level-0 table #141: 1344 bytes OK 2026/06/14-22:15:04.319636 7f29d4feb6c0 Manual compaction at level-0 from '!scenes!FJXugdbkBpEJEdR6' @ 72057594037927935 : 1 .. '!scenes.levels!FJXugdbkBpEJEdR6.defaultLevel0000' @ 0 : 0; will stop at '!scenes.levels!FJXugdbkBpEJEdR6.defaultLevel0000' @ 6 : 1
2025/05/09-10:26:08.657679 7fbe8fbff6c0 Delete type=0 #139 2026/06/14-22:15:04.319647 7f29d4feb6c0 Compacting 2@0 + 0@1 files
2025/05/09-10:26:08.818209 7fbe8fbff6c0 Manual compaction at level-0 from '!scenes!FJXugdbkBpEJEdR6' @ 72057594037927935 : 1 .. '!scenes!FJXugdbkBpEJEdR6' @ 0 : 0; will stop at '!scenes!FJXugdbkBpEJEdR6' @ 5 : 1 2026/06/14-22:15:04.322943 7f29d4feb6c0 Generated table #309@0: 2 keys, 1499 bytes
2025/05/09-10:26:08.818224 7fbe8fbff6c0 Compacting 1@0 + 1@1 files 2026/06/14-22:15:04.322965 7f29d4feb6c0 Compacted 2@0 + 0@1 files => 1499 bytes
2025/05/09-10:26:08.836037 7fbe8fbff6c0 Generated table #142@0: 1 keys, 1344 bytes 2026/06/14-22:15:04.329615 7f29d4feb6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/05/09-10:26:08.836067 7fbe8fbff6c0 Compacted 1@0 + 1@1 files => 1344 bytes 2026/06/14-22:15:04.329697 7f29d4feb6c0 Delete type=2 #300
2025/05/09-10:26:08.869141 7fbe8fbff6c0 compacted to: files[ 0 1 0 0 0 0 0 ] 2026/06/14-22:15:04.329824 7f29d4feb6c0 Delete type=2 #308
2025/05/09-10:26:08.869252 7fbe8fbff6c0 Delete type=2 #111 2026/06/14-22:15:04.330120 7f29d4feb6c0 Manual compaction at level-0 from '!scenes.levels!FJXugdbkBpEJEdR6.defaultLevel0000' @ 6 : 1 .. '!scenes.levels!FJXugdbkBpEJEdR6.defaultLevel0000' @ 0 : 0; will stop at (end)
2025/05/09-10:26:08.869366 7fbe8fbff6c0 Delete type=2 #141
2025/05/09-10:26:08.869479 7fbe8fbff6c0 Manual compaction at level-0 from '!scenes!FJXugdbkBpEJEdR6' @ 5 : 1 .. '!scenes!FJXugdbkBpEJEdR6' @ 0 : 0; will stop at (end)
+4 -7
View File
@@ -1,7 +1,4 @@
2025/04/20-09:24:48.018535 7fa418ffa6c0 Recovering log #132 2026/06/14-22:10:29.840720 7f29d6fef6c0 Log #303: 0 ops saved to Table #304 OK
2025/04/20-09:24:48.034352 7fa418ffa6c0 Delete type=3 #130 2026/06/14-22:10:29.840844 7f29d6fef6c0 Archiving /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/scenes/000303.log: OK
2025/04/20-09:24:48.034446 7fa418ffa6c0 Delete type=0 #132 2026/06/14-22:10:29.840926 7f29d6fef6c0 Table #300: 2 entries OK
2025/04/20-09:25:06.943076 7fa4127fc6c0 Level-0 table #137: started 2026/06/14-22:10:29.863454 7f29d6fef6c0 **** Repaired leveldb /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/scenes; recovered 1 files; 1499 bytes. Some data may have been lost. ****
2025/04/20-09:25:06.943110 7fa4127fc6c0 Level-0 table #137: 0 bytes OK
2025/04/20-09:25:06.949678 7fa4127fc6c0 Delete type=0 #135
2025/04/20-09:25:06.956277 7fa4127fc6c0 Manual compaction at level-0 from '!scenes!FJXugdbkBpEJEdR6' @ 72057594037927935 : 1 .. '!scenes!FJXugdbkBpEJEdR6' @ 0 : 0; will stop at (end)
Binary file not shown.
Binary file not shown.
View File
View File
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000201 MANIFEST-000368
+11 -14
View File
@@ -1,14 +1,11 @@
2025/05/09-10:15:41.609264 7fbe90ff96c0 Recovering log #199 2026/06/14-22:10:29.834862 7f29d6fef6c0 Delete type=3 #1
2025/05/09-10:15:41.672478 7fbe90ff96c0 Delete type=3 #197 2026/06/14-22:15:04.259532 7f29d4feb6c0 Level-0 table #371: started
2025/05/09-10:15:41.672535 7fbe90ff96c0 Delete type=0 #199 2026/06/14-22:15:04.259561 7f29d4feb6c0 Level-0 table #371: 0 bytes OK
2025/05/09-10:26:08.560441 7fbe8fbff6c0 Level-0 table #204: started 2026/06/14-22:15:04.266195 7f29d4feb6c0 Delete type=0 #369
2025/05/09-10:26:08.570942 7fbe8fbff6c0 Level-0 table #204: 21176 bytes OK 2026/06/14-22:15:04.298029 7f29d4feb6c0 Manual compaction at level-0 from '!items!1bAL2MQVpVBd0c5Z' @ 72057594037927935 : 1 .. '!items!zs67k4sxCid6oTK3' @ 0 : 0; will stop at '!items!zs67k4sxCid6oTK3' @ 80 : 1
2025/05/09-10:26:08.601073 7fbe8fbff6c0 Delete type=0 #202 2026/06/14-22:15:04.298039 7f29d4feb6c0 Compacting 1@0 + 0@1 files
2025/05/09-10:26:08.763048 7fbe8fbff6c0 Manual compaction at level-0 from '!items!1bAL2MQVpVBd0c5Z' @ 72057594037927935 : 1 .. '!items!zs67k4sxCid6oTK3' @ 0 : 0; will stop at '!items!zs67k4sxCid6oTK3' @ 80 : 1 2026/06/14-22:15:04.302060 7f29d4feb6c0 Generated table #372@0: 36 keys, 20892 bytes
2025/05/09-10:26:08.763056 7fbe8fbff6c0 Compacting 1@0 + 1@1 files 2026/06/14-22:15:04.302082 7f29d4feb6c0 Compacted 1@0 + 0@1 files => 20892 bytes
2025/05/09-10:26:08.781378 7fbe8fbff6c0 Generated table #205@0: 36 keys, 21176 bytes 2026/06/14-22:15:04.309124 7f29d4feb6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/05/09-10:26:08.781419 7fbe8fbff6c0 Compacted 1@0 + 1@1 files => 21176 bytes 2026/06/14-22:15:04.309213 7f29d4feb6c0 Delete type=2 #339
2025/05/09-10:26:08.817648 7fbe8fbff6c0 compacted to: files[ 0 1 0 0 0 0 0 ] 2026/06/14-22:15:04.329902 7f29d4feb6c0 Manual compaction at level-0 from '!items!zs67k4sxCid6oTK3' @ 80 : 1 .. '!items!zs67k4sxCid6oTK3' @ 0 : 0; will stop at (end)
2025/05/09-10:26:08.817810 7fbe8fbff6c0 Delete type=2 #196
2025/05/09-10:26:08.818060 7fbe8fbff6c0 Delete type=2 #204
2025/05/09-10:26:08.869448 7fbe8fbff6c0 Manual compaction at level-0 from '!items!zs67k4sxCid6oTK3' @ 80 : 1 .. '!items!zs67k4sxCid6oTK3' @ 0 : 0; will stop at (end)
+4 -7
View File
@@ -1,7 +1,4 @@
2025/04/20-09:24:47.993946 7fa413fff6c0 Recovering log #194 2026/06/14-22:10:29.759017 7f29d6fef6c0 Log #366: 0 ops saved to Table #367 OK
2025/04/20-09:24:48.011487 7fa413fff6c0 Delete type=3 #192 2026/06/14-22:10:29.759133 7f29d6fef6c0 Archiving /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/simples/000366.log: OK
2025/04/20-09:24:48.011668 7fa413fff6c0 Delete type=0 #194 2026/06/14-22:10:29.761524 7f29d6fef6c0 Table #339: 36 entries OK
2025/04/20-09:25:06.949829 7fa4127fc6c0 Level-0 table #200: started 2026/06/14-22:10:29.777665 7f29d6fef6c0 **** Repaired leveldb /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-te-deum/packs/simples; recovered 1 files; 20892 bytes. Some data may have been lost. ****
2025/04/20-09:25:06.949863 7fa4127fc6c0 Level-0 table #200: 0 bytes OK
2025/04/20-09:25:06.956072 7fa4127fc6c0 Delete type=0 #198
2025/04/20-09:25:06.956290 7fa4127fc6c0 Manual compaction at level-0 from '!items!1bAL2MQVpVBd0c5Z' @ 72057594037927935 : 1 .. '!items!zs67k4sxCid6oTK3' @ 0 : 0; will stop at (end)
Binary file not shown.
Binary file not shown.
View File
View File

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