Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c36f2d0116 | |||
| 690293c1c8 | |||
| 04e35228e4 | |||
| ec2d5385c5 | |||
| 438caf3b1c | |||
| 627ccc707b |
63
.gitea/workflows/release.yaml
Normal file
63
.gitea/workflows/release.yaml
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
name: Release Creation
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner."
|
||||||
|
|
||||||
|
#- uses: actions/checkout@v3
|
||||||
|
- uses: RouxAntoine/checkout@v3.5.4
|
||||||
|
|
||||||
|
# get part of the tag after the `v`
|
||||||
|
- name: Extract tag version number
|
||||||
|
id: get_version
|
||||||
|
uses: battila7/get-version-action@v2
|
||||||
|
|
||||||
|
# Substitute the Manifest and Download URLs in the system.json
|
||||||
|
- name: Substitute Manifest and Download Links For Versioned Ones
|
||||||
|
id: sub_manifest_link_version
|
||||||
|
uses: microsoft/variable-substitution@v1
|
||||||
|
with:
|
||||||
|
files: 'system.json'
|
||||||
|
env:
|
||||||
|
version: ${{steps.get_version.outputs.version-without-v}}
|
||||||
|
url: https://www.uberwald.me/gitea/${{gitea.repository}}
|
||||||
|
manifest: https://www.uberwald.me/gitea/public/fvtt-wasteland/releases/download/latest/system.json
|
||||||
|
download: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-wasteland.zip
|
||||||
|
|
||||||
|
# Create a zip file with all files required by the module to add to the release
|
||||||
|
- run: |
|
||||||
|
apt update -y
|
||||||
|
apt install -y zip
|
||||||
|
|
||||||
|
- run: zip -r ./fvtt-wasteland.zip system.json README.md changelog.md assets/ lang/ modules/ packs/ styles/ templates/ template.json
|
||||||
|
|
||||||
|
- name: setup go
|
||||||
|
uses: https://github.com/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: '>=1.20.1'
|
||||||
|
|
||||||
|
- name: Use Go Action
|
||||||
|
id: use-go-action
|
||||||
|
uses: https://gitea.com/actions/release-action@main
|
||||||
|
with:
|
||||||
|
files: |-
|
||||||
|
./fvtt-wasteland.zip
|
||||||
|
system.json
|
||||||
|
api_key: '${{secrets.ALLOW_PUSH_RELEASE}}'
|
||||||
|
|
||||||
|
- name: Publish to Foundry server
|
||||||
|
uses: https://github.com/djlechuck/foundryvtt-publish-package-action@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.FOUNDRYVTT_RELEASE_TOKEN }}
|
||||||
|
id: 'fvtt-wasteland'
|
||||||
|
version: ${{github.event.release.tag_name}}
|
||||||
|
manifest: 'https://www.uberwald.me/gitea/public/fvtt-wasteland/releases/download/latest/system.json'
|
||||||
|
notes: 'https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-wasteland.zip'
|
||||||
|
compatibility-minimum: '13'
|
||||||
|
compatibility-verified: '13'
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
.history/
|
.history/
|
||||||
|
node_modules
|
||||||
|
|||||||
35
gulpfile.js
Normal file
35
gulpfile.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
const gulp = require('gulp');
|
||||||
|
const less = require('gulp-less');
|
||||||
|
const sourcemaps = require('gulp-sourcemaps');
|
||||||
|
|
||||||
|
// Paths
|
||||||
|
const paths = {
|
||||||
|
styles: {
|
||||||
|
src: 'less/**/*.less',
|
||||||
|
dest: 'styles/'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compile LESS to CSS
|
||||||
|
function styles() {
|
||||||
|
return gulp.src('less/wasteland.less')
|
||||||
|
.pipe(sourcemaps.init())
|
||||||
|
.pipe(less())
|
||||||
|
.pipe(sourcemaps.write('.'))
|
||||||
|
.pipe(gulp.dest(paths.styles.dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch files
|
||||||
|
function watchFiles() {
|
||||||
|
gulp.watch(paths.styles.src, styles);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define complex tasks
|
||||||
|
const build = gulp.series(styles);
|
||||||
|
const watch = gulp.series(build, watchFiles);
|
||||||
|
|
||||||
|
// Export tasks
|
||||||
|
exports.styles = styles;
|
||||||
|
exports.build = build;
|
||||||
|
exports.watch = watch;
|
||||||
|
exports.default = build;
|
||||||
@@ -6,6 +6,8 @@
|
|||||||
"protection": "Protection",
|
"protection": "Protection",
|
||||||
"monnaie": "Monnaie",
|
"monnaie": "Monnaie",
|
||||||
"equipement": "Equipement",
|
"equipement": "Equipement",
|
||||||
|
"don": "Don",
|
||||||
|
"hubris": "Hubris",
|
||||||
"capacite": "Capacité",
|
"capacite": "Capacité",
|
||||||
"origine": "Origine",
|
"origine": "Origine",
|
||||||
"heritage": "Héritage",
|
"heritage": "Héritage",
|
||||||
@@ -19,7 +21,7 @@
|
|||||||
},
|
},
|
||||||
"Actor": {
|
"Actor": {
|
||||||
"personnage": "Personnage",
|
"personnage": "Personnage",
|
||||||
"pnj": "PNJ"
|
"creature": "Créature"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1201
less/actor-styles.less
Normal file
1201
less/actor-styles.less
Normal file
File diff suppressed because it is too large
Load Diff
859
less/chat-styles.less
Normal file
859
less/chat-styles.less
Normal file
@@ -0,0 +1,859 @@
|
|||||||
|
/* ============================================ */
|
||||||
|
/* WASTELAND CHAT MESSAGE STYLES */
|
||||||
|
/* Post-Apocalyptic Theme */
|
||||||
|
/* ============================================ */
|
||||||
|
|
||||||
|
.wasteland-chat-result {
|
||||||
|
background: linear-gradient(135deg, rgba(50, 40, 30, 0.95) 0%, rgba(30, 25, 20, 0.95) 100%);
|
||||||
|
border: 2px solid #8b7355;
|
||||||
|
border-radius: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
// Effet de texture sale/usée
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background:
|
||||||
|
repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
transparent,
|
||||||
|
transparent 2px,
|
||||||
|
rgba(0, 0, 0, 0.03) 2px,
|
||||||
|
rgba(0, 0, 0, 0.03) 4px
|
||||||
|
);
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-result-header {
|
||||||
|
background: linear-gradient(135deg, #3d2f1f 0%, #2a1f15 100%);
|
||||||
|
border-bottom: 2px solid #8b7355;
|
||||||
|
padding: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.625rem;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.4);
|
||||||
|
|
||||||
|
// Effet rouille sur le bord
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
bottom: -2px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 2px;
|
||||||
|
background: linear-gradient(90deg,
|
||||||
|
transparent 0%,
|
||||||
|
#6a0606 20%,
|
||||||
|
#8b7355 40%,
|
||||||
|
#6a0606 60%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.actor-icon {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 2px solid #8b7355;
|
||||||
|
object-fit: cover;
|
||||||
|
flex-shrink: 0;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.6);
|
||||||
|
filter: contrast(1.1) saturate(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-info {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.actor-name {
|
||||||
|
margin: 0;
|
||||||
|
color: #e8dcc4;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.9);
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-title {
|
||||||
|
color: #c9a86a;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin-top: 0.125rem;
|
||||||
|
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.9);
|
||||||
|
font-style: italic;
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
color: #8b7355;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-main {
|
||||||
|
background: linear-gradient(180deg, rgba(230, 220, 200, 0.9) 0%, rgba(210, 200, 180, 0.9) 100%);
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
border-bottom: 1px solid rgba(139, 115, 85, 0.5);
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.damage {
|
||||||
|
background: linear-gradient(180deg, rgba(200, 180, 160, 0.95) 0%, rgba(180, 160, 140, 0.95) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-display {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 0.1875rem;
|
||||||
|
|
||||||
|
.dice-result,
|
||||||
|
.total-result,
|
||||||
|
.difficulty {
|
||||||
|
text-align: center;
|
||||||
|
flex: 1;
|
||||||
|
background: linear-gradient(180deg, rgba(50, 40, 30, 0.7) 0%, rgba(40, 30, 20, 0.8) 100%);
|
||||||
|
padding: 0.25rem 0.375rem;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 2px solid #8b7355;
|
||||||
|
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5), 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: #c9a86a;
|
||||||
|
font-size: 1rem;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.125rem;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dice-value,
|
||||||
|
.total-value,
|
||||||
|
.difficulty-value {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: #e8dcc4;
|
||||||
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.9);
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-label,
|
||||||
|
.difficulty-label {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: #c9a86a;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1.1;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.damage-display {
|
||||||
|
.damage-total {
|
||||||
|
text-align: center;
|
||||||
|
background: linear-gradient(180deg, rgba(60, 50, 40, 0.8) 0%, rgba(50, 40, 30, 0.9) 100%);
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 2px solid #8b7355;
|
||||||
|
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.6), 0 2px 4px rgba(0, 0, 0, 0.4);
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: #c9a86a;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.damage-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #c9a86a;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.damage-value {
|
||||||
|
display: block;
|
||||||
|
font-size: 2rem;
|
||||||
|
color: #e8dcc4;
|
||||||
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.9), 0 0 8px rgba(200, 0, 0, 0.3);
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-badge-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
|
||||||
|
.result-badge {
|
||||||
|
padding: 0.25rem 0.75rem;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.2);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.4);
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.heroique {
|
||||||
|
background: linear-gradient(135deg, #c9a86a 0%, #8b7355 100%);
|
||||||
|
color: #1a1a1a;
|
||||||
|
text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.5);
|
||||||
|
border-color: #8b7355;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.success {
|
||||||
|
background: linear-gradient(135deg, #6b8e23 0%, #4a6017 100%);
|
||||||
|
color: #e8dcc4;
|
||||||
|
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.8);
|
||||||
|
border-color: #4a6017;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.failure {
|
||||||
|
background: linear-gradient(135deg, #5a4a3a 0%, #3a2a1a 100%);
|
||||||
|
color: #c9a86a;
|
||||||
|
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.9);
|
||||||
|
border-color: #3a2a1a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.dramatique {
|
||||||
|
background: linear-gradient(135deg, #4a0404 0%, #2a0202 100%);
|
||||||
|
color: #e8dcc4;
|
||||||
|
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.9);
|
||||||
|
border-color: #6a0606;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-details {
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: linear-gradient(180deg, rgba(70, 60, 50, 0.6) 0%, rgba(60, 50, 40, 0.7) 100%);
|
||||||
|
border-top: 1px solid rgba(139, 115, 85, 0.3);
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
|
||||||
|
.details-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.1875rem;
|
||||||
|
|
||||||
|
.detail-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0.1875rem 0.375rem;
|
||||||
|
background: linear-gradient(90deg, rgba(230, 220, 200, 0.6) 0%, rgba(210, 200, 180, 0.5) 100%);
|
||||||
|
border-radius: 1px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
border-left: 2px solid #8b7355;
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||||
|
|
||||||
|
&.bonus {
|
||||||
|
background: linear-gradient(90deg, rgba(200, 220, 180, 0.7) 0%, rgba(180, 200, 160, 0.6) 100%);
|
||||||
|
border-left-color: #6b8e23;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.malus {
|
||||||
|
background: linear-gradient(90deg, rgba(220, 180, 160, 0.7) 0%, rgba(200, 160, 140, 0.6) 100%);
|
||||||
|
border-left-color: #8b4513;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.rune {
|
||||||
|
background: linear-gradient(90deg, rgba(190, 180, 210, 0.7) 0%, rgba(170, 160, 190, 0.6) 100%);
|
||||||
|
border-left-color: #6a5acd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-label {
|
||||||
|
color: #2a1f15;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-value {
|
||||||
|
color: #2a1f15;
|
||||||
|
font-weight: 500;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-effects {
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: linear-gradient(180deg, rgba(80, 70, 60, 0.5) 0%, rgba(70, 60, 50, 0.6) 100%);
|
||||||
|
border-top: 1px solid rgba(139, 115, 85, 0.4);
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
|
||||||
|
.effect-success,
|
||||||
|
.effect-warning,
|
||||||
|
.effect-failure,
|
||||||
|
.effect-damage,
|
||||||
|
.effect-heroic {
|
||||||
|
padding: 0.3125rem 0.5rem;
|
||||||
|
margin-bottom: 0.3125rem;
|
||||||
|
background: linear-gradient(90deg, rgba(230, 220, 200, 0.8) 0%, rgba(210, 200, 180, 0.7) 100%);
|
||||||
|
border-radius: 1px;
|
||||||
|
border-left: 3px solid;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.effect-success {
|
||||||
|
border-left-color: #6b8e23;
|
||||||
|
color: #2a1f15;
|
||||||
|
}
|
||||||
|
|
||||||
|
.effect-heroic {
|
||||||
|
border-left-color: #c9a86a;
|
||||||
|
color: #2a1f15;
|
||||||
|
font-weight: bold;
|
||||||
|
background: linear-gradient(90deg, rgba(201, 168, 106, 0.3) 0%, rgba(230, 220, 200, 0.8) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.effect-warning {
|
||||||
|
border-left-color: #d97706;
|
||||||
|
color: #2a1f15;
|
||||||
|
}
|
||||||
|
|
||||||
|
.effect-failure {
|
||||||
|
border-left-color: #8b4513;
|
||||||
|
color: #2a1f15;
|
||||||
|
}
|
||||||
|
|
||||||
|
.effect-damage {
|
||||||
|
border-left-color: #6a0606;
|
||||||
|
color: #2a1f15;
|
||||||
|
background: linear-gradient(90deg, rgba(200, 100, 100, 0.3) 0%, rgba(210, 200, 180, 0.7) 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.damage-button-section {
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: linear-gradient(180deg, rgba(100, 70, 60, 0.5) 0%, rgba(80, 60, 50, 0.6) 100%);
|
||||||
|
border-top: 1px solid rgba(139, 115, 85, 0.5);
|
||||||
|
|
||||||
|
.chat-card-button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: linear-gradient(to bottom, #6a0606 0%, #4a0404 100%);
|
||||||
|
border: 2px solid #8b7355;
|
||||||
|
border-radius: 2px;
|
||||||
|
color: #e8dcc4;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||||
|
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.9);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(to bottom, #8a0808 0%, #5a0505 100%);
|
||||||
|
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.2);
|
||||||
|
border-color: #c9a86a;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.predilection-reroll-section {
|
||||||
|
padding: 0.75rem;
|
||||||
|
background: linear-gradient(135deg, rgba(139, 115, 85, 0.3) 0%, rgba(100, 80, 60, 0.4) 100%);
|
||||||
|
border: 2px solid #8b7355;
|
||||||
|
border-radius: 2px;
|
||||||
|
margin: 0.5rem;
|
||||||
|
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
|
||||||
|
// Cacher toute icône de dé qui pourrait apparaître par erreur
|
||||||
|
.fa-dice {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.predilection-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
border-bottom: 1px solid rgba(139, 115, 85, 0.5);
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: #c9a86a;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.predilection-title {
|
||||||
|
color: #e8dcc4;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.predilection-results {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
|
||||||
|
.predilection-roll {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: linear-gradient(90deg, rgba(230, 220, 200, 0.4) 0%, rgba(210, 200, 180, 0.3) 100%);
|
||||||
|
border-radius: 2px;
|
||||||
|
border-left: 2px solid #8b7355;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0.5rem;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.kept {
|
||||||
|
background: linear-gradient(90deg, rgba(200, 220, 180, 0.6) 0%, rgba(180, 200, 160, 0.5) 100%);
|
||||||
|
border-left-color: #6b8e23;
|
||||||
|
box-shadow: 0 0 8px rgba(107, 142, 35, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.roll-label {
|
||||||
|
color: #2a1f15;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roll-value {
|
||||||
|
color: #2a1f15;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
i.fa-check-circle {
|
||||||
|
color: #6b8e23;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.predilection-kept {
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: linear-gradient(90deg, rgba(200, 220, 180, 0.7) 0%, rgba(180, 200, 160, 0.6) 100%);
|
||||||
|
border: 1px solid #6b8e23;
|
||||||
|
border-radius: 2px;
|
||||||
|
text-align: center;
|
||||||
|
color: #2a1f15;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: #6b8e23;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kept-label {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.predilection-section {
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: linear-gradient(180deg, rgba(100, 90, 70, 0.5) 0%, rgba(80, 70, 60, 0.6) 100%);
|
||||||
|
border-top: 1px solid rgba(139, 115, 85, 0.5);
|
||||||
|
|
||||||
|
.chat-card-button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: linear-gradient(to bottom, #5a4a3a 0%, #3a2a1a 100%);
|
||||||
|
border: 2px solid #8b7355;
|
||||||
|
border-radius: 2px;
|
||||||
|
color: #e8dcc4;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||||
|
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.9);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(to bottom, #6a5a4a 0%, #4a3a2a 100%);
|
||||||
|
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.2);
|
||||||
|
border-color: #c9a86a;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================ */
|
||||||
|
/* WASTELAND ITEM CHAT POSTS */
|
||||||
|
/* ============================================ */
|
||||||
|
|
||||||
|
.wasteland-chat-item {
|
||||||
|
background: linear-gradient(135deg, rgba(50, 40, 30, 0.95) 0%, rgba(30, 25, 20, 0.95) 100%);
|
||||||
|
border: 2px solid #8b7355;
|
||||||
|
border-radius: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
// Effet de texture sale/usée
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background:
|
||||||
|
repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
transparent,
|
||||||
|
transparent 2px,
|
||||||
|
rgba(0, 0, 0, 0.03) 2px,
|
||||||
|
rgba(0, 0, 0, 0.03) 4px
|
||||||
|
);
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-item-header {
|
||||||
|
background: linear-gradient(135deg, #3d2f1f 0%, #2a1f15 100%);
|
||||||
|
border-bottom: 2px solid #8b7355;
|
||||||
|
padding: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.625rem;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.4);
|
||||||
|
|
||||||
|
// Effet rouille sur le bord
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
bottom: -2px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 2px;
|
||||||
|
background: linear-gradient(90deg,
|
||||||
|
transparent 0%,
|
||||||
|
#6a0606 20%,
|
||||||
|
#8b7355 40%,
|
||||||
|
#6a0606 60%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-icon {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 2px solid #8b7355;
|
||||||
|
object-fit: cover;
|
||||||
|
flex-shrink: 0;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.6);
|
||||||
|
filter: contrast(1.1) saturate(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-info {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.item-name {
|
||||||
|
margin: 0;
|
||||||
|
color: #e8dcc4;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.9);
|
||||||
|
font-weight: bold;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-type {
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
color: #c9a86a;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.375rem;
|
||||||
|
text-transform: capitalize;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: #8b7355;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-item-body {
|
||||||
|
padding: 0.75rem;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
.item-description {
|
||||||
|
color: #e8dcc4;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-properties {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
border-top: 1px solid rgba(139, 115, 85, 0.3);
|
||||||
|
|
||||||
|
.property {
|
||||||
|
background: linear-gradient(90deg, rgba(230, 220, 200, 0.6) 0%, rgba(210, 200, 180, 0.5) 100%);
|
||||||
|
padding: 0.375rem 0.5rem;
|
||||||
|
border-radius: 1px;
|
||||||
|
border-left: 2px solid #8b7355;
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.property-label {
|
||||||
|
color: #2a1f15;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.property-value {
|
||||||
|
color: #2a1f15;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================ */
|
||||||
|
/* WASTELAND WELCOME MESSAGE */
|
||||||
|
/* ============================================ */
|
||||||
|
|
||||||
|
.wasteland-welcome-message {
|
||||||
|
background: linear-gradient(135deg, rgba(61, 47, 31, 0.15) 0%, rgba(42, 31, 21, 0.2) 100%);
|
||||||
|
border: 2px solid #6a0606;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0;
|
||||||
|
margin: 8px 0;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4),
|
||||||
|
inset 0 1px 0 rgba(201, 168, 106, 0.1);
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
|
||||||
|
.welcome-header {
|
||||||
|
background: linear-gradient(135deg, #6a0606 0%, #4a0404 100%);
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: 2px solid #c9a86a;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
|
||||||
|
.welcome-icon {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
color: #c9a86a;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
text-shadow: 0 0 10px rgba(201, 168, 106, 0.5);
|
||||||
|
animation: pulse 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-title {
|
||||||
|
margin: 4px 0 2px 0;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #e8dcc4;
|
||||||
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-subtitle {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #c9a86a;
|
||||||
|
font-style: italic;
|
||||||
|
margin-top: 2px;
|
||||||
|
line-height: 1.2;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-content {
|
||||||
|
padding: 12px;
|
||||||
|
background: linear-gradient(180deg, rgba(230, 220, 200, 0.9) 0%, rgba(210, 200, 180, 0.85) 100%);
|
||||||
|
|
||||||
|
.welcome-section {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.5);
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #c9a86a;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: linear-gradient(135deg, #6a0606 0%, #4a0404 100%);
|
||||||
|
color: #c9a86a;
|
||||||
|
border-radius: 50%;
|
||||||
|
font-size: 1rem;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
|
||||||
|
i {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-text {
|
||||||
|
flex: 1;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||||
|
|
||||||
|
strong {
|
||||||
|
display: block;
|
||||||
|
color: #3d2f1f;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: #2a1f15;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-link {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 4px;
|
||||||
|
color: #6a0606;
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #8b0606;
|
||||||
|
text-shadow: 0 0 4px rgba(106, 6, 6, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-footer {
|
||||||
|
background: linear-gradient(135deg, #4a0404 0%, #6a0606 100%);
|
||||||
|
padding: 8px;
|
||||||
|
text-align: center;
|
||||||
|
color: #c9a86a;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
border-top: 1px solid #8b7355;
|
||||||
|
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin: 0 8px;
|
||||||
|
opacity: 0.7;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.05);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
569
less/item-styles.less
Normal file
569
less/item-styles.less
Normal file
@@ -0,0 +1,569 @@
|
|||||||
|
/* ==================== Item Sheet Styles ==================== */
|
||||||
|
|
||||||
|
/* Item header with image and name */
|
||||||
|
.fvtt-wasteland.item {
|
||||||
|
/* Background pour toute la fiche d'item */
|
||||||
|
background: url("../assets/ui/pc_sheet_bg.webp") repeat;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
/* AppV2 - Remove window content padding */
|
||||||
|
.window-content {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AppV2 - Main section structure */
|
||||||
|
section {
|
||||||
|
background: url("../assets/ui/pc_sheet_bg.webp") repeat-y;
|
||||||
|
color: black;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AppV2 Item Sheets - Disabled inputs readability */
|
||||||
|
input:disabled,
|
||||||
|
select:disabled {
|
||||||
|
color: #000000;
|
||||||
|
opacity: 0.8;
|
||||||
|
background-color: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inputs and selects styling */
|
||||||
|
input[type="text"],
|
||||||
|
input[type="number"],
|
||||||
|
select {
|
||||||
|
color: #000000;
|
||||||
|
background-color: rgba(255, 255, 255, 0.7);
|
||||||
|
border: 1px solid #999999;
|
||||||
|
margin: 0;
|
||||||
|
padding: 2px 4px;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
margin: 0;
|
||||||
|
padding: 2px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
margin: 0 4px;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
border-bottom: 1px solid #999;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: url("../assets/ui/pc_sheet_bg.webp") repeat;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-sheet-img {
|
||||||
|
flex: 0 0 100px;
|
||||||
|
height: 100px;
|
||||||
|
border: 2px solid #999;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-sheet-title {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25rem;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
border-bottom: none;
|
||||||
|
|
||||||
|
input {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-subtitle {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #666;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navigation tabs - Modern style */
|
||||||
|
nav.tabs {
|
||||||
|
display: flex;
|
||||||
|
border-bottom: 2px solid #403f3e;
|
||||||
|
margin: 0;
|
||||||
|
padding: 4px 8px;
|
||||||
|
background: linear-gradient(to bottom, #2a2520 0%, #1a1510 100%);
|
||||||
|
flex: 0 0 auto;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
a.item {
|
||||||
|
padding: 8px 16px;
|
||||||
|
color: rgba(218, 218, 218, 0.85);
|
||||||
|
text-decoration: none;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 6px 6px 0 0;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: normal;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
background: rgba(64, 63, 62, 0.3);
|
||||||
|
min-width: 80px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
i {
|
||||||
|
display: none; // Hide icons for cleaner look
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(74, 4, 4, 0.4);
|
||||||
|
color: #f5f5f5;
|
||||||
|
border-color: rgba(218, 218, 218, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: linear-gradient(to bottom, #4a0404 0%, #3a0303 100%);
|
||||||
|
border: 1px solid transparent;
|
||||||
|
color: #f5f5f5;
|
||||||
|
font-weight: bold;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tab content */
|
||||||
|
.tab {
|
||||||
|
display: none;
|
||||||
|
padding: 8px 12px;
|
||||||
|
overflow-y: auto;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sheet body - scrollable content */
|
||||||
|
.sheet-body {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
&[data-tab] {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dans l'onglet details, les form-group sont horizontaux par défaut */
|
||||||
|
&[data-tab="details"] {
|
||||||
|
.form-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #464331;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-width: 160px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"],
|
||||||
|
input[type="number"],
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checkbox avec label après (pas avant) */
|
||||||
|
&:has(input[type="checkbox"]:first-child) {
|
||||||
|
label {
|
||||||
|
min-width: auto;
|
||||||
|
flex: 1;
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
order: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exception: quand le label contient lui-même le checkbox */
|
||||||
|
label:has(input[type="checkbox"]) {
|
||||||
|
min-width: auto;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pour les sections avec grilles, garder le comportement vertical */
|
||||||
|
.grid .form-group {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0.25rem;
|
||||||
|
|
||||||
|
label {
|
||||||
|
min-width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form groups - comportement par défaut pour autres onglets */
|
||||||
|
.form-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #464331;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.horizontal {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
label {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select, textarea {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grid layouts */
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
|
||||||
|
&.grid-2col {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.grid-3col {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.grid-4col {
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Editor content */
|
||||||
|
.editor-content {
|
||||||
|
min-height: 200px;
|
||||||
|
border: 1px solid #999;
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Actions buttons */
|
||||||
|
.item-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
border-top: 1px solid #999;
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
background: rgba(74, 4, 4, 0.8);
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #000;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
transition: all 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(74, 4, 4, 1);
|
||||||
|
box-shadow: 0 0 8px rgba(74, 4, 4, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rollable elements */
|
||||||
|
.rollable {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #ff6600;
|
||||||
|
text-shadow: 0 0 8px rgba(255, 102, 0, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Item-specific sections */
|
||||||
|
.item-details {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
|
||||||
|
.detail-section {
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
border: 1px solid #999;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0 0 0.5rem 0;
|
||||||
|
padding-bottom: 0.25rem;
|
||||||
|
border-bottom: 1px solid #999;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: #2a1510;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Specific item type styles */
|
||||||
|
.fvtt-wasteland.item {
|
||||||
|
&.arme-content,
|
||||||
|
&.bouclier-content {
|
||||||
|
.weapon-stats {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
.stat-box {
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: rgba(255, 255, 255, 0.5);
|
||||||
|
border: 1px solid #999;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.competence-content {
|
||||||
|
.predilections-container {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
|
||||||
|
.no-predilections {
|
||||||
|
text-align: center;
|
||||||
|
font-style: italic;
|
||||||
|
color: #999;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.predilections-list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 0.75rem 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
.predilection-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: rgba(42, 37, 32, 0.3);
|
||||||
|
border: 1px solid rgba(106, 6, 6, 0.3);
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(42, 37, 32, 0.5);
|
||||||
|
border-color: rgba(106, 6, 6, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.predilection-main {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.predilection-name {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.375rem 0.5rem;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.3);
|
||||||
|
border-radius: 3px;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
font-family: inherit;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: #999;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #6a0606;
|
||||||
|
box-shadow: 0 0 0 2px rgba(106, 6, 6, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.predilection-controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
.predilection-used {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.375rem;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: rgba(218, 218, 218, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover span {
|
||||||
|
color: rgba(218, 218, 218, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.predilection-delete {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
padding: 0;
|
||||||
|
background: rgba(106, 6, 6, 0.6);
|
||||||
|
border: 1px solid rgba(106, 6, 6, 0.8);
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(106, 6, 6, 0.9);
|
||||||
|
border-color: #6a0606;
|
||||||
|
transform: scale(1.05);
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-predilection-btn {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
background: linear-gradient(to bottom, #4a0404 0%, #3a0303 100%);
|
||||||
|
border: 1px solid #6a0606;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: rgba(218, 218, 218, 0.95);
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(to bottom, #5a0505 0%, #4a0404 100%);
|
||||||
|
border-color: #8a0808;
|
||||||
|
color: #fff;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
311
less/roll-dialog-styles.less
Normal file
311
less/roll-dialog-styles.less
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
/* ============================================ */
|
||||||
|
/* WASTELAND ROLL DIALOG STYLES */
|
||||||
|
/* ============================================ */
|
||||||
|
|
||||||
|
.wasteland-roll-dialog {
|
||||||
|
background: url("../assets/ui/pc_sheet_bg.webp") repeat;
|
||||||
|
|
||||||
|
.window-content {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: linear-gradient(to bottom, #4a0404 0%, #3a0303 100%);
|
||||||
|
border-bottom: 2px solid #6a0606;
|
||||||
|
margin: -0.5rem -0.5rem 0.5rem -0.5rem;
|
||||||
|
|
||||||
|
.actor-icon {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border: 2px solid #6a0606;
|
||||||
|
border-radius: 4px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-title {
|
||||||
|
flex: 1;
|
||||||
|
color: #f5f5f5;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0 0 0.15rem 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.competence-name {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
font-style: italic;
|
||||||
|
|
||||||
|
.attribut-info {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-content {
|
||||||
|
padding: 0 0.5rem 0.5rem 0.5rem;
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 0.4rem;
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #2a1510;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
select,
|
||||||
|
input[type="number"] {
|
||||||
|
width: 100%;
|
||||||
|
background: rgba(255, 255, 255, 0.5);
|
||||||
|
border: 1px solid #6a0606;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0.3rem 0.4rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #1a1510;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
border-color: #aa0a0a;
|
||||||
|
box-shadow: 0 0 4px rgba(170, 10, 10, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modifiers-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 0.4rem;
|
||||||
|
margin-bottom: 0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attributes-section {
|
||||||
|
background: rgba(106, 6, 6, 0.1);
|
||||||
|
border: 1px solid #6a0606;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.5rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
|
label {
|
||||||
|
color: #6a0606;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.special-option {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: rgba(106, 6, 6, 0.05);
|
||||||
|
border: 2px solid #6a0606;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
.checkbox-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
margin: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.highlight {
|
||||||
|
span {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #6a0606;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
cursor: pointer;
|
||||||
|
accent-color: #6a0606;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #2a1510;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Weapon Section */
|
||||||
|
.weapon-section {
|
||||||
|
background: rgba(139, 101, 8, 0.1);
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid rgba(139, 101, 8, 0.4);
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
|
.weapon-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.4rem 0.5rem;
|
||||||
|
background: rgba(139, 101, 8, 0.15);
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
|
.weapon-label {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #2a1510;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weapon-bonus {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #8b0000;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.defense-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.4rem 0.5rem;
|
||||||
|
background: rgba(0, 100, 0, 0.1);
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
|
.defense-label {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #2a1510;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.defense-value {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #006400;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Combat Modifiers */
|
||||||
|
.combat-modifiers,
|
||||||
|
.ranged-combat-section {
|
||||||
|
background: rgba(139, 69, 19, 0.1);
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid rgba(139, 69, 19, 0.4);
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin: 0 0 0.5rem 0;
|
||||||
|
color: #2a1510;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
padding: 0.3rem 0.4rem;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
transition: background 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: auto;
|
||||||
|
margin: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
accent-color: #8b4513;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #2a1510;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-message {
|
||||||
|
padding: 0.4rem 0.6rem;
|
||||||
|
background: rgba(201, 168, 106, 0.2);
|
||||||
|
border-left: 3px solid rgba(201, 168, 106, 0.8);
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #2a1510;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modifiers-columns {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 0.3rem 0.6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Styles pour les boutons du dialog
|
||||||
|
.dialog-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.4rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-top: 1px solid #6a0606;
|
||||||
|
margin: 0.5rem -0.5rem -0.5rem -0.5rem;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
background: linear-gradient(to bottom, #4a0404 0%, #3a0303 100%);
|
||||||
|
border: 1px solid #6a0606;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: #f5f5f5;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: "Charlemagne", serif;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(to bottom, #5a0505 0%, #4a0404 100%);
|
||||||
|
box-shadow: 0 0 6px rgba(106, 6, 6, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.default {
|
||||||
|
border-width: 2px;
|
||||||
|
border-color: #aa0a0a;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 0.4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1365
less/simple-converted.less
Normal file
1365
less/simple-converted.less
Normal file
File diff suppressed because it is too large
Load Diff
8
less/wasteland.less
Normal file
8
less/wasteland.less
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// Main LESS file for Wasteland system
|
||||||
|
// Importing base styles and component-specific styles
|
||||||
|
|
||||||
|
@import "simple-converted";
|
||||||
|
@import "item-styles";
|
||||||
|
@import "actor-styles";
|
||||||
|
@import "roll-dialog-styles";
|
||||||
|
@import "chat-styles";
|
||||||
27
modules/applications/sheets/_module.mjs
Normal file
27
modules/applications/sheets/_module.mjs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Index des applications AppV2 pour Wasteland
|
||||||
|
* Ce fichier centralise tous les exports des applications
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Applications de feuilles d'acteurs
|
||||||
|
export { default as WastelandPersonnageSheet } from './wasteland-personnage-sheet.mjs';
|
||||||
|
export { default as WastelandCreatureSheet } from './wasteland-creature-sheet.mjs';
|
||||||
|
|
||||||
|
// Applications de feuilles d'items
|
||||||
|
export { default as WastelandArmeSheet } from './wasteland-arme-sheet.mjs';
|
||||||
|
export { default as WastelandArtifexSheet } from './wasteland-artifex-sheet.mjs';
|
||||||
|
export { default as WastelandBouclierSheet } from './wasteland-bouclier-sheet.mjs';
|
||||||
|
export { default as WastelandCapaciteSheet } from './wasteland-capacite-sheet.mjs';
|
||||||
|
export { default as WastelandCharmeSheet } from './wasteland-charme-sheet.mjs';
|
||||||
|
export { default as WastelandCompetenceSheet } from './wasteland-competence-sheet.mjs';
|
||||||
|
export { default as WastelandDonSheet } from './wasteland-don-sheet.mjs';
|
||||||
|
export { default as WastelandEquipementSheet } from './wasteland-equipement-sheet.mjs';
|
||||||
|
export { default as WastelandHeritageSheet } from './wasteland-heritage-sheet.mjs';
|
||||||
|
export { default as WastelandHubrisSheet } from './wasteland-hubris-sheet.mjs';
|
||||||
|
export { default as WastelandMetierSheet } from './wasteland-metier-sheet.mjs';
|
||||||
|
export { default as WastelandMonnaieSheet } from './wasteland-monnaie-sheet.mjs';
|
||||||
|
export { default as WastelandMutationSheet } from './wasteland-mutation-sheet.mjs';
|
||||||
|
export { default as WastelandOrigineSheet } from './wasteland-origine-sheet.mjs';
|
||||||
|
export { default as WastelandPeupleSheet } from './wasteland-peuple-sheet.mjs';
|
||||||
|
export { default as WastelandPouvoirSheet } from './wasteland-pouvoir-sheet.mjs';
|
||||||
|
export { default as WastelandProtectionSheet } from './wasteland-protection-sheet.mjs';
|
||||||
382
modules/applications/sheets/base-actor-sheet.mjs
Normal file
382
modules/applications/sheets/base-actor-sheet.mjs
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||||
|
|
||||||
|
import { WastelandUtility } from "../../wasteland-utility.js"
|
||||||
|
|
||||||
|
export default class WastelandActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
|
||||||
|
/**
|
||||||
|
* Different sheet modes.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
|
||||||
|
|
||||||
|
constructor(options = {}) {
|
||||||
|
super(options)
|
||||||
|
this.#dragDrop = this.#createDragDropHandlers()
|
||||||
|
this._sheetMode = this.constructor.SHEET_MODES.PLAY
|
||||||
|
}
|
||||||
|
|
||||||
|
#dragDrop
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["fvtt-wasteland", "sheet", "actor"],
|
||||||
|
position: {
|
||||||
|
width: 650,
|
||||||
|
height: 720,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
submitOnChange: true,
|
||||||
|
closeOnSubmit: false,
|
||||||
|
},
|
||||||
|
window: {
|
||||||
|
resizable: true,
|
||||||
|
},
|
||||||
|
tabs: [
|
||||||
|
{
|
||||||
|
navSelector: 'nav[data-group="primary"]',
|
||||||
|
contentSelector: "section.sheet-body",
|
||||||
|
initial: "stats",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
|
||||||
|
actions: {
|
||||||
|
editImage: WastelandActorSheet.#onEditImage,
|
||||||
|
toggleSheet: WastelandActorSheet.#onToggleSheet,
|
||||||
|
editItem: WastelandActorSheet.#onEditItem,
|
||||||
|
deleteItem: WastelandActorSheet.#onDeleteItem,
|
||||||
|
createItem: WastelandActorSheet.#onCreateItem,
|
||||||
|
equipItem: WastelandActorSheet.#onEquipItem,
|
||||||
|
modifyQuantity: WastelandActorSheet.#onModifyQuantity,
|
||||||
|
incDecSante: WastelandActorSheet.#onIncDecSante,
|
||||||
|
rollAttribut: WastelandActorSheet.#onRollAttribut,
|
||||||
|
rollCompetence: WastelandActorSheet.#onRollCompetence,
|
||||||
|
rollCharme: WastelandActorSheet.#onRollCharme,
|
||||||
|
rollPouvoir: WastelandActorSheet.#onRollPouvoir,
|
||||||
|
rollArmeOffensif: WastelandActorSheet.#onRollArmeOffensif,
|
||||||
|
rollArmeDegats: WastelandActorSheet.#onRollArmeDegats,
|
||||||
|
resetPredilections: WastelandActorSheet.#onResetPredilections,
|
||||||
|
rollAssommer: WastelandActorSheet.#onRollAssommer,
|
||||||
|
rollFuir: WastelandActorSheet.#onRollFuir,
|
||||||
|
rollImmobiliser: WastelandActorSheet.#onRollImmobiliser,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the sheet currently in 'Play' mode?
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
get isPlayMode() {
|
||||||
|
if (this._sheetMode === undefined) this._sheetMode = this.constructor.SHEET_MODES.PLAY
|
||||||
|
return this._sheetMode === this.constructor.SHEET_MODES.PLAY
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the sheet currently in 'Edit' mode?
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
get isEditMode() {
|
||||||
|
if (this._sheetMode === undefined) this._sheetMode = this.constructor.SHEET_MODES.PLAY
|
||||||
|
return this._sheetMode === this.constructor.SHEET_MODES.EDIT
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tab groups state
|
||||||
|
* @type {object}
|
||||||
|
*/
|
||||||
|
tabGroups = { primary: "stats" }
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext() {
|
||||||
|
const actor = this.document
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
actor: actor,
|
||||||
|
system: actor.system,
|
||||||
|
source: actor.toObject(),
|
||||||
|
fields: actor.schema.fields,
|
||||||
|
systemFields: actor.system.schema.fields,
|
||||||
|
isEditable: this.isEditable,
|
||||||
|
isEditMode: this.isEditMode,
|
||||||
|
isPlayMode: this.isPlayMode,
|
||||||
|
isGM: game.user.isGM,
|
||||||
|
config: game.system.wasteland.config,
|
||||||
|
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.description || "", { async: true }),
|
||||||
|
enrichedComportement: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.comportement || "", { async: true }),
|
||||||
|
enrichedHabitat: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.habitat || "", { async: true }),
|
||||||
|
}
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
_onRender(context, options) {
|
||||||
|
super._onRender(context, options)
|
||||||
|
this.#dragDrop.forEach((d) => d.bind(this.element))
|
||||||
|
|
||||||
|
// Handle edit-item-data changes
|
||||||
|
this.element.querySelectorAll('.edit-item-data').forEach(element => {
|
||||||
|
element.addEventListener('change', async (event) => {
|
||||||
|
const target = event.currentTarget
|
||||||
|
const itemElement = target.closest('[data-item-id]')
|
||||||
|
if (!itemElement) return
|
||||||
|
|
||||||
|
const itemId = itemElement.dataset.itemId
|
||||||
|
const itemType = itemElement.dataset.itemType
|
||||||
|
const itemField = target.dataset.itemField
|
||||||
|
const dataType = target.dataset.dtype
|
||||||
|
const value = target.value
|
||||||
|
|
||||||
|
await this.document.editItemField(itemId, itemType, itemField, dataType, value)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Activate tab navigation manually
|
||||||
|
const nav = this.element.querySelector('nav.tabs[data-group]')
|
||||||
|
if (nav) {
|
||||||
|
const group = nav.dataset.group
|
||||||
|
// Activate the current tab
|
||||||
|
const activeTab = this.tabGroups[group] || "stats"
|
||||||
|
nav.querySelectorAll('[data-tab]').forEach(link => {
|
||||||
|
const tab = link.dataset.tab
|
||||||
|
link.classList.toggle('active', tab === activeTab)
|
||||||
|
link.addEventListener('click', (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
this.tabGroups[group] = tab
|
||||||
|
this.render()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Show/hide tab content
|
||||||
|
this.element.querySelectorAll('[data-group="' + group + '"][data-tab]').forEach(content => {
|
||||||
|
content.classList.toggle('active', content.dataset.tab === activeTab)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #region Drag-and-Drop Workflow
|
||||||
|
/**
|
||||||
|
* Create drag-and-drop workflow handlers for this Application
|
||||||
|
*/
|
||||||
|
#createDragDropHandlers() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// #region Actions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle editing the actor image
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
*/
|
||||||
|
static async #onEditImage(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
const sheet = this
|
||||||
|
const filePicker = new FilePicker({
|
||||||
|
type: "image",
|
||||||
|
current: sheet.document.img,
|
||||||
|
callback: (path) => {
|
||||||
|
sheet.document.update({ img: path })
|
||||||
|
},
|
||||||
|
})
|
||||||
|
filePicker.browse()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle toggling the sheet mode
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
*/
|
||||||
|
static async #onToggleSheet(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
const sheet = this
|
||||||
|
sheet._sheetMode = sheet._sheetMode === sheet.constructor.SHEET_MODES.PLAY ? sheet.constructor.SHEET_MODES.EDIT : sheet.constructor.SHEET_MODES.PLAY
|
||||||
|
sheet.render()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle editing an item
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onEditItem(event, target) {
|
||||||
|
const li = target.closest(".item")
|
||||||
|
const itemId = li?.dataset.itemId
|
||||||
|
if (!itemId) return
|
||||||
|
const item = this.actor.items.get(itemId)
|
||||||
|
if (item) item.sheet.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle deleting an item
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onDeleteItem(event, target) {
|
||||||
|
const li = target.closest(".item")
|
||||||
|
await WastelandUtility.confirmDelete(this, li)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle creating an item
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onCreateItem(event, target) {
|
||||||
|
const itemType = target.dataset.type
|
||||||
|
await this.actor.createEmbeddedDocuments("Item", [{ name: `Nouveau ${itemType}`, type: itemType }], { renderSheet: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle equipping an item
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onEquipItem(event, target) {
|
||||||
|
const li = target.closest(".item")
|
||||||
|
const itemId = li?.dataset.itemId
|
||||||
|
if (!itemId) return
|
||||||
|
await this.actor.equipItem(itemId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle modifying item quantity
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onModifyQuantity(event, target) {
|
||||||
|
const li = target.closest(".item")
|
||||||
|
const itemId = li?.dataset.itemId
|
||||||
|
if (!itemId) return
|
||||||
|
|
||||||
|
const item = this.actor.items.get(itemId)
|
||||||
|
if (!item) return
|
||||||
|
|
||||||
|
const qty = parseInt(target.dataset.qty) || 0
|
||||||
|
const currentQty = item.system.quantite || 0
|
||||||
|
const newQty = Math.max(0, currentQty + qty)
|
||||||
|
|
||||||
|
await item.update({ 'system.quantite': newQty })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle modifying santé/psyché
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onIncDecSante(event, target) {
|
||||||
|
const field = target.dataset.field
|
||||||
|
const value = parseInt(target.dataset.value) || 0
|
||||||
|
|
||||||
|
if (field === 'psyche') {
|
||||||
|
await this.actor.update({ 'system.psyche.value': this.actor.system.psyche.value + value })
|
||||||
|
} else if (field === 'nonletaux') {
|
||||||
|
await this.actor.update({ 'system.sante.nonletaux': this.actor.system.sante.nonletaux + value })
|
||||||
|
} else if (field === 'letaux') {
|
||||||
|
await this.actor.update({ 'system.sante.letaux': this.actor.system.sante.letaux + value })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle rolling an attribute
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onRollAttribut(event, target) {
|
||||||
|
const attrKey = target.dataset.attrKey
|
||||||
|
await this.actor.rollAttribut(attrKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle rolling a competence
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onRollCompetence(event, target) {
|
||||||
|
const li = target.closest(".item")
|
||||||
|
const itemId = li?.dataset.itemId
|
||||||
|
const attrKey = target.dataset.attrKey
|
||||||
|
if (!itemId) return
|
||||||
|
await this.actor.rollCompetence(attrKey, itemId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle rolling a charme
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onRollCharme(event, target) {
|
||||||
|
const li = target.closest(".item")
|
||||||
|
const itemId = li?.dataset.itemId
|
||||||
|
if (!itemId) return
|
||||||
|
await this.actor.rollCharme(itemId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle rolling a pouvoir
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onRollPouvoir(event, target) {
|
||||||
|
const li = target.closest(".item")
|
||||||
|
const itemId = li?.dataset.itemId
|
||||||
|
if (!itemId) return
|
||||||
|
await this.actor.rollPouvoir(itemId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle rolling weapon attack
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onRollArmeOffensif(event, target) {
|
||||||
|
const li = target.closest(".item")
|
||||||
|
const itemId = li?.dataset.itemId
|
||||||
|
if (!itemId) return
|
||||||
|
await this.actor.rollArmeOffensif(itemId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle rolling weapon damage
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onRollArmeDegats(event, target) {
|
||||||
|
const li = target.closest(".item")
|
||||||
|
const itemId = li?.dataset.itemId
|
||||||
|
if (!itemId) return
|
||||||
|
await this.actor.rollArmeDegats(itemId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle resetting all predilections
|
||||||
|
* @param {Event} event - The originating click event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onResetPredilections(event, target) {
|
||||||
|
await this.actor.resetAllPredilections()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle Assommer roll
|
||||||
|
* @param {Event} event - The originating click event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onRollAssommer(event, target) {
|
||||||
|
await this.actor.rollAssommer()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle Fuir roll
|
||||||
|
* @param {Event} event - The originating click event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onRollFuir(event, target) {
|
||||||
|
await this.actor.rollFuir()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle Immobiliser roll
|
||||||
|
* @param {Event} event - The originating click event
|
||||||
|
* @param {HTMLElement} target - The target element
|
||||||
|
*/
|
||||||
|
static async #onRollImmobiliser(event, target) {
|
||||||
|
await this.actor.rollImmobiliser()
|
||||||
|
}
|
||||||
|
}
|
||||||
158
modules/applications/sheets/base-item-sheet.mjs
Normal file
158
modules/applications/sheets/base-item-sheet.mjs
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||||
|
|
||||||
|
export default class WastelandItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
|
||||||
|
constructor(options = {}) {
|
||||||
|
super(options)
|
||||||
|
this.#dragDrop = this.#createDragDropHandlers()
|
||||||
|
}
|
||||||
|
|
||||||
|
#dragDrop
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["fvtt-wasteland", "item"],
|
||||||
|
position: {
|
||||||
|
width: 620,
|
||||||
|
height: 600,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
submitOnChange: true,
|
||||||
|
},
|
||||||
|
window: {
|
||||||
|
resizable: true,
|
||||||
|
},
|
||||||
|
tabs: [
|
||||||
|
{
|
||||||
|
navSelector: 'nav[data-group="primary"]',
|
||||||
|
contentSelector: "section.sheet-body",
|
||||||
|
initial: "description",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
dragDrop: [{ dragSelector: "[data-drag]", dropSelector: null }],
|
||||||
|
actions: {
|
||||||
|
editImage: WastelandItemSheet.#onEditImage,
|
||||||
|
postItem: WastelandItemSheet.#onPostItem,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tab groups state
|
||||||
|
* @type {object}
|
||||||
|
*/
|
||||||
|
tabGroups = { primary: "description" }
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = {
|
||||||
|
fields: this.document.schema.fields,
|
||||||
|
systemFields: this.document.system.schema.fields,
|
||||||
|
item: this.document,
|
||||||
|
system: this.document.system,
|
||||||
|
source: this.document.toObject(),
|
||||||
|
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true }),
|
||||||
|
isEditMode: true,
|
||||||
|
isEditable: this.isEditable,
|
||||||
|
isGM: game.user.isGM,
|
||||||
|
config: game.system.wasteland.config,
|
||||||
|
}
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
_onRender(context, options) {
|
||||||
|
super._onRender(context, options)
|
||||||
|
this.#dragDrop.forEach((d) => d.bind(this.element))
|
||||||
|
|
||||||
|
// Activate tab navigation manually
|
||||||
|
const nav = this.element.querySelector('nav.tabs[data-group]')
|
||||||
|
if (nav) {
|
||||||
|
const group = nav.dataset.group
|
||||||
|
// Activate the current tab
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Show/hide tab content
|
||||||
|
this.element.querySelectorAll('[data-group="' + group + '"][data-tab]').forEach(content => {
|
||||||
|
content.classList.toggle('active', content.dataset.tab === activeTab)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #region Drag-and-Drop Workflow
|
||||||
|
/**
|
||||||
|
* Create drag-and-drop workflow handlers for this Application
|
||||||
|
*/
|
||||||
|
#createDragDropHandlers() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// #region Actions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle editing the item image
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
*/
|
||||||
|
static async #onEditImage(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
const filePicker = new FilePicker({
|
||||||
|
type: "image",
|
||||||
|
current: this.document.img,
|
||||||
|
callback: (path) => {
|
||||||
|
this.document.update({ img: path })
|
||||||
|
},
|
||||||
|
})
|
||||||
|
filePicker.browse()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle posting the item to chat
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
*/
|
||||||
|
static async #onPostItem(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
// Prepare chat data
|
||||||
|
const chatData = {
|
||||||
|
name: this.document.name,
|
||||||
|
img: this.document.img,
|
||||||
|
type: this.document.type,
|
||||||
|
system: this.document.system,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add actor reference if item is owned
|
||||||
|
if (this.document.actor) {
|
||||||
|
chatData.actor = { id: this.document.actor.id }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't post any image for the item if the default image is used
|
||||||
|
if (chatData.img && chatData.img.includes("/blank.png")) {
|
||||||
|
chatData.img = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON object for easy creation
|
||||||
|
chatData.jsondata = JSON.stringify({
|
||||||
|
compendium: "postedItem",
|
||||||
|
payload: chatData,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Render the chat card template
|
||||||
|
const html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-wasteland/templates/post-item.hbs', chatData)
|
||||||
|
|
||||||
|
// Create the chat message
|
||||||
|
const chatOptions = {
|
||||||
|
user: game.user.id,
|
||||||
|
content: html,
|
||||||
|
speaker: ChatMessage.getSpeaker({ actor: this.document.actor })
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatMessage.create(chatOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
49
modules/applications/sheets/wasteland-arme-sheet.mjs
Normal file
49
modules/applications/sheets/wasteland-arme-sheet.mjs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandArmeSheet extends WastelandItemSheet {
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["arme"],
|
||||||
|
position: {
|
||||||
|
width: 620,
|
||||||
|
},
|
||||||
|
window: {
|
||||||
|
contentClasses: ["arme-content"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/fvtt-wasteland/templates/item-arme-sheet.hbs",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
tabGroups = {
|
||||||
|
primary: "details",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare an array of form header tabs.
|
||||||
|
* @returns {Record<string, Partial<ApplicationTab>>}
|
||||||
|
*/
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
details: { id: "details", group: "primary", label: "Détails" },
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
33
modules/applications/sheets/wasteland-artifex-sheet.mjs
Normal file
33
modules/applications/sheets/wasteland-artifex-sheet.mjs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandArtifexSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["artifex"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["artifex-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-artifex-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "details" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
details: { id: "details", group: "primary", label: "Détails" },
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
33
modules/applications/sheets/wasteland-bouclier-sheet.mjs
Normal file
33
modules/applications/sheets/wasteland-bouclier-sheet.mjs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandBouclierSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["bouclier"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["bouclier-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-bouclier-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "details" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
details: { id: "details", group: "primary", label: "Détails" },
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
32
modules/applications/sheets/wasteland-capacite-sheet.mjs
Normal file
32
modules/applications/sheets/wasteland-capacite-sheet.mjs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandCapaciteSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["capacite"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["capacite-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-capacite-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "description" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
33
modules/applications/sheets/wasteland-charme-sheet.mjs
Normal file
33
modules/applications/sheets/wasteland-charme-sheet.mjs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandCharmeSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["charme"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["charme-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-charme-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "details" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
details: { id: "details", group: "primary", label: "Détails" },
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
72
modules/applications/sheets/wasteland-competence-sheet.mjs
Normal file
72
modules/applications/sheets/wasteland-competence-sheet.mjs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandCompetenceSheet extends WastelandItemSheet {
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["competence"],
|
||||||
|
position: {
|
||||||
|
width: 620,
|
||||||
|
},
|
||||||
|
window: {
|
||||||
|
contentClasses: ["competence-content"],
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
"add-predilection": this.#onAddPredilection,
|
||||||
|
"delete-predilection": this.#onDeletePredilection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/fvtt-wasteland/templates/item-competence-sheet.hbs",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
tabGroups = {
|
||||||
|
primary: "details",
|
||||||
|
}
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
details: { id: "details", group: "primary", label: "Détails" },
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle adding a new predilection
|
||||||
|
* @param {PointerEvent} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The button element
|
||||||
|
*/
|
||||||
|
static async #onAddPredilection(event, target) {
|
||||||
|
const predilections = foundry.utils.duplicate(this.document.system.predilections)
|
||||||
|
predilections.push({ name: "Nouvelle prédilection", used: false })
|
||||||
|
await this.document.update({ "system.predilections": predilections })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle deleting a predilection
|
||||||
|
* @param {PointerEvent} event - The triggering event
|
||||||
|
* @param {HTMLElement} target - The delete button element
|
||||||
|
*/
|
||||||
|
static async #onDeletePredilection(event, target) {
|
||||||
|
const index = parseInt(target.dataset.index)
|
||||||
|
const predilections = foundry.utils.duplicate(this.document.system.predilections)
|
||||||
|
predilections.splice(index, 1)
|
||||||
|
await this.document.update({ "system.predilections": predilections })
|
||||||
|
}
|
||||||
|
}
|
||||||
40
modules/applications/sheets/wasteland-creature-sheet.mjs
Normal file
40
modules/applications/sheets/wasteland-creature-sheet.mjs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import WastelandActorSheet from "./base-actor-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandCreatureSheet extends WastelandActorSheet {
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
...super.DEFAULT_OPTIONS,
|
||||||
|
classes: [...super.DEFAULT_OPTIONS.classes, "creature"],
|
||||||
|
window: {
|
||||||
|
...super.DEFAULT_OPTIONS.window,
|
||||||
|
title: "Feuille de Créature",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
sheet: {
|
||||||
|
template: "systems/fvtt-wasteland/templates/actor-creature-sheet.hbs",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
tabGroups = {
|
||||||
|
primary: "stats",
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
const actor = this.document
|
||||||
|
|
||||||
|
// Add creature-specific data
|
||||||
|
context.skills = actor.getSkills()
|
||||||
|
context.armes = foundry.utils.duplicate(actor.getWeapons())
|
||||||
|
context.protections = foundry.utils.duplicate(actor.getArmors())
|
||||||
|
context.capacites = foundry.utils.duplicate(actor.getCapacites())
|
||||||
|
context.combat = actor.getCombatValues()
|
||||||
|
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
32
modules/applications/sheets/wasteland-don-sheet.mjs
Normal file
32
modules/applications/sheets/wasteland-don-sheet.mjs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandDonSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["don"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["don-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-don-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "description" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
33
modules/applications/sheets/wasteland-equipement-sheet.mjs
Normal file
33
modules/applications/sheets/wasteland-equipement-sheet.mjs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandEquipementSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["equipement"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["equipement-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-equipement-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "details" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
details: { id: "details", group: "primary", label: "Détails" },
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
32
modules/applications/sheets/wasteland-heritage-sheet.mjs
Normal file
32
modules/applications/sheets/wasteland-heritage-sheet.mjs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandHeritageSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["heritage"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["heritage-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-heritage-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "description" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
33
modules/applications/sheets/wasteland-hubris-sheet.mjs
Normal file
33
modules/applications/sheets/wasteland-hubris-sheet.mjs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandHubrisSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["hubris"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["hubris-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-hubris-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "details" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
details: { id: "details", group: "primary", label: "Détails" },
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
32
modules/applications/sheets/wasteland-metier-sheet.mjs
Normal file
32
modules/applications/sheets/wasteland-metier-sheet.mjs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandMetierSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["metier"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["metier-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-metier-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "description" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
33
modules/applications/sheets/wasteland-monnaie-sheet.mjs
Normal file
33
modules/applications/sheets/wasteland-monnaie-sheet.mjs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandMonnaieSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["monnaie"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["monnaie-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-monnaie-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "details" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
details: { id: "details", group: "primary", label: "Détails" },
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
32
modules/applications/sheets/wasteland-mutation-sheet.mjs
Normal file
32
modules/applications/sheets/wasteland-mutation-sheet.mjs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandMutationSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["mutation"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["mutation-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-mutation-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "description" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
32
modules/applications/sheets/wasteland-origine-sheet.mjs
Normal file
32
modules/applications/sheets/wasteland-origine-sheet.mjs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandOrigineSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["origine"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["origine-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-origine-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "description" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
59
modules/applications/sheets/wasteland-personnage-sheet.mjs
Normal file
59
modules/applications/sheets/wasteland-personnage-sheet.mjs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import WastelandActorSheet from "./base-actor-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandPersonnageSheet extends WastelandActorSheet {
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
...super.DEFAULT_OPTIONS,
|
||||||
|
classes: [...super.DEFAULT_OPTIONS.classes, "personnage"],
|
||||||
|
window: {
|
||||||
|
...super.DEFAULT_OPTIONS.window,
|
||||||
|
title: "Feuille de Personnage",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
sheet: {
|
||||||
|
template: "systems/fvtt-wasteland/templates/actor-personnage-sheet.hbs",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
tabGroups = {
|
||||||
|
primary: "stats",
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
const actor = this.document
|
||||||
|
|
||||||
|
// Add personnage-specific data
|
||||||
|
context.skills = actor.getSkills()
|
||||||
|
context.armes = foundry.utils.duplicate(actor.getWeapons())
|
||||||
|
context.protections = foundry.utils.duplicate(actor.getArmors())
|
||||||
|
context.pouvoirs = foundry.utils.duplicate(actor.getPouvoirs())
|
||||||
|
context.dons = foundry.utils.duplicate(actor.getDons())
|
||||||
|
context.hubrises = foundry.utils.duplicate(actor.getHubris())
|
||||||
|
context.tours = foundry.utils.duplicate(actor.getTours())
|
||||||
|
context.artifex = foundry.utils.duplicate(actor.getArtifex())
|
||||||
|
context.charmes = foundry.utils.duplicate(actor.getCharmes())
|
||||||
|
context.peuple = foundry.utils.duplicate(actor.getPeuple() || {})
|
||||||
|
context.origine = foundry.utils.duplicate(actor.getOrigine() || {})
|
||||||
|
context.heritage = foundry.utils.duplicate(actor.getHeritage() || {})
|
||||||
|
context.metier = foundry.utils.duplicate(actor.getMetier() || {})
|
||||||
|
context.combat = actor.getCombatValues()
|
||||||
|
context.capacites = foundry.utils.duplicate(actor.getCapacites())
|
||||||
|
context.equipements = foundry.utils.duplicate(actor.getEquipments())
|
||||||
|
context.monnaies = foundry.utils.duplicate(actor.getMonnaies())
|
||||||
|
context.mutations = foundry.utils.duplicate(actor.getMutations())
|
||||||
|
|
||||||
|
// Enrich HTML fields for biodata
|
||||||
|
context.enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.notes || "", { async: true })
|
||||||
|
context.enrichedGMNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.gmnotes || "", { async: true })
|
||||||
|
context.enrichedSequelles = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.sequelles || "", { async: true })
|
||||||
|
context.enrichedTraumatismes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.traumatismes || "", { async: true })
|
||||||
|
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
32
modules/applications/sheets/wasteland-peuple-sheet.mjs
Normal file
32
modules/applications/sheets/wasteland-peuple-sheet.mjs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandPeupleSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["peuple"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["peuple-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-peuple-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "description" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
33
modules/applications/sheets/wasteland-pouvoir-sheet.mjs
Normal file
33
modules/applications/sheets/wasteland-pouvoir-sheet.mjs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandPouvoirSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["pouvoir"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["pouvoir-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-pouvoir-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "details" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
details: { id: "details", group: "primary", label: "Détails" },
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
33
modules/applications/sheets/wasteland-protection-sheet.mjs
Normal file
33
modules/applications/sheets/wasteland-protection-sheet.mjs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import WastelandItemSheet from "./base-item-sheet.mjs"
|
||||||
|
|
||||||
|
export default class WastelandProtectionSheet extends WastelandItemSheet {
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["protection"],
|
||||||
|
position: { width: 620 },
|
||||||
|
window: { contentClasses: ["protection-content"] },
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/fvtt-wasteland/templates/item-protection-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
tabGroups = { primary: "details" }
|
||||||
|
|
||||||
|
#getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
details: { id: "details", group: "primary", label: "Détails" },
|
||||||
|
description: { id: "description", group: "primary", label: "Description" }
|
||||||
|
}
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] === v.id
|
||||||
|
v.cssClass = v.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext()
|
||||||
|
context.tabs = this.#getTabs()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
156
modules/applications/wasteland-roll-dialog.mjs
Normal file
156
modules/applications/wasteland-roll-dialog.mjs
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
import { WastelandUtility } from "../wasteland-utility.js"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialogue de jet de dé pour Wasteland - Version DialogV2
|
||||||
|
*/
|
||||||
|
export class WastelandRollDialog {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and display the roll dialog
|
||||||
|
* @param {WastelandActor} actor - The actor making the roll
|
||||||
|
* @param {Object} rollData - Data for the roll
|
||||||
|
* @returns {Promise<WastelandRollDialog>}
|
||||||
|
*/
|
||||||
|
static async create(actor, rollData) {
|
||||||
|
// Préparer le contexte pour le template
|
||||||
|
const context = {
|
||||||
|
...rollData,
|
||||||
|
difficulte: String(rollData.difficulte || 0),
|
||||||
|
img: actor.img,
|
||||||
|
name: actor.name,
|
||||||
|
config: game.system.wasteland.config,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rendre le template en HTML
|
||||||
|
const content = await foundry.applications.handlebars.renderTemplate(
|
||||||
|
"systems/fvtt-wasteland/templates/roll-dialog-v2.hbs",
|
||||||
|
context
|
||||||
|
)
|
||||||
|
|
||||||
|
// Utiliser DialogV2.wait avec le HTML rendu
|
||||||
|
return foundry.applications.api.DialogV2.wait({
|
||||||
|
window: { title: "Test de Capacité", icon: "fa-solid fa-dice-d20" },
|
||||||
|
classes: ["wasteland-roll-dialog"],
|
||||||
|
position: { width: 500 },
|
||||||
|
modal: false,
|
||||||
|
content,
|
||||||
|
buttons: rollData.charme ? [
|
||||||
|
{
|
||||||
|
action: "roll",
|
||||||
|
label: "Lancer",
|
||||||
|
icon: "fa-solid fa-dice-d20",
|
||||||
|
default: true,
|
||||||
|
callback: (event, button, dialog) => {
|
||||||
|
this._updateRollDataFromForm(rollData, button.form.elements, actor)
|
||||||
|
WastelandUtility.rollWasteland(rollData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] : [
|
||||||
|
{
|
||||||
|
action: "rolld10",
|
||||||
|
label: "Lancer 1d10",
|
||||||
|
icon: "fa-solid fa-dice-d10",
|
||||||
|
default: true,
|
||||||
|
callback: (event, button, dialog) => {
|
||||||
|
this._updateRollDataFromForm(rollData, button.form.elements, actor)
|
||||||
|
rollData.mainDice = "1d10"
|
||||||
|
WastelandUtility.rollWasteland(rollData)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: "rolld20",
|
||||||
|
label: "Lancer 1d20",
|
||||||
|
icon: "fa-solid fa-dice-d20",
|
||||||
|
callback: (event, button, dialog) => {
|
||||||
|
this._updateRollDataFromForm(rollData, button.form.elements, actor)
|
||||||
|
rollData.mainDice = "1d20"
|
||||||
|
WastelandUtility.rollWasteland(rollData)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
rejectClose: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mettre à jour rollData avec les valeurs du formulaire
|
||||||
|
* @param {Object} rollData - L'objet rollData à mettre à jour
|
||||||
|
* @param {HTMLFormControlsCollection} formElements - Les éléments du formulaire
|
||||||
|
* @param {WastelandActor} actor - L'acteur pour récupérer les attributs
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static _updateRollDataFromForm(rollData, formElements, actor) {
|
||||||
|
// Attributs
|
||||||
|
if (formElements.attrKey) {
|
||||||
|
rollData.attrKey = formElements.attrKey.value
|
||||||
|
if (rollData.attrKey !== "tochoose" && actor) {
|
||||||
|
rollData.attr = foundry.utils.duplicate(actor.system.attributs[rollData.attrKey])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modificateurs de base
|
||||||
|
if (formElements.difficulte) {
|
||||||
|
rollData.difficulte = Number(formElements.difficulte.value)
|
||||||
|
}
|
||||||
|
if (formElements.modificateur) {
|
||||||
|
rollData.modificateur = Number(formElements.modificateur.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Charme
|
||||||
|
if (formElements.charmeDice) {
|
||||||
|
rollData.charmeDice = String(formElements.charmeDice.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combat mêlée
|
||||||
|
if (formElements.typeAttaque) {
|
||||||
|
rollData.typeAttaque = String(formElements.typeAttaque.value)
|
||||||
|
rollData.typeAttaqueLabel = rollData.config.attaques[rollData.typeAttaque]
|
||||||
|
}
|
||||||
|
if (formElements.isMonte !== undefined) {
|
||||||
|
rollData.isMonte = formElements.isMonte.checked
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combat distance
|
||||||
|
if (formElements.visee !== undefined) {
|
||||||
|
rollData.visee = formElements.visee.checked
|
||||||
|
}
|
||||||
|
if (formElements.cibleconsciente !== undefined) {
|
||||||
|
rollData.cibleconsciente = formElements.cibleconsciente.checked
|
||||||
|
}
|
||||||
|
if (formElements.ciblecourt !== undefined) {
|
||||||
|
rollData.ciblecourt = formElements.ciblecourt.checked
|
||||||
|
}
|
||||||
|
if (formElements.typeCouvert) {
|
||||||
|
rollData.typeCouvert = String(formElements.typeCouvert.value)
|
||||||
|
const couvert = rollData.config.couverts[rollData.typeCouvert]
|
||||||
|
if (rollData.typeCouvert !== "aucun" && couvert) {
|
||||||
|
rollData.typeCouvertLabel = couvert.name
|
||||||
|
rollData.typeCouvertValue = couvert.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Désavantages (avantages tactiques)
|
||||||
|
if (!rollData.desavantages) rollData.desavantages = {}
|
||||||
|
|
||||||
|
if (formElements.cibleausol !== undefined) {
|
||||||
|
rollData.desavantages.cibleausol = formElements.cibleausol.checked
|
||||||
|
}
|
||||||
|
if (formElements.cibledesarmee !== undefined) {
|
||||||
|
rollData.desavantages.cibledesarmee = formElements.cibledesarmee.checked
|
||||||
|
}
|
||||||
|
if (formElements.ciblerestreint !== undefined) {
|
||||||
|
rollData.desavantages.ciblerestreint = formElements.ciblerestreint.checked
|
||||||
|
}
|
||||||
|
if (formElements.cibleimmobilisée !== undefined) {
|
||||||
|
rollData.desavantages.cibleimmobilisée = formElements.cibleimmobilisée.checked
|
||||||
|
}
|
||||||
|
if (formElements.ciblesurplomb !== undefined) {
|
||||||
|
rollData.desavantages.ciblesurplomb = formElements.ciblesurplomb.checked
|
||||||
|
}
|
||||||
|
|
||||||
|
// Double D20
|
||||||
|
if (formElements.doubleD20 !== undefined) {
|
||||||
|
rollData.doubleD20 = formElements.doubleD20.checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
modules/models/arme.mjs
Normal file
26
modules/models/arme.mjs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les armes
|
||||||
|
*/
|
||||||
|
export default class ArmeDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
typearme: new fields.StringField({ initial: "" }),
|
||||||
|
isdefense: new fields.BooleanField({ initial: false }),
|
||||||
|
bonusmaniementoff: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
bonusmaniementdef: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
nobonusdegats: new fields.BooleanField({ initial: false }),
|
||||||
|
degats: new fields.StringField({ initial: "" }),
|
||||||
|
nonletaux: new fields.BooleanField({ initial: false }),
|
||||||
|
deuxmains: new fields.BooleanField({ initial: false }),
|
||||||
|
courte: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
moyenne: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
longue: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
tr: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
rarete: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
prix: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
equipped: new fields.BooleanField({ initial: false })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
18
modules/models/artifex.mjs
Normal file
18
modules/models/artifex.mjs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les artifex
|
||||||
|
*/
|
||||||
|
export default class ArtifexDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
artifextype: new fields.StringField({ initial: "vapeur" }),
|
||||||
|
competence: new fields.StringField({ initial: "" }),
|
||||||
|
complexite: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
dureerealisation: new fields.StringField({ initial: "" }),
|
||||||
|
tempsmiseenroute: new fields.StringField({ initial: "" }),
|
||||||
|
defautcourant: new fields.StringField({ initial: "" }),
|
||||||
|
prix: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
17
modules/models/bouclier.mjs
Normal file
17
modules/models/bouclier.mjs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les boucliers
|
||||||
|
*/
|
||||||
|
export default class BouclierDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
bonusdefense: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
degats: new fields.StringField({ initial: "" }),
|
||||||
|
nonletaux: new fields.BooleanField({ initial: false }),
|
||||||
|
rarete: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
prix: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
equipped: new fields.BooleanField({ initial: false })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
11
modules/models/capacite.mjs
Normal file
11
modules/models/capacite.mjs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les capacités
|
||||||
|
*/
|
||||||
|
export default class CapaciteDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
25
modules/models/charme.mjs
Normal file
25
modules/models/charme.mjs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les charmes
|
||||||
|
*/
|
||||||
|
export default class CharmeDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
charmetype: new fields.StringField({ initial: "tour" }),
|
||||||
|
resultats: new fields.ArrayField(new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: -1, integer: true }),
|
||||||
|
description: new fields.StringField({ initial: "" })
|
||||||
|
}), {
|
||||||
|
initial: [
|
||||||
|
{ value: -1, description: "" },
|
||||||
|
{ value: -1, description: "" },
|
||||||
|
{ value: -1, description: "" },
|
||||||
|
{ value: -1, description: "" },
|
||||||
|
{ value: -1, description: "" },
|
||||||
|
{ value: -1, description: "" }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
21
modules/models/competence.mjs
Normal file
21
modules/models/competence.mjs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les compétences
|
||||||
|
*/
|
||||||
|
export default class CompetenceDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
niveau: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
attribut1: new fields.StringField({ initial: "" }),
|
||||||
|
attribut2: new fields.StringField({ initial: "" }),
|
||||||
|
attribut3: new fields.StringField({ initial: "" }),
|
||||||
|
doublebonus: new fields.BooleanField({ initial: false }),
|
||||||
|
predilections: new fields.ArrayField(new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ initial: "" }),
|
||||||
|
description: new fields.StringField({ initial: "" }),
|
||||||
|
used: new fields.BooleanField({ initial: false })
|
||||||
|
}), { initial: [] })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
99
modules/models/creature.mjs
Normal file
99
modules/models/creature.mjs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les créatures
|
||||||
|
*/
|
||||||
|
export default class CreatureDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
// Template biodata
|
||||||
|
biodata: new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ initial: "" }),
|
||||||
|
age: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
alignement: new fields.StringField({ initial: "" }),
|
||||||
|
poids: new fields.StringField({ initial: "" }),
|
||||||
|
taille: new fields.StringField({ initial: "" }),
|
||||||
|
cheveux: new fields.StringField({ initial: "" }),
|
||||||
|
sexe: new fields.StringField({ initial: "" }),
|
||||||
|
yeux: new fields.StringField({ initial: "" }),
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
habitat: new fields.StringField({ initial: "" }),
|
||||||
|
comportement: new fields.StringField({ initial: "" }),
|
||||||
|
psychemultiplier: new fields.NumberField({ initial: 1, integer: true }),
|
||||||
|
notes: new fields.HTMLField({ initial: "" }),
|
||||||
|
gmnotes: new fields.HTMLField({ initial: "" })
|
||||||
|
}),
|
||||||
|
// Template core
|
||||||
|
terreur: new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: -1, integer: true })
|
||||||
|
}),
|
||||||
|
protection: new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
ressource: new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
subactors: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||||
|
attributs: new fields.SchemaField({
|
||||||
|
adr: new fields.SchemaField({
|
||||||
|
label: new fields.StringField({ initial: "Adresse" }),
|
||||||
|
labelnorm: new fields.StringField({ initial: "adresse" }),
|
||||||
|
abbrev: new fields.StringField({ initial: "adr" }),
|
||||||
|
value: new fields.NumberField({ initial: 1, integer: true })
|
||||||
|
}),
|
||||||
|
pui: new fields.SchemaField({
|
||||||
|
label: new fields.StringField({ initial: "Puissance" }),
|
||||||
|
labelnorm: new fields.StringField({ initial: "puissance" }),
|
||||||
|
abbrev: new fields.StringField({ initial: "pui" }),
|
||||||
|
value: new fields.NumberField({ initial: 1, integer: true })
|
||||||
|
}),
|
||||||
|
cla: new fields.SchemaField({
|
||||||
|
label: new fields.StringField({ initial: "Clairvoyance" }),
|
||||||
|
labelnorm: new fields.StringField({ initial: "clairvoyance" }),
|
||||||
|
abbrev: new fields.StringField({ initial: "cla" }),
|
||||||
|
value: new fields.NumberField({ initial: 1, integer: true })
|
||||||
|
}),
|
||||||
|
pre: new fields.SchemaField({
|
||||||
|
label: new fields.StringField({ initial: "Présence" }),
|
||||||
|
labelnorm: new fields.StringField({ initial: "presence" }),
|
||||||
|
abbrev: new fields.StringField({ initial: "pre" }),
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
tre: new fields.SchemaField({
|
||||||
|
label: new fields.StringField({ initial: "Trempe" }),
|
||||||
|
labelnorm: new fields.StringField({ initial: "trempe" }),
|
||||||
|
abbrev: new fields.StringField({ initial: "tre" }),
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
bonneaventure: new fields.SchemaField({
|
||||||
|
base: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
actuelle: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
experience: new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
eclat: new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
sante: new fields.SchemaField({
|
||||||
|
base: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
bonus: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
nonletaux: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
letaux: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
sequelles: new fields.StringField({ initial: "" })
|
||||||
|
}),
|
||||||
|
psyche: new fields.SchemaField({
|
||||||
|
fullmax: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
currentmax: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
traumatismes: new fields.StringField({ initial: "" })
|
||||||
|
}),
|
||||||
|
combat: new fields.SchemaField({
|
||||||
|
initbonus: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
vitessebonus: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
bonusdegats: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
defensebonus: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
12
modules/models/don.mjs
Normal file
12
modules/models/don.mjs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les dons
|
||||||
|
*/
|
||||||
|
export default class DonDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
coutpsyche: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
14
modules/models/equipement.mjs
Normal file
14
modules/models/equipement.mjs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les équipements
|
||||||
|
*/
|
||||||
|
export default class EquipementDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
quantite: new fields.NumberField({ initial: 1, integer: true, min: 0 }),
|
||||||
|
rarete: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
prix: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
11
modules/models/heritage.mjs
Normal file
11
modules/models/heritage.mjs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les héritages
|
||||||
|
*/
|
||||||
|
export default class HeritageDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
12
modules/models/hubris.mjs
Normal file
12
modules/models/hubris.mjs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les hubris
|
||||||
|
*/
|
||||||
|
export default class HubrisDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
hubristype: new fields.StringField({ initial: "mental" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
27
modules/models/index.mjs
Normal file
27
modules/models/index.mjs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Index des DataModels pour Wasteland
|
||||||
|
* Ce fichier centralise tous les exports des modèles de données
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Modèles d'items
|
||||||
|
export { default as ArmeDataModel } from './arme.mjs';
|
||||||
|
export { default as BouclierDataModel } from './bouclier.mjs';
|
||||||
|
export { default as CapaciteDataModel } from './capacite.mjs';
|
||||||
|
export { default as CompetenceDataModel } from './competence.mjs';
|
||||||
|
export { default as DonDataModel } from './don.mjs';
|
||||||
|
export { default as EquipementDataModel } from './equipement.mjs';
|
||||||
|
export { default as HeritageDataModel } from './heritage.mjs';
|
||||||
|
export { default as MetierDataModel } from './metier.mjs';
|
||||||
|
export { default as MonnaieDataModel } from './monnaie.mjs';
|
||||||
|
export { default as OrigineDataModel } from './origine.mjs';
|
||||||
|
export { default as ProtectionDataModel } from './protection.mjs';
|
||||||
|
export { default as MutationDataModel } from './mutation.mjs';
|
||||||
|
export { default as PouvoirDataModel } from './pouvoir.mjs';
|
||||||
|
export { default as CharmeDataModel } from './charme.mjs';
|
||||||
|
export { default as ArtifexDataModel } from './artifex.mjs';
|
||||||
|
export { default as PeupleDataModel } from './peuple.mjs';
|
||||||
|
export { default as HubrisDataModel } from './hubris.mjs';
|
||||||
|
|
||||||
|
// Modèles d'acteurs
|
||||||
|
export { default as PersonnageDataModel } from './personnage.mjs';
|
||||||
|
export { default as CreatureDataModel } from './creature.mjs';
|
||||||
11
modules/models/metier.mjs
Normal file
11
modules/models/metier.mjs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les métiers
|
||||||
|
*/
|
||||||
|
export default class MetierDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
13
modules/models/monnaie.mjs
Normal file
13
modules/models/monnaie.mjs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les monnaies
|
||||||
|
*/
|
||||||
|
export default class MonnaieDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
quantite: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
unite: new fields.StringField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
11
modules/models/mutation.mjs
Normal file
11
modules/models/mutation.mjs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les mutations
|
||||||
|
*/
|
||||||
|
export default class MutationDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
11
modules/models/origine.mjs
Normal file
11
modules/models/origine.mjs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les origines
|
||||||
|
*/
|
||||||
|
export default class OrigineDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
100
modules/models/personnage.mjs
Normal file
100
modules/models/personnage.mjs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les personnages
|
||||||
|
*/
|
||||||
|
export default class PersonnageDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
// Template biodata
|
||||||
|
biodata: new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ initial: "" }),
|
||||||
|
age: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
alignement: new fields.StringField({ initial: "" }),
|
||||||
|
poids: new fields.StringField({ initial: "" }),
|
||||||
|
taille: new fields.StringField({ initial: "" }),
|
||||||
|
cheveux: new fields.StringField({ initial: "" }),
|
||||||
|
sexe: new fields.StringField({ initial: "" }),
|
||||||
|
yeux: new fields.StringField({ initial: "" }),
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
habitat: new fields.StringField({ initial: "" }),
|
||||||
|
comportement: new fields.StringField({ initial: "" }),
|
||||||
|
psychemultiplier: new fields.NumberField({ initial: 1, integer: true }),
|
||||||
|
notes: new fields.HTMLField({ initial: "" }),
|
||||||
|
gmnotes: new fields.HTMLField({ initial: "" })
|
||||||
|
}),
|
||||||
|
// Template core
|
||||||
|
terreur: new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: -1, integer: true })
|
||||||
|
}),
|
||||||
|
protection: new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
ressource: new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
subactors: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||||
|
attributs: new fields.SchemaField({
|
||||||
|
adr: new fields.SchemaField({
|
||||||
|
label: new fields.StringField({ initial: "Adresse" }),
|
||||||
|
labelnorm: new fields.StringField({ initial: "adresse" }),
|
||||||
|
abbrev: new fields.StringField({ initial: "adr" }),
|
||||||
|
value: new fields.NumberField({ initial: 1, integer: true })
|
||||||
|
}),
|
||||||
|
pui: new fields.SchemaField({
|
||||||
|
label: new fields.StringField({ initial: "Puissance" }),
|
||||||
|
labelnorm: new fields.StringField({ initial: "puissance" }),
|
||||||
|
abbrev: new fields.StringField({ initial: "pui" }),
|
||||||
|
value: new fields.NumberField({ initial: 1, integer: true })
|
||||||
|
}),
|
||||||
|
cla: new fields.SchemaField({
|
||||||
|
label: new fields.StringField({ initial: "Clairvoyance" }),
|
||||||
|
labelnorm: new fields.StringField({ initial: "clairvoyance" }),
|
||||||
|
abbrev: new fields.StringField({ initial: "cla" }),
|
||||||
|
value: new fields.NumberField({ initial: 1, integer: true })
|
||||||
|
}),
|
||||||
|
pre: new fields.SchemaField({
|
||||||
|
label: new fields.StringField({ initial: "Présence" }),
|
||||||
|
labelnorm: new fields.StringField({ initial: "presence" }),
|
||||||
|
abbrev: new fields.StringField({ initial: "pre" }),
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
tre: new fields.SchemaField({
|
||||||
|
label: new fields.StringField({ initial: "Trempe" }),
|
||||||
|
labelnorm: new fields.StringField({ initial: "trempe" }),
|
||||||
|
abbrev: new fields.StringField({ initial: "tre" }),
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
bonneaventure: new fields.SchemaField({
|
||||||
|
base: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
actuelle: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
experience: new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
eclat: new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
sante: new fields.SchemaField({
|
||||||
|
base: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
bonus: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
nonletaux: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
letaux: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
sequelles: new fields.StringField({ initial: "" })
|
||||||
|
}),
|
||||||
|
psyche: new fields.SchemaField({
|
||||||
|
fullmax: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
currentmax: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
traumatismes: new fields.StringField({ initial: "" })
|
||||||
|
}),
|
||||||
|
combat: new fields.SchemaField({
|
||||||
|
initbonus: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
vitessebonus: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
bonusdegats: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
defensebonus: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
monte: new fields.BooleanField({ initial: false })
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
11
modules/models/peuple.mjs
Normal file
11
modules/models/peuple.mjs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les peuples
|
||||||
|
*/
|
||||||
|
export default class PeupleDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
20
modules/models/pouvoir.mjs
Normal file
20
modules/models/pouvoir.mjs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les pouvoirs
|
||||||
|
*/
|
||||||
|
export default class PouvoirDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
chemin: new fields.StringField({ initial: "force" }),
|
||||||
|
attribut1: new fields.StringField({ initial: "cla" }),
|
||||||
|
competence: new fields.StringField({ initial: "" }),
|
||||||
|
seuil: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
coutpsyche: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
cible: new fields.StringField({ initial: "" }),
|
||||||
|
duree: new fields.StringField({ initial: "" }),
|
||||||
|
formulesimple: new fields.StringField({ initial: "" }),
|
||||||
|
formuleetendue: new fields.StringField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
15
modules/models/protection.mjs
Normal file
15
modules/models/protection.mjs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les protections
|
||||||
|
*/
|
||||||
|
export default class ProtectionDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
protection: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
equipped: new fields.BooleanField({ initial: false }),
|
||||||
|
rarete: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
prix: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
/**
|
|
||||||
* Extend the basic ActorSheet with some very simple modifications
|
|
||||||
* @extends {ActorSheet}
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { WastelandUtility } from "./wasteland-utility.js";
|
|
||||||
import { WastelandRollDialog } from "./wasteland-roll-dialog.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
export class WastelandActorSheet extends ActorSheet {
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
static get defaultOptions() {
|
|
||||||
|
|
||||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
|
||||||
classes: ["fvtt-wasteland", "sheet", "actor"],
|
|
||||||
template: "systems/fvtt-wasteland/templates/actor-sheet.html",
|
|
||||||
width: 640,
|
|
||||||
height: 720,
|
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "stats" }],
|
|
||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
|
|
||||||
editScore: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async getData() {
|
|
||||||
const objectData = foundry.utils.duplicate(this.object)
|
|
||||||
let actorData = objectData
|
|
||||||
|
|
||||||
let formData = {
|
|
||||||
title: this.title,
|
|
||||||
id: objectData.id,
|
|
||||||
type: objectData.type,
|
|
||||||
img: objectData.img,
|
|
||||||
name: objectData.name,
|
|
||||||
editable: this.isEditable,
|
|
||||||
cssClass: this.isEditable ? "editable" : "locked",
|
|
||||||
data: actorData.system,
|
|
||||||
effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)),
|
|
||||||
limited: this.object.limited,
|
|
||||||
skills: this.actor.getSkills(),
|
|
||||||
armes: foundry.utils.duplicate(this.actor.getWeapons()),
|
|
||||||
protections: foundry.utils.duplicate(this.actor.getArmors()),
|
|
||||||
pouvoirs:foundry.utils.duplicate(this.actor.getPouvoirs()),
|
|
||||||
dons: foundry.utils.duplicate(this.actor.getDons()),
|
|
||||||
hubrises: foundry.utils.duplicate(this.actor.getHubris()),
|
|
||||||
tours:foundry.utils.duplicate(this.actor.getTours()),
|
|
||||||
artifex: foundry.utils.duplicate(this.actor.getArtifex()),
|
|
||||||
charmes:foundry.utils.duplicate(this.actor.getCharmes()),
|
|
||||||
peuple: foundry.utils.duplicate(this.actor.getPeuple() || {}),
|
|
||||||
origine: foundry.utils.duplicate(this.actor.getOrigine() || {}),
|
|
||||||
heritage: foundry.utils.duplicate(this.actor.getHeritage() || {}),
|
|
||||||
metier: foundry.utils.duplicate(this.actor.getMetier() || {}),
|
|
||||||
combat: this.actor.getCombatValues(),
|
|
||||||
config: foundry.utils.duplicate(game.system.wasteland.config),
|
|
||||||
capacites: foundry.utils.duplicate(this.actor.getCapacites()),
|
|
||||||
equipements: foundry.utils.duplicate(this.actor.getEquipments()),
|
|
||||||
monnaies: foundry.utils.duplicate(this.actor.getMonnaies()),
|
|
||||||
mutations: foundry.utils.duplicate(this.actor.getMutations()),
|
|
||||||
description: await TextEditor.enrichHTML(this.object.system.biodata.description, {async: true}),
|
|
||||||
comportement: await TextEditor.enrichHTML(this.object.system.biodata.comportement, {async: true}),
|
|
||||||
habitat: await TextEditor.enrichHTML(this.object.system.biodata.habitat, {async: true}),
|
|
||||||
options: this.options,
|
|
||||||
owner: this.document.isOwner,
|
|
||||||
editScore: this.options.editScore,
|
|
||||||
isGM: game.user.isGM,
|
|
||||||
config: game.system.wasteland.config
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
|
|
||||||
// Update Inventory Item
|
|
||||||
html.find('.item-edit').click(ev => {
|
|
||||||
const li = $(ev.currentTarget).parents(".item")
|
|
||||||
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");
|
|
||||||
WastelandUtility.confirmDelete(this, li);
|
|
||||||
})
|
|
||||||
html.find('.edit-item-data').change(ev => {
|
|
||||||
const li = $(ev.currentTarget).parents(".item")
|
|
||||||
let itemId = li.data("item-id")
|
|
||||||
let itemType = li.data("item-type")
|
|
||||||
let itemField = $(ev.currentTarget).data("item-field")
|
|
||||||
let dataType = $(ev.currentTarget).data("dtype")
|
|
||||||
let value = ev.currentTarget.value
|
|
||||||
this.actor.editItemField(itemId, itemType, itemField, dataType, value)
|
|
||||||
})
|
|
||||||
|
|
||||||
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-attribut').click((event) => {
|
|
||||||
const li = $(event.currentTarget).parents(".item")
|
|
||||||
let attrKey = li.data("attr-key")
|
|
||||||
this.actor.rollAttribut(attrKey)
|
|
||||||
})
|
|
||||||
html.find('.roll-competence').click((event) => {
|
|
||||||
const li = $(event.currentTarget).parents(".item")
|
|
||||||
let attrKey = $(event.currentTarget).data("attr-key")
|
|
||||||
let compId = li.data("item-id")
|
|
||||||
this.actor.rollCompetence(attrKey, compId)
|
|
||||||
})
|
|
||||||
html.find('.roll-charme').click((event) => {
|
|
||||||
const li = $(event.currentTarget).parents(".item")
|
|
||||||
let charmeId = li.data("item-id")
|
|
||||||
this.actor.rollCharme(charmeId)
|
|
||||||
})
|
|
||||||
|
|
||||||
html.find('.roll-pouvoir').click((event) => {
|
|
||||||
const li = $(event.currentTarget).parents(".item")
|
|
||||||
let pouvoirId = li.data("item-id")
|
|
||||||
this.actor.rollPouvoir(pouvoirId)
|
|
||||||
})
|
|
||||||
html.find('.roll-arme-offensif').click((event) => {
|
|
||||||
const li = $(event.currentTarget).parents(".item")
|
|
||||||
let armeId = li.data("item-id")
|
|
||||||
this.actor.rollArmeOffensif(armeId)
|
|
||||||
})
|
|
||||||
html.find('.roll-arme-degats').click((event) => {
|
|
||||||
const li = $(event.currentTarget).parents(".item")
|
|
||||||
let armeId = li.data("item-id")
|
|
||||||
this.actor.rollArmeDegats(armeId)
|
|
||||||
})
|
|
||||||
html.find('.quantity-modify').click(event => {
|
|
||||||
const li = $(event.currentTarget).parents(".item")
|
|
||||||
const value = Number($(event.currentTarget).data("quantite-value"))
|
|
||||||
this.actor.incDecQuantity( li.data("item-id"), value );
|
|
||||||
})
|
|
||||||
html.find('.item-add').click((event) => {
|
|
||||||
const itemType = $(event.currentTarget).data("type")
|
|
||||||
this.actor.createEmbeddedDocuments('Item', [{ name: `Nouveau ${itemType}`, type: itemType }], { renderSheet: true })
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** @override */
|
|
||||||
setPosition(options = {}) {
|
|
||||||
const position = super.setPosition(options);
|
|
||||||
const sheetBody = this.element.find(".sheet-body");
|
|
||||||
const bodyHeight = position.height - 192;
|
|
||||||
sheetBody.css("height", bodyHeight);
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/*async _onDropItem(event, dragData) {
|
|
||||||
let item = await WastelandUtility.searchItem( dragData)
|
|
||||||
this.actor.preprocessItem( event, item, true )
|
|
||||||
super._onDropItem(event, dragData)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** @override */
|
|
||||||
_updateObject(event, formData) {
|
|
||||||
// Update the Actor
|
|
||||||
return this.object.update(formData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
import { WastelandUtility } from "./wasteland-utility.js";
|
import { WastelandUtility } from "./wasteland-utility.js";
|
||||||
import { WastelandRollDialog } from "./wasteland-roll-dialog.js";
|
import { WastelandRollDialog } from "./applications/wasteland-roll-dialog.mjs";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10]
|
const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10]
|
||||||
@@ -53,6 +53,7 @@ export class WastelandActor extends Actor {
|
|||||||
arme = foundry.utils.duplicate(arme)
|
arme = foundry.utils.duplicate(arme)
|
||||||
let combat = this.getCombatValues()
|
let combat = this.getCombatValues()
|
||||||
if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") {
|
if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") {
|
||||||
|
arme.system.isMelee = true
|
||||||
arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée"))
|
arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée"))
|
||||||
arme.system.attrKey = "pui"
|
arme.system.attrKey = "pui"
|
||||||
arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal
|
arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal
|
||||||
@@ -62,6 +63,7 @@ export class WastelandActor extends Actor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (arme.system.typearme == "jet" || arme.system.typearme == "tir") {
|
if (arme.system.typearme == "jet" || arme.system.typearme == "tir") {
|
||||||
|
arme.system.isDistance = true
|
||||||
arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance"))
|
arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance"))
|
||||||
arme.system.attrKey = "adr"
|
arme.system.attrKey = "adr"
|
||||||
arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff
|
arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff
|
||||||
@@ -296,6 +298,10 @@ export class WastelandActor extends Actor {
|
|||||||
changeEclat(value) {
|
changeEclat(value) {
|
||||||
let newE = this.system.eclat.value
|
let newE = this.system.eclat.value
|
||||||
newE += value
|
newE += value
|
||||||
|
// Empêcher que l'éclat devienne négatif
|
||||||
|
if (newE < 0) {
|
||||||
|
newE = 0
|
||||||
|
}
|
||||||
this.update({ 'system.eclat.value': newE })
|
this.update({ 'system.eclat.value': newE })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,6 +388,32 @@ export class WastelandActor extends Actor {
|
|||||||
await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }])
|
await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async resetAllPredilections() {
|
||||||
|
let updates = []
|
||||||
|
for (let item of this.items) {
|
||||||
|
if (item.type === "competence" && item.system.predilections && item.system.predilections.length > 0) {
|
||||||
|
let pred = foundry.utils.duplicate(item.system.predilections)
|
||||||
|
let hasUsed = false
|
||||||
|
for (let p of pred) {
|
||||||
|
if (p.used) {
|
||||||
|
p.used = false
|
||||||
|
hasUsed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasUsed) {
|
||||||
|
updates.push({ _id: item.id, 'system.predilections': pred })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (updates.length > 0) {
|
||||||
|
await this.updateEmbeddedDocuments('Item', updates)
|
||||||
|
ui.notifications.info(`${updates.length} prédilection(s) réinitialisée(s) pour ${this.name}`)
|
||||||
|
} else {
|
||||||
|
ui.notifications.info(`Aucune prédilection à réinitialiser pour ${this.name}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getInitiativeScore( ) {
|
getInitiativeScore( ) {
|
||||||
return Number(this.system.attributs.adr.value) + Number(this.system.combat.initbonus)
|
return Number(this.system.attributs.adr.value) + Number(this.system.combat.initbonus)
|
||||||
@@ -414,10 +446,12 @@ export class WastelandActor extends Actor {
|
|||||||
rollData.actorId = this.id
|
rollData.actorId = this.id
|
||||||
rollData.tokenId = this.token?.id
|
rollData.tokenId = this.token?.id
|
||||||
rollData.img = this.img
|
rollData.img = this.img
|
||||||
rollData.canEclatDoubleD20 = true // Always true in Wastelan
|
rollData.canEclatDoubleD20 = this.getEclat() >= 1 // Vérifier que l'acteur a au moins 1 point d'éclat
|
||||||
rollData.doubleD20 = false
|
rollData.doubleD20 = false
|
||||||
rollData.attributs = WastelandUtility.getAttributs()
|
rollData.attributs = WastelandUtility.getAttributs()
|
||||||
rollData.config = foundry.utils.duplicate(game.system.wasteland.config)
|
rollData.config = foundry.utils.duplicate(game.system.wasteland.config)
|
||||||
|
rollData.desavantages = {}
|
||||||
|
rollData.isMonte = this.system.combat.monte
|
||||||
|
|
||||||
if (attrKey) {
|
if (attrKey) {
|
||||||
rollData.attrKey = attrKey
|
rollData.attrKey = attrKey
|
||||||
@@ -440,8 +474,7 @@ export class WastelandActor extends Actor {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async launchRoll(rollData) {
|
async launchRoll(rollData) {
|
||||||
console.log("RollData", rollData)
|
console.log("RollData", rollData)
|
||||||
let rollDialog = await WastelandRollDialog.create(this, rollData)
|
await WastelandRollDialog.create(this, rollData)
|
||||||
rollDialog.render(true)
|
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
rollAttribut(attrKey) {
|
rollAttribut(attrKey) {
|
||||||
@@ -467,7 +500,7 @@ export class WastelandActor extends Actor {
|
|||||||
async rollPouvoir(pouvoirId) {
|
async rollPouvoir(pouvoirId) {
|
||||||
let pouvoir = foundry.utils.duplicate(this.items.get(pouvoirId) || {})
|
let pouvoir = foundry.utils.duplicate(this.items.get(pouvoirId) || {})
|
||||||
if (pouvoir?.system) {
|
if (pouvoir?.system) {
|
||||||
let rollData = this.getCommonRollData(pouvoir.system.attribut, undefined, pouvoir.system.competence)
|
let rollData = this.getCommonRollData(pouvoir.system.attribut1, undefined, pouvoir.system.competence)
|
||||||
if (!rollData.competence) {
|
if (!rollData.competence) {
|
||||||
ui.notifications.error("Le pouvoir " + pouvoir.name + " n'a pas de compétence associée. Editez le pouvoir avec la compétence associée.")
|
ui.notifications.error("Le pouvoir " + pouvoir.name + " n'a pas de compétence associée. Editez le pouvoir avec la compétence associée.")
|
||||||
return
|
return
|
||||||
@@ -488,6 +521,12 @@ export class WastelandActor extends Actor {
|
|||||||
}
|
}
|
||||||
let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id)
|
let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id)
|
||||||
rollData.arme = arme
|
rollData.arme = arme
|
||||||
|
rollData.typeAttaque = "assaut"
|
||||||
|
rollData.typeCouvert = "aucun"
|
||||||
|
rollData.hasDesavantageBonus = true
|
||||||
|
rollData.visee = false
|
||||||
|
rollData.ciblecourt = false
|
||||||
|
rollData.cibleconsciente = false
|
||||||
this.launchRoll(rollData)
|
this.launchRoll(rollData)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,8 +550,52 @@ export class WastelandActor extends Actor {
|
|||||||
actionImg: arme.img,
|
actionImg: arme.img,
|
||||||
}
|
}
|
||||||
WastelandUtility.createChatWithRollMode(rollData.alias, {
|
WastelandUtility.createChatWithRollMode(rollData.alias, {
|
||||||
content: await renderTemplate(`systems/fvtt-wasteland/templates/chat-degats-result.html`, rollData)
|
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-wasteland/templates/chat-degats-result-v2.hbs`, rollData)
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async rollAssommer() {
|
||||||
|
let rollData = this.getCommonRollData("adr", undefined, "Mouvements")
|
||||||
|
rollData.specialAction = "Assommer"
|
||||||
|
rollData.typeAttaque = "assommer"
|
||||||
|
rollData.typeCouvert = "aucun"
|
||||||
|
rollData.hasDesavantageBonus = true
|
||||||
|
if (rollData.defender) {
|
||||||
|
rollData.selectDifficulte = false
|
||||||
|
rollData.difficulte = rollData.defender.system.attributs.tre.value * 2
|
||||||
|
}
|
||||||
|
this.launchRoll(rollData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async rollFuir() {
|
||||||
|
let rollData = this.getCommonRollData("adr", undefined, "Mouvements")
|
||||||
|
rollData.specialAction = "Fuir"
|
||||||
|
rollData.typeAttaque = "fuir"
|
||||||
|
rollData.typeCouvert = "aucun"
|
||||||
|
rollData.hasDesavantageBonus = true
|
||||||
|
if (rollData.defender) {
|
||||||
|
rollData.selectDifficulte = false
|
||||||
|
let comp = rollData.defender.items.find(it => it.type == "competence" && it.name.toLowerCase() == "mouvements")
|
||||||
|
rollData.difficulte = rollData.defender.system.attributs.adr.value + ((comp) ? comp.system.niveau : rollData.defender.system.attributs.adr.value)
|
||||||
|
}
|
||||||
|
this.launchRoll(rollData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async rollImmobiliser() {
|
||||||
|
let rollData = this.getCommonRollData("pui", undefined, "Mêlée")
|
||||||
|
rollData.specialAction = "Immobiliser"
|
||||||
|
rollData.typeAttaque = "immobiliser"
|
||||||
|
rollData.typeCouvert = "aucun"
|
||||||
|
rollData.hasDesavantageBonus = true
|
||||||
|
if (rollData.defender) {
|
||||||
|
rollData.selectDifficulte = false
|
||||||
|
rollData.difficulte = rollData.armeDefense ? rollData.armeDefense.system.totalDefensif : 10
|
||||||
|
}
|
||||||
|
this.launchRoll(rollData)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
import { WastelandUtility } from "./wasteland-utility.js";
|
import { WastelandUtility } from "./wasteland-utility.js";
|
||||||
import { WastelandRollDialog } from "./wasteland-roll-dialog.js";
|
import { WastelandRollDialog } from "./applications/wasteland-roll-dialog.mjs";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class WastelandCommands {
|
export class WastelandCommands {
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
export const WASTELAND_CONFIG = {
|
export const WASTELAND_CONFIG = {
|
||||||
|
|
||||||
|
attributs: {
|
||||||
|
"adr": "Adresse",
|
||||||
|
"pui": "Puissance",
|
||||||
|
"cla": "Clairvoyance",
|
||||||
|
"pre": "Présence",
|
||||||
|
"tre": "Trempe"
|
||||||
|
},
|
||||||
cheminpouvoir : {
|
cheminpouvoir : {
|
||||||
"force": "Chemin des Forces",
|
"force": "Chemin des Forces",
|
||||||
"forge": "Chemin des Forges",
|
"forge": "Chemin des Forges",
|
||||||
@@ -44,13 +51,54 @@ export const WASTELAND_CONFIG = {
|
|||||||
tir: "Arme de Tir",
|
tir: "Arme de Tir",
|
||||||
special: "Spécial (capacité/don)"
|
special: "Spécial (capacité/don)"
|
||||||
},
|
},
|
||||||
|
attaques: {
|
||||||
|
assaut: "Assaut",
|
||||||
|
precise: "Attaque Précise",
|
||||||
|
feinte: "Feinte",
|
||||||
|
coupbas: "Coup Bas",
|
||||||
|
charger: "Charger",
|
||||||
|
contenir: "Contenir",
|
||||||
|
desarmer: "Désarmer"
|
||||||
|
},
|
||||||
|
couverts: {
|
||||||
|
aucun: { name: "Aucun", value: 0 },
|
||||||
|
rondache: { name: "Couvert Léger", value: -2 },
|
||||||
|
pavois: { name: "Couvert Moyen", value: -5 },
|
||||||
|
complet: { name: "Couvert Complet", value: -10 },
|
||||||
|
},
|
||||||
|
listePortees: {
|
||||||
|
"10": "Moins que Courte",
|
||||||
|
"15": "Courte ou plus",
|
||||||
|
"20": "Moyenne ou plus",
|
||||||
|
"25": "Longue ou plus"
|
||||||
|
},
|
||||||
difficulteOptions: {
|
difficulteOptions: {
|
||||||
"0": "Aucune/Inconnue",
|
"0": "Aucune/Inconnue",
|
||||||
"5": "Facile (5)",
|
"5": "Facile (5)",
|
||||||
|
"6": "(6)",
|
||||||
|
"7": "(7)",
|
||||||
|
"8": "(8)",
|
||||||
|
"9": "(9)",
|
||||||
"10": "Moyenne (10)",
|
"10": "Moyenne (10)",
|
||||||
|
"11": "(11)",
|
||||||
|
"12": "(12)",
|
||||||
|
"13": "(13)",
|
||||||
|
"14": "(14)",
|
||||||
"15": "Ardue (15)",
|
"15": "Ardue (15)",
|
||||||
|
"16": "(16)",
|
||||||
|
"17": "(17)",
|
||||||
|
"18": "(18)",
|
||||||
|
"19": "(19)",
|
||||||
"20": "Hasardeuse (20)",
|
"20": "Hasardeuse (20)",
|
||||||
|
"21": "(21)",
|
||||||
|
"22": "(22)",
|
||||||
|
"23": "(23)",
|
||||||
|
"24": "(24)",
|
||||||
"25": "Insensée (25)",
|
"25": "Insensée (25)",
|
||||||
|
"26": "(26)",
|
||||||
|
"27": "(27)",
|
||||||
|
"28": "(28)",
|
||||||
|
"29": "(29)",
|
||||||
"30": "Pure Folie (30)"
|
"30": "Pure Folie (30)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
/**
|
|
||||||
* Extend the basic ActorSheet with some very simple modifications
|
|
||||||
* @extends {ActorSheet}
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { WastelandUtility } from "./wasteland-utility.js";
|
|
||||||
import { WastelandActorSheet } from "./wasteland-actor-sheet.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
export class WastelandCreatureSheet extends WastelandActorSheet {
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
static get defaultOptions() {
|
|
||||||
|
|
||||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
|
||||||
classes: ["fvtt-wasteland", "sheet", "creature"],
|
|
||||||
template: "systems/fvtt-wasteland/templates/creature-sheet.html",
|
|
||||||
width: 640,
|
|
||||||
height: 720,
|
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "stats" }],
|
|
||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
|
|
||||||
editScore: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
import { WastelandUtility } from "./wasteland-utility.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extend the basic ItemSheet with some very simple modifications
|
|
||||||
* @extends {ItemSheet}
|
|
||||||
*/
|
|
||||||
export class WastelandItemSheet extends ItemSheet {
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
static get defaultOptions() {
|
|
||||||
|
|
||||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
|
||||||
classes: ["fvtt-wasteland", "sheet", "item"],
|
|
||||||
template: "systems/fvtt-wasteland/templates/item-sheet.html",
|
|
||||||
dragDrop: [{ dragSelector: null, dropSelector: null }],
|
|
||||||
width: 620,
|
|
||||||
height: 550
|
|
||||||
//tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description"}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
_getHeaderButtons() {
|
|
||||||
let buttons = super._getHeaderButtons();
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** @override */
|
|
||||||
setPosition(options = {}) {
|
|
||||||
const position = super.setPosition(options);
|
|
||||||
const sheetBody = this.element.find(".sheet-body");
|
|
||||||
const bodyHeight = position.height - 192;
|
|
||||||
sheetBody.css("height", bodyHeight);
|
|
||||||
if (this.item.type.includes('weapon')) {
|
|
||||||
position.width = 640;
|
|
||||||
}
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async getData() {
|
|
||||||
const objectData = foundry.utils.duplicate(this.object)
|
|
||||||
let itemData = objectData
|
|
||||||
let formData = {
|
|
||||||
title: this.title,
|
|
||||||
id: this.id,
|
|
||||||
type: objectData.type,
|
|
||||||
img: objectData.img,
|
|
||||||
name: objectData.name,
|
|
||||||
editable: this.isEditable,
|
|
||||||
cssClass: this.isEditable ? "editable" : "locked",
|
|
||||||
attributs: WastelandUtility.getAttributs(),
|
|
||||||
config: foundry.utils.duplicate(game.system.wasteland.config),
|
|
||||||
data: itemData.system,
|
|
||||||
system: itemData.system,
|
|
||||||
limited: this.object.limited,
|
|
||||||
options: this.options,
|
|
||||||
owner: this.document.isOwner,
|
|
||||||
description: await TextEditor.enrichHTML(this.object.system.description, {async: true}),
|
|
||||||
isGM: game.user.isGM
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
let chatData = foundry.utils.duplicate(WastelandUtility.data(this.item));
|
|
||||||
if (this.actor) {
|
|
||||||
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")) {
|
|
||||||
chatData.img = null;
|
|
||||||
}
|
|
||||||
// JSON object for easy creation
|
|
||||||
chatData.jsondata = JSON.stringify(
|
|
||||||
{
|
|
||||||
compendium: "postedItem",
|
|
||||||
payload: chatData,
|
|
||||||
});
|
|
||||||
|
|
||||||
renderTemplate('systems/fvtt-Wasteland-rpg/templates/post-item.html', chatData).then(html => {
|
|
||||||
let chatOptions = WastelandUtility.chatDataSetup(html);
|
|
||||||
ChatMessage.create(chatOptions)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** @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);
|
|
||||||
})
|
|
||||||
html.find('.edit-prediction').change(ev => {
|
|
||||||
const li = $(ev.currentTarget).parents(".prediction-item")
|
|
||||||
let index = li.data("prediction-index")
|
|
||||||
let pred = foundry.utils.duplicate(this.object.system.predilections)
|
|
||||||
pred[index].name = ev.currentTarget.value
|
|
||||||
this.object.update( { 'data.predilections': pred })
|
|
||||||
})
|
|
||||||
html.find('.delete-prediction').click(ev => {
|
|
||||||
const li = $(ev.currentTarget).parents(".prediction-item")
|
|
||||||
let index = li.data("prediction-index")
|
|
||||||
let pred = foundry.utils.duplicate(this.object.system.predilections)
|
|
||||||
pred.splice(index,1)
|
|
||||||
this.object.update( { 'data.predilections': pred })
|
|
||||||
})
|
|
||||||
html.find('.use-prediction').change(ev => {
|
|
||||||
const li = $(ev.currentTarget).parents(".prediction-item")
|
|
||||||
let index = li.data("prediction-index")
|
|
||||||
let pred = foundry.utils.duplicate(this.object.system.predilections)
|
|
||||||
pred[index].used = ev.currentTarget.checked
|
|
||||||
this.object.update( { 'data.predilections': pred })
|
|
||||||
})
|
|
||||||
html.find('#add-predilection').click(ev => {
|
|
||||||
let pred = foundry.utils.duplicate(this.object.system.predilections)
|
|
||||||
pred.push( { name: "Nouvelle prédilection", used: false })
|
|
||||||
this.object.update( { 'data.predilections': pred })
|
|
||||||
})
|
|
||||||
// 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-wasteland/templates/item-${type}-sheet.html`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** @override */
|
|
||||||
_updateObject(event, formData) {
|
|
||||||
return this.object.update(formData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,14 +9,17 @@
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// Import Modules
|
// Import Modules
|
||||||
import { WastelandActor } from "./wasteland-actor.js";
|
import { WastelandActor } from "./wasteland-actor.js";
|
||||||
import { WastelandItemSheet } from "./wasteland-item-sheet.js";
|
|
||||||
import { WastelandActorSheet } from "./wasteland-actor-sheet.js";
|
|
||||||
import { WastelandCreatureSheet } from "./wasteland-creature-sheet.js";
|
|
||||||
import { WastelandUtility } from "./wasteland-utility.js";
|
import { WastelandUtility } from "./wasteland-utility.js";
|
||||||
import { WastelandCombat } from "./wasteland-combat.js";
|
import { WastelandCombat } from "./wasteland-combat.js";
|
||||||
import { WastelandItem } from "./wasteland-item.js";
|
import { WastelandItem } from "./wasteland-item.js";
|
||||||
import { WASTELAND_CONFIG } from "./wasteland-config.js";
|
import { WASTELAND_CONFIG } from "./wasteland-config.js";
|
||||||
|
|
||||||
|
// Import DataModels
|
||||||
|
import * as models from "./models/index.mjs";
|
||||||
|
|
||||||
|
// Import AppV2 Sheets
|
||||||
|
import * as sheets from "./applications/sheets/_module.mjs";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Foundry VTT Initialization */
|
/* Foundry VTT Initialization */
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -45,35 +48,112 @@ Hooks.once("init", async function () {
|
|||||||
// Define custom Entity classes
|
// Define custom Entity classes
|
||||||
CONFIG.Combat.documentClass = WastelandCombat
|
CONFIG.Combat.documentClass = WastelandCombat
|
||||||
CONFIG.Actor.documentClass = WastelandActor
|
CONFIG.Actor.documentClass = WastelandActor
|
||||||
CONFIG.Item.documentClass = WastelandItem
|
CONFIG.Actor.dataModels = {
|
||||||
game.system.wasteland = {
|
personnage: models.PersonnageDataModel,
|
||||||
config: WASTELAND_CONFIG
|
creature: models.CreatureDataModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CONFIG.Item.documentClass = WastelandItem
|
||||||
|
CONFIG.Item.dataModels = {
|
||||||
|
arme: models.ArmeDataModel,
|
||||||
|
artifex: models.ArtifexDataModel,
|
||||||
|
bouclier: models.BouclierDataModel,
|
||||||
|
capacite: models.CapaciteDataModel,
|
||||||
|
charme: models.CharmeDataModel,
|
||||||
|
competence: models.CompetenceDataModel,
|
||||||
|
don: models.DonDataModel,
|
||||||
|
equipement: models.EquipementDataModel,
|
||||||
|
heritage: models.HeritageDataModel,
|
||||||
|
hubris: models.HubrisDataModel,
|
||||||
|
metier: models.MetierDataModel,
|
||||||
|
monnaie: models.MonnaieDataModel,
|
||||||
|
mutation: models.MutationDataModel,
|
||||||
|
origine: models.OrigineDataModel,
|
||||||
|
peuple: models.PeupleDataModel,
|
||||||
|
pouvoir: models.PouvoirDataModel,
|
||||||
|
protection: models.ProtectionDataModel
|
||||||
|
}
|
||||||
|
|
||||||
|
game.system.wasteland = {
|
||||||
|
config: WASTELAND_CONFIG,
|
||||||
|
models,
|
||||||
|
sheets
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize dynamic config options that need to be available immediately
|
||||||
|
// Create option lists inline to ensure they're available
|
||||||
|
const listeNiveauSkill = {}
|
||||||
|
for (let i = 0; i <= 10; i++) {
|
||||||
|
listeNiveauSkill[`${i}`] = `${i}`
|
||||||
|
}
|
||||||
|
game.system.wasteland.config.listeNiveauSkill = listeNiveauSkill
|
||||||
|
|
||||||
|
const listeNiveauAttribut = {}
|
||||||
|
for (let i = 0; i <= 10; i++) {
|
||||||
|
listeNiveauAttribut[`${i}`] = `${i}`
|
||||||
|
}
|
||||||
|
game.system.wasteland.config.listeNiveauAttribut = listeNiveauAttribut
|
||||||
|
|
||||||
|
const listeNiveauCreature = {}
|
||||||
|
for (let i = 0; i <= 35; i++) {
|
||||||
|
listeNiveauCreature[`${i}`] = `${i}`
|
||||||
|
}
|
||||||
|
game.system.wasteland.config.listeNiveauCreature = listeNiveauCreature
|
||||||
|
|
||||||
|
const modificateurOptions = []
|
||||||
|
for (let i = -15; i <= 15; i++) {
|
||||||
|
modificateurOptions.push({ key: i, label: `${i >= 0 ? '+' : ''}${i}` })
|
||||||
|
}
|
||||||
|
game.system.wasteland.config.modificateurOptions = modificateurOptions
|
||||||
|
|
||||||
|
const pointsAmeOptions = {}
|
||||||
|
for (let i = 0; i <= 20; i++) {
|
||||||
|
pointsAmeOptions[`${i}`] = `${i}`
|
||||||
|
}
|
||||||
|
game.system.wasteland.config.pointsAmeOptions = pointsAmeOptions
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// Register sheet application classes
|
// Register sheet application classes
|
||||||
Actors.unregisterSheet("core", ActorSheet);
|
|
||||||
Actors.registerSheet("fvtt-wasteland", WastelandActorSheet, { types: ["personnage"], makeDefault: true })
|
|
||||||
Actors.registerSheet("fvtt-wasteland", WastelandCreatureSheet, { types: ["creature"], makeDefault: false });
|
|
||||||
|
|
||||||
Items.unregisterSheet("core", ItemSheet);
|
// Register AppV2 Actor Sheets
|
||||||
Items.registerSheet("fvtt-wasteland", WastelandItemSheet, { makeDefault: true })
|
foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet);
|
||||||
|
foundry.documents.collections.Actors.registerSheet("fvtt-wasteland", sheets.WastelandPersonnageSheet, { types: ["personnage"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Actors.registerSheet("fvtt-wasteland", sheets.WastelandCreatureSheet, { types: ["creature"], makeDefault: true });
|
||||||
|
|
||||||
|
// Register AppV2 Item Sheets
|
||||||
|
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet);
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandArmeSheet, { types: ["arme"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandArtifexSheet, { types: ["artifex"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandBouclierSheet, { types: ["bouclier"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandCapaciteSheet, { types: ["capacite"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandCharmeSheet, { types: ["charme"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandCompetenceSheet, { types: ["competence"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandDonSheet, { types: ["don"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandEquipementSheet, { types: ["equipement"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandHeritageSheet, { types: ["heritage"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandHubrisSheet, { types: ["hubris"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandMetierSheet, { types: ["metier"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandMonnaieSheet, { types: ["monnaie"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandMutationSheet, { types: ["mutation"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandOrigineSheet, { types: ["origine"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandPeupleSheet, { types: ["peuple"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandPouvoirSheet, { types: ["pouvoir"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-wasteland", sheets.WastelandProtectionSheet, { types: ["protection"], makeDefault: true });
|
||||||
|
|
||||||
WastelandUtility.init();
|
WastelandUtility.init();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
function welcomeMessage() {
|
async function welcomeMessage() {
|
||||||
|
const templateData = {};
|
||||||
|
const html = await foundry.applications.handlebars.renderTemplate("systems/fvtt-wasteland/templates/chat-welcome-message.hbs", templateData);
|
||||||
|
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
user: game.user.id,
|
user: game.user.id,
|
||||||
whisper: [game.user.id],
|
whisper: [game.user.id],
|
||||||
content: `<div id="welcome-message-Wasteland"><span class="rdd-roll-part">
|
content: html
|
||||||
<strong>Bienvenue dans les Wasteland !</strong>
|
});
|
||||||
<p>Les livres de Wasteland sont nécessaires pour jouer : https://www.titam-france.fr</p>
|
|
||||||
<p>Wasteland est jeu de rôle publié par Titam France/Sombres projets, tout les droits leur appartiennent.</p>
|
|
||||||
<p>Système développé par LeRatierBretonnien, avec le support de Prêtre. Plus d'infos et aides sur le <a href="https://discord.gg/pPSDNJk">Discord FR de Foundry</a>.</p>
|
|
||||||
` });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -136,4 +216,3 @@ Hooks.on("chatMessage", (html, content, msg) => {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
import { WastelandUtility } from "./wasteland-utility.js";
|
|
||||||
|
|
||||||
export class WastelandRollDialog extends Dialog {
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async create(actor, rollData) {
|
|
||||||
|
|
||||||
let options = { classes: ["WastelandDialog"], width: 340, height: 'fit-content', 'z-index': 99999 };
|
|
||||||
let html = await renderTemplate('systems/fvtt-wasteland/templates/roll-dialog-generic.html', rollData);
|
|
||||||
|
|
||||||
return new WastelandRollDialog(actor, rollData, html, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
constructor(actor, rollData, html, options, close = undefined) {
|
|
||||||
let buttons = {
|
|
||||||
rolld10: {
|
|
||||||
icon: '<i class="fas fa-check"></i>',
|
|
||||||
label: "Lancer 1d10",
|
|
||||||
callback: () => { this.roll("1d10") }
|
|
||||||
},
|
|
||||||
rolld20: {
|
|
||||||
icon: '<i class="fas fa-check"></i>',
|
|
||||||
label: "Lancer 1d20",
|
|
||||||
callback: () => { this.roll("1d20") }
|
|
||||||
},
|
|
||||||
cancel: {
|
|
||||||
icon: '<i class="fas fa-times"></i>',
|
|
||||||
label: "Annuler",
|
|
||||||
callback: () => { this.close() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rollData.charme) {
|
|
||||||
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() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let conf = {
|
|
||||||
title: "Test de Capacité",
|
|
||||||
content: html,
|
|
||||||
buttons: buttons,
|
|
||||||
close: close
|
|
||||||
}
|
|
||||||
|
|
||||||
super(conf, options);
|
|
||||||
|
|
||||||
this.actor = actor
|
|
||||||
this.rollData = rollData
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
roll(dice) {
|
|
||||||
this.rollData.mainDice = dice
|
|
||||||
WastelandUtility.rollWasteland(this.rollData)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
|
|
||||||
var dialog = this;
|
|
||||||
function onLoad() {
|
|
||||||
}
|
|
||||||
$(function () { onLoad(); });
|
|
||||||
|
|
||||||
html.find('#modificateur').change(async (event) => {
|
|
||||||
this.rollData.modificateur = Number(event.currentTarget.value)
|
|
||||||
})
|
|
||||||
html.find('#difficulte').change(async (event) => {
|
|
||||||
this.rollData.difficulte = Number(event.currentTarget.value)
|
|
||||||
})
|
|
||||||
html.find('#attrKey').change(async (event) => {
|
|
||||||
this.rollData.attrKey = String(event.currentTarget.value)
|
|
||||||
})
|
|
||||||
html.find('#runemode').change(async (event) => {
|
|
||||||
this.rollData.runemode = String(event.currentTarget.value)
|
|
||||||
})
|
|
||||||
html.find('#runeame').change(async (event) => {
|
|
||||||
this.rollData.runeame = Number(event.currentTarget.value)
|
|
||||||
})
|
|
||||||
html.find('#doubleD20').change(async (event) => {
|
|
||||||
this.rollData.doubleD20 = event.currentTarget.checked
|
|
||||||
})
|
|
||||||
html.find('#charmeDice').change(async (event) => {
|
|
||||||
this.rollData.charmeDice = String(event.currentTarget.value)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -23,7 +23,8 @@ export class WastelandUtility {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async init() {
|
static async init() {
|
||||||
Hooks.on('renderChatLog', (log, html, data) => WastelandUtility.chatListeners(html))
|
Hooks.on('renderChatLog', (log, html, data) => WastelandUtility.chatListeners(html))
|
||||||
Hooks.on("getChatLogEntryContext", (html, options) => WastelandUtility.chatRollMenu(html, options))
|
Hooks.on('renderChatMessageHTML', (message, html, data) => WastelandUtility.chatListeners(html))
|
||||||
|
Hooks.on("getChatMessageContextOptions", (html, options) => WastelandUtility.chatRollMenu(html, options))
|
||||||
|
|
||||||
Hooks.on("getCombatTrackerEntryContext", (html, options) => {
|
Hooks.on("getCombatTrackerEntryContext", (html, options) => {
|
||||||
WastelandUtility.pushInitiativeOptions(html, options);
|
WastelandUtility.pushInitiativeOptions(html, options);
|
||||||
@@ -112,11 +113,8 @@ export class WastelandUtility {
|
|||||||
const skills = await WastelandUtility.loadCompendium("fvtt-wasteland.skills")
|
const skills = await WastelandUtility.loadCompendium("fvtt-wasteland.skills")
|
||||||
this.skills = skills.map(i => i.toObject())
|
this.skills = skills.map(i => i.toObject())
|
||||||
|
|
||||||
game.system.wasteland.config.listeNiveauSkill = WastelandUtility.createDirectOptionList(0, 10)
|
// Note: listeNiveauSkill, listeNiveauCreature, etc. are now created in init hook
|
||||||
game.system.wasteland.config.listeNiveauCreature = WastelandUtility.createDirectOptionList(0, 35)
|
// to be available immediately when sheets are opened
|
||||||
game.system.wasteland.config.modificateurOptions = WastelandUtility.createArrayOptionList(-15, 15)
|
|
||||||
game.system.wasteland.config.pointsAmeOptions = WastelandUtility.createDirectOptionList(0, 20)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -154,15 +152,41 @@ export class WastelandUtility {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async chatListeners(html) {
|
static async chatListeners(html) {
|
||||||
|
|
||||||
html.on("click", '.predilection-reroll', async event => {
|
$(html).on("click", '.predilection-reroll', async event => {
|
||||||
let predIdx = $(event.currentTarget).data("predilection-index")
|
let predIdx = $(event.currentTarget).data("predilection-index")
|
||||||
let messageId = WastelandUtility.findChatMessageId(event.currentTarget)
|
let messageId = WastelandUtility.findChatMessageId(event.currentTarget)
|
||||||
let message = game.messages.get(messageId)
|
let message = game.messages.get(messageId)
|
||||||
let rollData = message.getFlag("world", "wasteland-roll")
|
let rollData = message.getFlag("world", "wasteland-roll")
|
||||||
let actor = WastelandUtility.getActorFromRollData(rollData)
|
let actor = WastelandUtility.getActorFromRollData(rollData)
|
||||||
|
|
||||||
|
// Sauvegarder le résultat précédent
|
||||||
|
let previousResult = {
|
||||||
|
diceResult: rollData.diceResult,
|
||||||
|
finalResult: rollData.finalResult,
|
||||||
|
diceFormula: rollData.diceFormula
|
||||||
|
}
|
||||||
|
|
||||||
|
// Récupérer la prédilection utilisée
|
||||||
|
let predilectionUsed = foundry.utils.duplicate(rollData.competence.system.predilections[predIdx])
|
||||||
|
|
||||||
|
// Marquer la prédilection comme utilisée
|
||||||
await actor.setPredilectionUsed(rollData.competence._id, predIdx)
|
await actor.setPredilectionUsed(rollData.competence._id, predIdx)
|
||||||
|
|
||||||
|
// Mettre à jour la compétence dans rollData
|
||||||
rollData.competence = foundry.utils.duplicate(actor.getCompetence(rollData.competence._id))
|
rollData.competence = foundry.utils.duplicate(actor.getCompetence(rollData.competence._id))
|
||||||
await WastelandUtility.rollWasteland(rollData)
|
|
||||||
|
// Lancer le reroll avec prédilection
|
||||||
|
await WastelandUtility.rollWastelandPredilection(rollData, predilectionUsed, previousResult)
|
||||||
|
})
|
||||||
|
|
||||||
|
$(html).on("click", '.arme-roll-degats', async event => {
|
||||||
|
let messageId = WastelandUtility.findChatMessageId(event.currentTarget)
|
||||||
|
let message = game.messages.get(messageId)
|
||||||
|
let rollData = message.getFlag("world", "wasteland-roll")
|
||||||
|
if (rollData && rollData.arme) {
|
||||||
|
let actor = WastelandUtility.getActorFromRollData(rollData)
|
||||||
|
await actor.rollArmeDegats(rollData.arme._id)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,10 +194,12 @@ export class WastelandUtility {
|
|||||||
static async preloadHandlebarsTemplates() {
|
static async preloadHandlebarsTemplates() {
|
||||||
|
|
||||||
const templatePaths = [
|
const templatePaths = [
|
||||||
'systems/fvtt-wasteland/templates/editor-notes-gm.html',
|
'systems/fvtt-wasteland/templates/editor-notes-gm.hbs',
|
||||||
'systems/fvtt-wasteland/templates/partial-item-description.html'
|
'systems/fvtt-wasteland/templates/partial-item-description.hbs',
|
||||||
|
'systems/fvtt-wasteland/templates/partial-item-header.hbs',
|
||||||
|
'systems/fvtt-wasteland/templates/partial-item-nav.hbs'
|
||||||
]
|
]
|
||||||
return loadTemplates(templatePaths);
|
return foundry.applications.handlebars.loadTemplates(templatePaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -356,16 +382,19 @@ export class WastelandUtility {
|
|||||||
if (rollData.attrKey == "tochoose") { // No attr selected, force address
|
if (rollData.attrKey == "tochoose") { // No attr selected, force address
|
||||||
rollData.attrKey = "adr"
|
rollData.attrKey = "adr"
|
||||||
}
|
}
|
||||||
if (!rollData.attr) {
|
if (!rollData.attr && actor && actor.system.attributs && actor.system.attributs[rollData.attrKey]) {
|
||||||
rollData.actionImg = "systems/fvtt-wasteland/assets/icons/" + actor.system.attributs[rollData.attrKey].labelnorm + ".webp"
|
|
||||||
rollData.attr = foundry.utils.duplicate(actor.system.attributs[rollData.attrKey])
|
rollData.attr = foundry.utils.duplicate(actor.system.attributs[rollData.attrKey])
|
||||||
|
if (rollData.attr.labelnorm) {
|
||||||
|
rollData.actionImg = "systems/fvtt-wasteland/assets/icons/" + rollData.attr.labelnorm + ".webp"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rollData.charme) {
|
if (rollData.charme) {
|
||||||
rollData.diceFormula = rollData.charmeDice
|
rollData.diceFormula = rollData.charmeDice
|
||||||
} else {
|
} else {
|
||||||
rollData.diceFormula = rollData.mainDice
|
rollData.diceFormula = rollData.mainDice
|
||||||
if (rollData.doubleD20) { // Multiply result !
|
// Double D20 ne s'applique que si on lance un D20, pas un D10
|
||||||
|
if (rollData.doubleD20 && rollData.mainDice === "1d20") {
|
||||||
rollData.diceFormula += "*2"
|
rollData.diceFormula += "*2"
|
||||||
if (!rollData.isReroll) {
|
if (!rollData.isReroll) {
|
||||||
actor.changeEclat(-1)
|
actor.changeEclat(-1)
|
||||||
@@ -377,14 +406,55 @@ export class WastelandUtility {
|
|||||||
if (rollData.competence) {
|
if (rollData.competence) {
|
||||||
rollData.predilections = foundry.utils.duplicate(rollData.competence.system.predilections.filter(pred => !pred.used) || [])
|
rollData.predilections = foundry.utils.duplicate(rollData.competence.system.predilections.filter(pred => !pred.used) || [])
|
||||||
let compmod = (rollData.competence.system.niveau == 0) ? -3 : 0
|
let compmod = (rollData.competence.system.niveau == 0) ? -3 : 0
|
||||||
rollData.diceFormula += `+${rollData.attr.value}+${rollData.competence.system.niveau}+${rollData.modificateur}+${compmod}`
|
let attrValue = rollData.attr?.value || 0
|
||||||
|
rollData.diceFormula += `+${attrValue}+${rollData.competence.system.niveau}+${rollData.modificateur}+${compmod}`
|
||||||
} else {
|
} else {
|
||||||
rollData.diceFormula += `+${rollData.attr.value}*2+${rollData.modificateur}`
|
let attrValue = rollData.attr?.value || 0
|
||||||
|
rollData.diceFormula += `+${attrValue}*2+${rollData.modificateur}`
|
||||||
}
|
}
|
||||||
if (rollData.arme && rollData.arme.type == "arme") {
|
if (rollData.arme && rollData.arme.type == "arme") {
|
||||||
rollData.diceFormula += `+${rollData.arme.system.bonusmaniementoff}`
|
rollData.diceFormula += `+${rollData.arme.system.bonusmaniementoff}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply desavantages (tactical advantages)
|
||||||
|
let desavantagesBonus = 0
|
||||||
|
if (rollData.desavantages) {
|
||||||
|
for (let desavantage in rollData.desavantages) {
|
||||||
|
if (rollData.desavantages[desavantage]) {
|
||||||
|
desavantagesBonus += 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
desavantagesBonus = Math.min(15, desavantagesBonus)
|
||||||
|
if (desavantagesBonus > 0) {
|
||||||
|
rollData.diceFormula += `+${desavantagesBonus}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monté ?
|
||||||
|
if (rollData.isMonte) {
|
||||||
|
rollData.diceFormula += "+5"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specific modifiers for ranged combat
|
||||||
|
if (rollData.arme?.system?.isDistance) {
|
||||||
|
if (rollData.visee) {
|
||||||
|
rollData.diceFormula += "+5"
|
||||||
|
}
|
||||||
|
if (rollData.cibleconsciente && rollData.defender) {
|
||||||
|
rollData.diceFormula += `-${rollData.defender.system.attributs.adr.value}`
|
||||||
|
}
|
||||||
|
if (rollData.ciblecourt) {
|
||||||
|
if (rollData.difficulte <= 15) { // Portée courte ou moins
|
||||||
|
rollData.diceFormula += `-5`
|
||||||
|
} else {
|
||||||
|
rollData.diceFormula += `-10`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rollData.typeCouvert && rollData.typeCouvert != "aucun" && rollData.config.couverts[rollData.typeCouvert]) {
|
||||||
|
rollData.diceFormula += `+${rollData.config.couverts[rollData.typeCouvert].value}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let myRoll = await new Roll(rollData.diceFormula).roll()
|
let myRoll = await new Roll(rollData.diceFormula).roll()
|
||||||
await this.showDiceSoNice(myRoll, game.settings.get("core", "rollMode"))
|
await this.showDiceSoNice(myRoll, game.settings.get("core", "rollMode"))
|
||||||
rollData.roll = foundry.utils.duplicate(myRoll)
|
rollData.roll = foundry.utils.duplicate(myRoll)
|
||||||
@@ -395,7 +465,7 @@ export class WastelandUtility {
|
|||||||
await this.computeResult(rollData, actor)
|
await this.computeResult(rollData, actor)
|
||||||
|
|
||||||
this.createChatWithRollMode(rollData.alias, {
|
this.createChatWithRollMode(rollData.alias, {
|
||||||
content: await renderTemplate(`systems/fvtt-wasteland/templates/chat-generic-result.html`, rollData)
|
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-wasteland/templates/chat-generic-result-v2.hbs`, rollData)
|
||||||
}, rollData)
|
}, rollData)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -413,11 +483,137 @@ export class WastelandUtility {
|
|||||||
await this.computeResult(rollData)
|
await this.computeResult(rollData)
|
||||||
|
|
||||||
this.createChatWithRollMode(rollData.alias, {
|
this.createChatWithRollMode(rollData.alias, {
|
||||||
content: await renderTemplate(`systems/fvtt-wasteland/templates/chat-generic-result.html`, rollData)
|
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-wasteland/templates/chat-generic-result-v2.hbs`, rollData)
|
||||||
}, rollData)
|
}, rollData)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async rollWastelandPredilection(rollData, predilectionUsed, previousResult) {
|
||||||
|
// Sauvegarder le premier résultat
|
||||||
|
rollData.firstRoll = {
|
||||||
|
diceResult: previousResult.diceResult,
|
||||||
|
finalResult: previousResult.finalResult,
|
||||||
|
diceFormula: previousResult.diceFormula
|
||||||
|
}
|
||||||
|
rollData.predilectionUsed = predilectionUsed
|
||||||
|
rollData.isPredilectionReroll = true
|
||||||
|
|
||||||
|
let actor = WastelandUtility.getActorFromRollData(rollData)
|
||||||
|
if (rollData.attrKey == "tochoose") {
|
||||||
|
rollData.attrKey = "adr"
|
||||||
|
}
|
||||||
|
if (!rollData.attr && actor && actor.system.attributs && actor.system.attributs[rollData.attrKey]) {
|
||||||
|
rollData.attr = foundry.utils.duplicate(actor.system.attributs[rollData.attrKey])
|
||||||
|
if (rollData.attr.labelnorm) {
|
||||||
|
rollData.actionImg = "systems/fvtt-wasteland/assets/icons/" + rollData.attr.labelnorm + ".webp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rollData.charme) {
|
||||||
|
rollData.diceFormula = rollData.charmeDice
|
||||||
|
} else {
|
||||||
|
rollData.diceFormula = rollData.mainDice
|
||||||
|
// Double D20 ne s'applique que si on lance un D20, pas un D10
|
||||||
|
if (rollData.doubleD20 && rollData.mainDice === "1d20") {
|
||||||
|
rollData.diceFormula += "*2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rollData.competence) {
|
||||||
|
rollData.predilections = foundry.utils.duplicate(rollData.competence.system.predilections.filter(pred => !pred.used) || [])
|
||||||
|
let compmod = (rollData.competence.system.niveau == 0) ? -3 : 0
|
||||||
|
let attrValue = rollData.attr?.value || 0
|
||||||
|
rollData.diceFormula += `+${attrValue}+${rollData.competence.system.niveau}+${rollData.modificateur}+${compmod}`
|
||||||
|
} else {
|
||||||
|
let attrValue = rollData.attr?.value || 0
|
||||||
|
rollData.diceFormula += `+${attrValue}*2+${rollData.modificateur}`
|
||||||
|
}
|
||||||
|
if (rollData.arme && rollData.arme.type == "arme") {
|
||||||
|
rollData.diceFormula += `+${rollData.arme.system.bonusmaniementoff}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply desavantages (tactical advantages)
|
||||||
|
if (rollData.desavantages) {
|
||||||
|
let totalDesavantage = 0
|
||||||
|
for (let key in rollData.desavantages) {
|
||||||
|
if (rollData.desavantages[key]) {
|
||||||
|
totalDesavantage += 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalDesavantage = Math.min(totalDesavantage, 15)
|
||||||
|
if (totalDesavantage > 0) {
|
||||||
|
rollData.diceFormula += `+${totalDesavantage}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply mounted bonus
|
||||||
|
if (rollData.isMonte) {
|
||||||
|
rollData.diceFormula += `+5`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply ranged combat modifiers
|
||||||
|
if (rollData.arme && rollData.arme.system && rollData.arme.system.isDistance) {
|
||||||
|
if (rollData.visee) {
|
||||||
|
rollData.diceFormula += `+5`
|
||||||
|
}
|
||||||
|
if (rollData.cibleconsciente && rollData.defender) {
|
||||||
|
let adrMalus = -(rollData.defender.system?.attributs?.adr?.value || 0)
|
||||||
|
rollData.diceFormula += `${adrMalus}`
|
||||||
|
}
|
||||||
|
if (rollData.ciblecourt) {
|
||||||
|
if (rollData.portee === "portee-courte" || rollData.portee === "portee-moyenne") {
|
||||||
|
rollData.diceFormula += `-5`
|
||||||
|
} else {
|
||||||
|
rollData.diceFormula += `-10`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rollData.couvert && rollData.typeCouvertValue) {
|
||||||
|
rollData.diceFormula += `${rollData.typeCouvertValue}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nouveau jet de dé
|
||||||
|
let myRoll = await new Roll(rollData.diceFormula).roll()
|
||||||
|
await this.showDiceSoNice(myRoll, game.settings.get("core", "rollMode"))
|
||||||
|
rollData.roll = foundry.utils.duplicate(myRoll)
|
||||||
|
rollData.diceResult = myRoll.total
|
||||||
|
|
||||||
|
rollData.bonusFormula = "0"
|
||||||
|
if (rollData.charme && rollData.charme.system.bonusmajeur > 0) {
|
||||||
|
rollData.bonusFormula = `${rollData.charme.system.bonusmajeur}d6`
|
||||||
|
rollData.textBonus = "Bonus de Charme"
|
||||||
|
}
|
||||||
|
|
||||||
|
rollData.finalResult = rollData.diceResult
|
||||||
|
let bonusRoll = await new Roll(rollData.bonusFormula).roll()
|
||||||
|
await this.showDiceSoNice(bonusRoll, game.settings.get("core", "rollMode"))
|
||||||
|
rollData.bonusRoll = foundry.utils.duplicate(bonusRoll)
|
||||||
|
rollData.finalResult += rollData.bonusRoll.total
|
||||||
|
|
||||||
|
// Comparer avec le premier jet et garder le meilleur
|
||||||
|
rollData.secondRoll = {
|
||||||
|
diceResult: rollData.diceResult,
|
||||||
|
finalResult: rollData.finalResult
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rollData.firstRoll.finalResult > rollData.finalResult) {
|
||||||
|
// Garder le premier résultat
|
||||||
|
rollData.diceResult = rollData.firstRoll.diceResult
|
||||||
|
rollData.finalResult = rollData.firstRoll.finalResult
|
||||||
|
rollData.keptRoll = "first"
|
||||||
|
} else {
|
||||||
|
// Garder le second résultat
|
||||||
|
rollData.keptRoll = "second"
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.computeResult(rollData)
|
||||||
|
|
||||||
|
this.createChatWithRollMode(rollData.alias, {
|
||||||
|
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-wasteland/templates/chat-generic-result-v2.hbs`, rollData)
|
||||||
|
}, rollData)
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getUsers(filter) {
|
static getUsers(filter) {
|
||||||
return game.users.filter(filter).map(user => user.data._id);
|
return game.users.filter(filter).map(user => user.data._id);
|
||||||
@@ -508,6 +704,7 @@ export class WastelandUtility {
|
|||||||
pointAmeOptions: this.getPointAmeOptions(),
|
pointAmeOptions: this.getPointAmeOptions(),
|
||||||
difficulte: 0,
|
difficulte: 0,
|
||||||
modificateur: 0,
|
modificateur: 0,
|
||||||
|
config: game.system.wasteland.config,
|
||||||
}
|
}
|
||||||
WastelandUtility.updateWithTarget(rollData)
|
WastelandUtility.updateWithTarget(rollData)
|
||||||
return rollData
|
return rollData
|
||||||
@@ -519,6 +716,7 @@ export class WastelandUtility {
|
|||||||
if (target) {
|
if (target) {
|
||||||
rollData.defenderTokenId = target.id
|
rollData.defenderTokenId = target.id
|
||||||
let defender = game.canvas.tokens.get(rollData.defenderTokenId).actor
|
let defender = game.canvas.tokens.get(rollData.defenderTokenId).actor
|
||||||
|
rollData.defender = defender.toObject() // For template access
|
||||||
rollData.armeDefense = defender.getBestDefenseValue()
|
rollData.armeDefense = defender.getBestDefenseValue()
|
||||||
if (rollData.armeDefense) {
|
if (rollData.armeDefense) {
|
||||||
rollData.difficulte = rollData.armeDefense.system.totalDefensif
|
rollData.difficulte = rollData.armeDefense.system.totalDefensif
|
||||||
@@ -535,7 +733,7 @@ export class WastelandUtility {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static applyBonneAventureRoll(li, changed, addedBonus) {
|
static applyBonneAventureRoll(li, changed, addedBonus) {
|
||||||
let msgId = li.data("message-id")
|
let msgId = $(li).data("message-id")
|
||||||
let msg = game.messages.get(msgId)
|
let msg = game.messages.get(msgId)
|
||||||
if (msg) {
|
if (msg) {
|
||||||
let rollData = msg.getFlag("world", "wasteland-roll")
|
let rollData = msg.getFlag("world", "wasteland-roll")
|
||||||
@@ -554,7 +752,7 @@ export class WastelandUtility {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static applyEclatRoll(li, changed, addedBonus) {
|
static applyEclatRoll(li, changed, addedBonus) {
|
||||||
let msgId = li.data("message-id")
|
let msgId = $(li).data("message-id")
|
||||||
let msg = game.messages.get(msgId)
|
let msg = game.messages.get(msgId)
|
||||||
if (msg) {
|
if (msg) {
|
||||||
let rollData = msg.getFlag("world", "wasteland-roll")
|
let rollData = msg.getFlag("world", "wasteland-roll")
|
||||||
@@ -567,11 +765,90 @@ export class WastelandUtility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static cancelBlessure(li) {
|
||||||
|
let msgId = $(li).data("message-id")
|
||||||
|
let msg = game.messages.get(msgId)
|
||||||
|
if (msg) {
|
||||||
|
let rollData = msg.getFlag("world", "wasteland-roll")
|
||||||
|
let actor = WastelandUtility.getActorFromRollData(rollData)
|
||||||
|
|
||||||
|
// Vérifier que l'acteur a au moins 1 point d'éclat
|
||||||
|
if (actor.getEclat() < 1) {
|
||||||
|
ui.notifications.warn("Pas assez de points d'Éclat")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Déduire 1 point d'éclat
|
||||||
|
actor.changeEclat(-1)
|
||||||
|
|
||||||
|
// Annuler la dernière blessure (incrémenter la santé)
|
||||||
|
let currentSante = actor.system.sante.value
|
||||||
|
let maxSante = actor.system.sante.max
|
||||||
|
if (currentSante < maxSante) {
|
||||||
|
actor.update({ 'system.sante.value': currentSante + 1 })
|
||||||
|
ui.notifications.info("Blessure annulée - 1 Point d'Éclat dépensé")
|
||||||
|
} else {
|
||||||
|
ui.notifications.warn("Vous êtes déjà en pleine santé")
|
||||||
|
// Rembourser le point d'éclat
|
||||||
|
actor.changeEclat(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static reloadBA(li) {
|
||||||
|
let msgId = $(li).data("message-id")
|
||||||
|
let msg = game.messages.get(msgId)
|
||||||
|
if (msg) {
|
||||||
|
let rollData = msg.getFlag("world", "wasteland-roll")
|
||||||
|
let actor = WastelandUtility.getActorFromRollData(rollData)
|
||||||
|
|
||||||
|
// Vérifier que l'acteur a au moins 1 point d'éclat
|
||||||
|
if (actor.getEclat() < 1) {
|
||||||
|
ui.notifications.warn("Pas assez de points d'Éclat")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Déduire 1 point d'éclat
|
||||||
|
actor.changeEclat(-1)
|
||||||
|
|
||||||
|
// Recharger les points de Bonne Aventure au maximum
|
||||||
|
let maxBA = actor.system.bonneaventure.base
|
||||||
|
actor.update({ 'system.bonneaventure.actuelle': maxBA })
|
||||||
|
ui.notifications.info(`Points de Bonne Aventure rechargés à ${maxBA} - 1 Point d'Éclat dépensé`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static incDecSante(li, value, costBA) {
|
||||||
|
let msgId = $(li).data("message-id")
|
||||||
|
let msg = game.messages.get(msgId)
|
||||||
|
if (msg) {
|
||||||
|
let rollData = msg.getFlag("world", "wasteland-roll")
|
||||||
|
let actor = WastelandUtility.getActorFromRollData(rollData)
|
||||||
|
|
||||||
|
// Vérifier que l'acteur a assez de points de Bonne Aventure
|
||||||
|
if (actor.getBonneAventure() < costBA) {
|
||||||
|
ui.notifications.warn("Pas assez de points de Bonne Aventure")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Déduire les points de Bonne Aventure
|
||||||
|
actor.changeBonneAventure(-costBA)
|
||||||
|
|
||||||
|
// Incrémenter la santé
|
||||||
|
actor.incDecSante(value)
|
||||||
|
|
||||||
|
ui.notifications.info(`+${value} Point(s) de Santé - ${costBA} Point(s) de Bonne Aventure dépensé(s)`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static chatRollMenu(html, options) {
|
static chatRollMenu(html, options) {
|
||||||
let canApply = li => canvas.tokens.controlled.length && li.find(".wasteland-roll").length
|
let canApply = li => canvas.tokens.controlled.length && li.find(".wasteland-roll").length
|
||||||
let hasBA = function (li) {
|
let hasBA = function (li) {
|
||||||
let message = game.messages.get(li.attr("data-message-id"))
|
let message = game.messages.get($(li).attr("data-message-id"))
|
||||||
let rollData = message.getFlag("world", "wasteland-roll")
|
let rollData = message.getFlag("world", "wasteland-roll")
|
||||||
if (rollData?.actorId) {
|
if (rollData?.actorId) {
|
||||||
let actor = game.actors.get(rollData.actorId)
|
let actor = game.actors.get(rollData.actorId)
|
||||||
@@ -581,7 +858,7 @@ export class WastelandUtility {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
let hasBA2 = function (li) {
|
let hasBA2 = function (li) {
|
||||||
let message = game.messages.get(li.attr("data-message-id"))
|
let message = game.messages.get($(li).attr("data-message-id"))
|
||||||
let rollData = message.getFlag("world", "wasteland-roll")
|
let rollData = message.getFlag("world", "wasteland-roll")
|
||||||
if (rollData?.actorId) {
|
if (rollData?.actorId) {
|
||||||
let actor = game.actors.get(rollData.actorId)
|
let actor = game.actors.get(rollData.actorId)
|
||||||
@@ -591,7 +868,7 @@ export class WastelandUtility {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
let hasBA3 = function (li) {
|
let hasBA3 = function (li) {
|
||||||
let message = game.messages.get(li.attr("data-message-id"))
|
let message = game.messages.get($(li).attr("data-message-id"))
|
||||||
let rollData = message.getFlag("world", "wasteland-roll")
|
let rollData = message.getFlag("world", "wasteland-roll")
|
||||||
if (rollData?.actorId) {
|
if (rollData?.actorId) {
|
||||||
let actor = game.actors.get(rollData.actorId)
|
let actor = game.actors.get(rollData.actorId)
|
||||||
@@ -601,7 +878,7 @@ export class WastelandUtility {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
let hasPE = function (li) {
|
let hasPE = function (li) {
|
||||||
let message = game.messages.get(li.attr("data-message-id"))
|
let message = game.messages.get($(li).attr("data-message-id"))
|
||||||
let rollData = message.getFlag("world", "wasteland-roll")
|
let rollData = message.getFlag("world", "wasteland-roll")
|
||||||
if (rollData?.actorId) {
|
if (rollData?.actorId) {
|
||||||
let actor = game.actors.get(rollData.actorId)
|
let actor = game.actors.get(rollData.actorId)
|
||||||
@@ -611,7 +888,7 @@ export class WastelandUtility {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
let hasPredilection = function (li) {
|
let hasPredilection = function (li) {
|
||||||
let message = game.messages.get(li.attr("data-message-id"))
|
let message = game.messages.get($(li).attr("data-message-id"))
|
||||||
let rollData = message.getFlag("world", "wasteland-roll")
|
let rollData = message.getFlag("world", "wasteland-roll")
|
||||||
if (rollData.competence) {
|
if (rollData.competence) {
|
||||||
let nbPred = rollData.competence.data.predilections.filter(pred => !pred.used).length
|
let nbPred = rollData.competence.data.predilections.filter(pred => !pred.used).length
|
||||||
@@ -620,7 +897,7 @@ export class WastelandUtility {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
let canCompetenceDouble = function (li) {
|
let canCompetenceDouble = function (li) {
|
||||||
let message = game.messages.get(li.attr("data-message-id"))
|
let message = game.messages.get($(li).attr("data-message-id"))
|
||||||
let rollData = message.getFlag("world", "wasteland-roll")
|
let rollData = message.getFlag("world", "wasteland-roll")
|
||||||
if (rollData.competence) {
|
if (rollData.competence) {
|
||||||
return rollData.competence.data.doublebonus
|
return rollData.competence.data.doublebonus
|
||||||
@@ -640,7 +917,7 @@ export class WastelandUtility {
|
|||||||
name: "Gain de 1 Point de Santé / 24 heure (1 point de Bonne Aventure)",
|
name: "Gain de 1 Point de Santé / 24 heure (1 point de Bonne Aventure)",
|
||||||
icon: "<i class='fas fa-user-plus'></i>",
|
icon: "<i class='fas fa-user-plus'></i>",
|
||||||
condition: canApply && hasBA,
|
condition: canApply && hasBA,
|
||||||
callback: li => WastelandUtility.incDecSante(1)
|
callback: li => WastelandUtility.incDecSante(li, 1, 1)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
options.push(
|
options.push(
|
||||||
@@ -648,7 +925,7 @@ export class WastelandUtility {
|
|||||||
name: "Gain de 2 Points de Santé / 24 heure (2 points de Bonne Aventure)",
|
name: "Gain de 2 Points de Santé / 24 heure (2 points de Bonne Aventure)",
|
||||||
icon: "<i class='fas fa-user-plus'></i>",
|
icon: "<i class='fas fa-user-plus'></i>",
|
||||||
condition: canApply && hasBA2,
|
condition: canApply && hasBA2,
|
||||||
callback: li => WastelandUtility.incDecSante(2)
|
callback: li => WastelandUtility.incDecSante(li, 2, 2)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
options.push(
|
options.push(
|
||||||
@@ -704,30 +981,24 @@ export class WastelandUtility {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async confirmDelete(actorSheet, li) {
|
static async confirmDelete(actorSheet, li) {
|
||||||
let itemId = li.data("item-id");
|
const itemId = li.dataset.itemId
|
||||||
let msgTxt = "<p>Are you sure to remove this Item ?";
|
if (!itemId) return
|
||||||
let buttons = {
|
|
||||||
delete: {
|
const item = actorSheet.document.items.get(itemId)
|
||||||
icon: '<i class="fas fa-check"></i>',
|
if (!item) return
|
||||||
label: "Yes, remove it",
|
|
||||||
callback: () => {
|
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||||
actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]);
|
window: { title: "Confirmer la suppression" },
|
||||||
li.slideUp(200, () => actorSheet.render(false));
|
content: `<p>Êtes-vous sûr de vouloir supprimer <strong>${item.name}</strong> ?</p>`,
|
||||||
}
|
rejectClose: false,
|
||||||
},
|
modal: true,
|
||||||
cancel: {
|
yes: { label: "Supprimer", icon: "fa-trash" },
|
||||||
icon: '<i class="fas fa-times"></i>',
|
no: { label: "Annuler", icon: "fa-times" }
|
||||||
label: "Cancel"
|
})
|
||||||
}
|
|
||||||
|
if (confirmed) {
|
||||||
|
await actorSheet.document.deleteEmbeddedDocuments("Item", [itemId])
|
||||||
}
|
}
|
||||||
msgTxt += "</p>";
|
|
||||||
let d = new Dialog({
|
|
||||||
title: "Confirm removal",
|
|
||||||
content: msgTxt,
|
|
||||||
buttons: buttons,
|
|
||||||
default: "cancel"
|
|
||||||
});
|
|
||||||
d.render(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
4971
package-lock.json
generated
Normal file
4971
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
16
package.json
Normal file
16
package.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "fvtt-wasteland",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Wasteland RPG for FoundryVTT - French",
|
||||||
|
"scripts": {
|
||||||
|
"build": "gulp build",
|
||||||
|
"watch": "gulp watch"
|
||||||
|
},
|
||||||
|
"author": "Uberwald/LeRatierBretonnien",
|
||||||
|
"license": "SEE LICENSE IN LICENCE.txt",
|
||||||
|
"devDependencies": {
|
||||||
|
"gulp": "^4.0.2",
|
||||||
|
"gulp-less": "^5.0.0",
|
||||||
|
"gulp-sourcemaps": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
BIN
packs/armes/000211.ldb
Normal file
BIN
packs/armes/000211.ldb
Normal file
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000199
|
MANIFEST-000224
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
2024/10/23-20:49:34.562318 7fee7b4006c0 Recovering log #197
|
2026/01/10-09:44:14.205626 7f1c56bff6c0 Recovering log #222
|
||||||
2024/10/23-20:49:34.572510 7fee7b4006c0 Delete type=3 #195
|
2026/01/10-09:44:14.218871 7f1c56bff6c0 Delete type=3 #220
|
||||||
2024/10/23-20:49:34.572580 7fee7b4006c0 Delete type=0 #197
|
2026/01/10-09:44:14.219004 7f1c56bff6c0 Delete type=0 #222
|
||||||
2024/10/23-20:50:51.301785 7fee796006c0 Level-0 table #202: started
|
|
||||||
2024/10/23-20:50:51.301810 7fee796006c0 Level-0 table #202: 0 bytes OK
|
|
||||||
2024/10/23-20:50:51.308254 7fee796006c0 Delete type=0 #200
|
|
||||||
2024/10/23-20:50:51.321194 7fee796006c0 Manual compaction at level-0 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end)
|
|
||||||
2024/10/23-20:50:51.321237 7fee796006c0 Manual compaction at level-1 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
2024/06/08-21:15:33.864288 7fadb8c006c0 Recovering log #193
|
2026/01/10-09:33:50.449402 7f1c553fc6c0 Recovering log #218
|
||||||
2024/06/08-21:15:33.874053 7fadb8c006c0 Delete type=3 #191
|
2026/01/10-09:33:50.499238 7f1c553fc6c0 Delete type=3 #216
|
||||||
2024/06/08-21:15:33.874106 7fadb8c006c0 Delete type=0 #193
|
2026/01/10-09:33:50.499325 7f1c553fc6c0 Delete type=0 #218
|
||||||
2024/06/08-21:15:57.231395 7fadb1a006c0 Level-0 table #198: started
|
2026/01/10-09:42:25.332397 7f1c54bfb6c0 Level-0 table #223: started
|
||||||
2024/06/08-21:15:57.231418 7fadb1a006c0 Level-0 table #198: 0 bytes OK
|
2026/01/10-09:42:25.332474 7f1c54bfb6c0 Level-0 table #223: 0 bytes OK
|
||||||
2024/06/08-21:15:57.238165 7fadb1a006c0 Delete type=0 #196
|
2026/01/10-09:42:25.395595 7f1c54bfb6c0 Delete type=0 #221
|
||||||
2024/06/08-21:15:57.238384 7fadb1a006c0 Manual compaction at level-0 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end)
|
2026/01/10-09:42:25.519167 7f1c54bfb6c0 Manual compaction at level-0 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end)
|
||||||
2024/06/08-21:15:57.238414 7fadb1a006c0 Manual compaction at level-1 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end)
|
2026/01/10-09:42:25.519295 7f1c54bfb6c0 Manual compaction at level-1 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
BIN
packs/armes/MANIFEST-000224
Normal file
BIN
packs/armes/MANIFEST-000224
Normal file
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000060
|
MANIFEST-000085
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
2024/10/23-20:49:34.600131 7fee80e006c0 Recovering log #58
|
2026/01/10-09:44:14.267526 7f1c563fe6c0 Recovering log #83
|
||||||
2024/10/23-20:49:34.610075 7fee80e006c0 Delete type=3 #56
|
2026/01/10-09:44:14.284469 7f1c563fe6c0 Delete type=3 #81
|
||||||
2024/10/23-20:49:34.610136 7fee80e006c0 Delete type=0 #58
|
2026/01/10-09:44:14.284596 7f1c563fe6c0 Delete type=0 #83
|
||||||
2024/10/23-20:50:51.295734 7fee796006c0 Level-0 table #63: started
|
|
||||||
2024/10/23-20:50:51.295761 7fee796006c0 Level-0 table #63: 0 bytes OK
|
|
||||||
2024/10/23-20:50:51.301677 7fee796006c0 Delete type=0 #61
|
|
||||||
2024/10/23-20:50:51.321172 7fee796006c0 Manual compaction at level-0 from '!items!PqP7BWEkK7aK65yH' @ 72057594037927935 : 1 .. '!items!irEA0eyE731viEYl' @ 0 : 0; will stop at (end)
|
|
||||||
2024/10/23-20:50:51.321229 7fee796006c0 Manual compaction at level-1 from '!items!PqP7BWEkK7aK65yH' @ 72057594037927935 : 1 .. '!items!irEA0eyE731viEYl' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
2024/06/08-21:15:33.902106 7fadb2a006c0 Recovering log #54
|
2026/01/10-09:33:50.652107 7f1c563fe6c0 Recovering log #79
|
||||||
2024/06/08-21:15:33.912559 7fadb2a006c0 Delete type=3 #52
|
2026/01/10-09:33:50.742710 7f1c563fe6c0 Delete type=3 #77
|
||||||
2024/06/08-21:15:33.912651 7fadb2a006c0 Delete type=0 #54
|
2026/01/10-09:33:50.742808 7f1c563fe6c0 Delete type=0 #79
|
||||||
2024/06/08-21:15:57.217278 7fadb1a006c0 Level-0 table #59: started
|
2026/01/10-09:42:25.395879 7f1c54bfb6c0 Level-0 table #84: started
|
||||||
2024/06/08-21:15:57.217331 7fadb1a006c0 Level-0 table #59: 0 bytes OK
|
2026/01/10-09:42:25.395959 7f1c54bfb6c0 Level-0 table #84: 0 bytes OK
|
||||||
2024/06/08-21:15:57.224892 7fadb1a006c0 Delete type=0 #57
|
2026/01/10-09:42:25.461875 7f1c54bfb6c0 Delete type=0 #82
|
||||||
2024/06/08-21:15:57.238359 7fadb1a006c0 Manual compaction at level-0 from '!items!PqP7BWEkK7aK65yH' @ 72057594037927935 : 1 .. '!items!irEA0eyE731viEYl' @ 0 : 0; will stop at (end)
|
2026/01/10-09:42:25.519225 7f1c54bfb6c0 Manual compaction at level-0 from '!items!PqP7BWEkK7aK65yH' @ 72057594037927935 : 1 .. '!items!irEA0eyE731viEYl' @ 0 : 0; will stop at (end)
|
||||||
2024/06/08-21:15:57.238399 7fadb1a006c0 Manual compaction at level-1 from '!items!PqP7BWEkK7aK65yH' @ 72057594037927935 : 1 .. '!items!irEA0eyE731viEYl' @ 0 : 0; will stop at (end)
|
2026/01/10-09:42:25.519316 7f1c54bfb6c0 Manual compaction at level-1 from '!items!PqP7BWEkK7aK65yH' @ 72057594037927935 : 1 .. '!items!irEA0eyE731viEYl' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
BIN
packs/artifex/MANIFEST-000085
Normal file
BIN
packs/artifex/MANIFEST-000085
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs/bestiaire/000084.ldb
Normal file
BIN
packs/bestiaire/000084.ldb
Normal file
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000072
|
MANIFEST-000097
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
2024/10/23-20:49:34.456483 7fee7b4006c0 Recovering log #70
|
2026/01/10-09:44:14.021312 7f1c55bfd6c0 Recovering log #95
|
||||||
2024/10/23-20:49:34.466636 7fee7b4006c0 Delete type=3 #68
|
2026/01/10-09:44:14.040496 7f1c55bfd6c0 Delete type=3 #93
|
||||||
2024/10/23-20:49:34.466698 7fee7b4006c0 Delete type=0 #70
|
2026/01/10-09:44:14.040627 7f1c55bfd6c0 Delete type=0 #95
|
||||||
2024/10/23-20:50:51.249627 7fee796006c0 Level-0 table #75: started
|
|
||||||
2024/10/23-20:50:51.249668 7fee796006c0 Level-0 table #75: 0 bytes OK
|
|
||||||
2024/10/23-20:50:51.255757 7fee796006c0 Delete type=0 #73
|
|
||||||
2024/10/23-20:50:51.269192 7fee796006c0 Manual compaction at level-0 from '!actors!S7FhBajQ5KKhIpj6' @ 72057594037927935 : 1 .. '!folders!BHMWTRHF2lNlAK8u' @ 0 : 0; will stop at (end)
|
|
||||||
2024/10/23-20:50:51.269229 7fee796006c0 Manual compaction at level-1 from '!actors!S7FhBajQ5KKhIpj6' @ 72057594037927935 : 1 .. '!folders!BHMWTRHF2lNlAK8u' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
2024/06/08-21:15:33.757474 7fadb8c006c0 Recovering log #66
|
2026/01/10-09:33:49.998930 7f1c56bff6c0 Recovering log #91
|
||||||
2024/06/08-21:15:33.767507 7fadb8c006c0 Delete type=3 #64
|
2026/01/10-09:33:50.047028 7f1c56bff6c0 Delete type=3 #89
|
||||||
2024/06/08-21:15:33.767557 7fadb8c006c0 Delete type=0 #66
|
2026/01/10-09:33:50.047160 7f1c56bff6c0 Delete type=0 #91
|
||||||
2024/06/08-21:15:57.168619 7fadb1a006c0 Level-0 table #71: started
|
2026/01/10-09:42:24.848889 7f1c54bfb6c0 Level-0 table #96: started
|
||||||
2024/06/08-21:15:57.168658 7fadb1a006c0 Level-0 table #71: 0 bytes OK
|
2026/01/10-09:42:24.848942 7f1c54bfb6c0 Level-0 table #96: 0 bytes OK
|
||||||
2024/06/08-21:15:57.176105 7fadb1a006c0 Delete type=0 #69
|
2026/01/10-09:42:24.909912 7f1c54bfb6c0 Delete type=0 #94
|
||||||
2024/06/08-21:15:57.182883 7fadb1a006c0 Manual compaction at level-0 from '!actors!S7FhBajQ5KKhIpj6' @ 72057594037927935 : 1 .. '!folders!BHMWTRHF2lNlAK8u' @ 0 : 0; will stop at (end)
|
2026/01/10-09:42:25.030500 7f1c54bfb6c0 Manual compaction at level-0 from '!actors!S7FhBajQ5KKhIpj6' @ 72057594037927935 : 1 .. '!folders!BHMWTRHF2lNlAK8u' @ 0 : 0; will stop at (end)
|
||||||
2024/06/08-21:15:57.182910 7fadb1a006c0 Manual compaction at level-1 from '!actors!S7FhBajQ5KKhIpj6' @ 72057594037927935 : 1 .. '!folders!BHMWTRHF2lNlAK8u' @ 0 : 0; will stop at (end)
|
2026/01/10-09:42:25.030611 7f1c54bfb6c0 Manual compaction at level-1 from '!actors!S7FhBajQ5KKhIpj6' @ 72057594037927935 : 1 .. '!folders!BHMWTRHF2lNlAK8u' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
BIN
packs/bestiaire/MANIFEST-000097
Normal file
BIN
packs/bestiaire/MANIFEST-000097
Normal file
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000060
|
MANIFEST-000085
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
2024/10/23-20:49:34.612874 7fee7b4006c0 Recovering log #58
|
2026/01/10-09:44:14.288059 7f1c553fc6c0 Recovering log #83
|
||||||
2024/10/23-20:49:34.622528 7fee7b4006c0 Delete type=3 #56
|
2026/01/10-09:44:14.307028 7f1c553fc6c0 Delete type=3 #81
|
||||||
2024/10/23-20:49:34.622591 7fee7b4006c0 Delete type=0 #58
|
2026/01/10-09:44:14.307153 7f1c553fc6c0 Delete type=0 #83
|
||||||
2024/10/23-20:50:51.321403 7fee796006c0 Level-0 table #63: started
|
|
||||||
2024/10/23-20:50:51.321447 7fee796006c0 Level-0 table #63: 0 bytes OK
|
|
||||||
2024/10/23-20:50:51.327468 7fee796006c0 Delete type=0 #61
|
|
||||||
2024/10/23-20:50:51.348060 7fee796006c0 Manual compaction at level-0 from '!items!JzGNaagJD2jLi9tH' @ 72057594037927935 : 1 .. '!items!LaiHuZ30K4iJr6ce' @ 0 : 0; will stop at (end)
|
|
||||||
2024/10/23-20:50:51.348136 7fee796006c0 Manual compaction at level-1 from '!items!JzGNaagJD2jLi9tH' @ 72057594037927935 : 1 .. '!items!LaiHuZ30K4iJr6ce' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
2024/06/08-21:15:33.915184 7fadb8c006c0 Recovering log #54
|
2026/01/10-09:33:50.746372 7f1c553fc6c0 Recovering log #79
|
||||||
2024/06/08-21:15:33.925245 7fadb8c006c0 Delete type=3 #52
|
2026/01/10-09:33:50.798633 7f1c553fc6c0 Delete type=3 #77
|
||||||
2024/06/08-21:15:33.925299 7fadb8c006c0 Delete type=0 #54
|
2026/01/10-09:33:50.798745 7f1c553fc6c0 Delete type=0 #79
|
||||||
2024/06/08-21:15:57.258825 7fadb1a006c0 Level-0 table #59: started
|
2026/01/10-09:42:25.580579 7f1c54bfb6c0 Level-0 table #84: started
|
||||||
2024/06/08-21:15:57.258884 7fadb1a006c0 Level-0 table #59: 0 bytes OK
|
2026/01/10-09:42:25.580643 7f1c54bfb6c0 Level-0 table #84: 0 bytes OK
|
||||||
2024/06/08-21:15:57.265178 7fadb1a006c0 Delete type=0 #57
|
2026/01/10-09:42:25.633628 7f1c54bfb6c0 Delete type=0 #82
|
||||||
2024/06/08-21:15:57.265355 7fadb1a006c0 Manual compaction at level-0 from '!items!JzGNaagJD2jLi9tH' @ 72057594037927935 : 1 .. '!items!LaiHuZ30K4iJr6ce' @ 0 : 0; will stop at (end)
|
2026/01/10-09:42:25.776283 7f1c54bfb6c0 Manual compaction at level-0 from '!items!JzGNaagJD2jLi9tH' @ 72057594037927935 : 1 .. '!items!LaiHuZ30K4iJr6ce' @ 0 : 0; will stop at (end)
|
||||||
2024/06/08-21:15:57.265376 7fadb1a006c0 Manual compaction at level-1 from '!items!JzGNaagJD2jLi9tH' @ 72057594037927935 : 1 .. '!items!LaiHuZ30K4iJr6ce' @ 0 : 0; will stop at (end)
|
2026/01/10-09:42:25.776373 7f1c54bfb6c0 Manual compaction at level-1 from '!items!JzGNaagJD2jLi9tH' @ 72057594037927935 : 1 .. '!items!LaiHuZ30K4iJr6ce' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
BIN
packs/capacreature/MANIFEST-000085
Normal file
BIN
packs/capacreature/MANIFEST-000085
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs/equipement/000165.ldb
Normal file
BIN
packs/equipement/000165.ldb
Normal file
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000153
|
MANIFEST-000178
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
2024/10/23-20:49:34.587051 7fee7aa006c0 Recovering log #151
|
2026/01/10-09:44:14.242382 7f1c55bfd6c0 Recovering log #176
|
||||||
2024/10/23-20:49:34.597931 7fee7aa006c0 Delete type=3 #149
|
2026/01/10-09:44:14.263103 7f1c55bfd6c0 Delete type=3 #174
|
||||||
2024/10/23-20:49:34.598050 7fee7aa006c0 Delete type=0 #151
|
2026/01/10-09:44:14.263260 7f1c55bfd6c0 Delete type=0 #176
|
||||||
2024/10/23-20:50:51.314989 7fee796006c0 Level-0 table #156: started
|
|
||||||
2024/10/23-20:50:51.315013 7fee796006c0 Level-0 table #156: 0 bytes OK
|
|
||||||
2024/10/23-20:50:51.320996 7fee796006c0 Delete type=0 #154
|
|
||||||
2024/10/23-20:50:51.321220 7fee796006c0 Manual compaction at level-0 from '!folders!JlP90zkPvPcJDq0q' @ 72057594037927935 : 1 .. '!items!zjMDuxKHKJ4vE5UV' @ 0 : 0; will stop at (end)
|
|
||||||
2024/10/23-20:50:51.321258 7fee796006c0 Manual compaction at level-1 from '!folders!JlP90zkPvPcJDq0q' @ 72057594037927935 : 1 .. '!items!zjMDuxKHKJ4vE5UV' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
2024/06/08-21:15:33.889173 7fadb34006c0 Recovering log #147
|
2026/01/10-09:33:50.554913 7f1c56bff6c0 Recovering log #172
|
||||||
2024/06/08-21:15:33.898942 7fadb34006c0 Delete type=3 #145
|
2026/01/10-09:33:50.649209 7f1c56bff6c0 Delete type=3 #170
|
||||||
2024/06/08-21:15:33.899016 7fadb34006c0 Delete type=0 #147
|
2026/01/10-09:33:50.649312 7f1c56bff6c0 Delete type=0 #172
|
||||||
2024/06/08-21:15:57.225037 7fadb1a006c0 Level-0 table #152: started
|
2026/01/10-09:42:25.462137 7f1c54bfb6c0 Level-0 table #177: started
|
||||||
2024/06/08-21:15:57.225064 7fadb1a006c0 Level-0 table #152: 0 bytes OK
|
2026/01/10-09:42:25.462208 7f1c54bfb6c0 Level-0 table #177: 0 bytes OK
|
||||||
2024/06/08-21:15:57.231253 7fadb1a006c0 Delete type=0 #150
|
2026/01/10-09:42:25.518795 7f1c54bfb6c0 Delete type=0 #175
|
||||||
2024/06/08-21:15:57.238374 7fadb1a006c0 Manual compaction at level-0 from '!folders!JlP90zkPvPcJDq0q' @ 72057594037927935 : 1 .. '!items!zjMDuxKHKJ4vE5UV' @ 0 : 0; will stop at (end)
|
2026/01/10-09:42:25.519253 7f1c54bfb6c0 Manual compaction at level-0 from '!folders!JlP90zkPvPcJDq0q' @ 72057594037927935 : 1 .. '!items!zjMDuxKHKJ4vE5UV' @ 0 : 0; will stop at (end)
|
||||||
2024/06/08-21:15:57.238407 7fadb1a006c0 Manual compaction at level-1 from '!folders!JlP90zkPvPcJDq0q' @ 72057594037927935 : 1 .. '!items!zjMDuxKHKJ4vE5UV' @ 0 : 0; will stop at (end)
|
2026/01/10-09:42:25.519343 7f1c54bfb6c0 Manual compaction at level-1 from '!folders!JlP90zkPvPcJDq0q' @ 72057594037927935 : 1 .. '!items!zjMDuxKHKJ4vE5UV' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user