Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8c79e6f0ba | |||
| 55a3c694db | |||
| 85c970869c | |||
| 97f1f999b1 | |||
| 06c1beabe0 | |||
| 3ac589d411 | |||
| f4d7b99497 | |||
| 92b2a5ef5e | |||
| 3b621d2af7 | |||
| 31b22fad68 | |||
| f08a741708 | |||
| f49d9e2cf4 | |||
| 6ae99aadb0 | |||
| c1a9bfbb04 | |||
| 0fec217528 | |||
| 1d95628a23 | |||
| 4a65bee2dc | |||
| 497c687eb8 | |||
| b0c6b2a3e8 | |||
| 055d853171 | |||
| f1ab04bf32 | |||
| 64eb40abfb | |||
| b5b1d2ca24 | |||
| 5ce0059f1b | |||
| 76a5afc79e | |||
| f130f24a23 | |||
| e47ad95a38 | |||
| fc386487e8 | |||
| bda88c067e | |||
| 4003e0e42b | |||
| a6d811bcda | |||
| 94eb637637 | |||
| 8c58367cdc | |||
| c439ca978c | |||
| ffe1144f2a | |||
| 38ef07d17b | |||
| a8cc2dce4b | |||
| 0fadd0783c | |||
| a55a038d32 | |||
| d012f78881 | |||
| 01e13da234 | |||
| bc09b5050d | |||
| d68001b376 |
@@ -1,54 +0,0 @@
|
|||||||
name: Release Creation
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner."
|
|
||||||
|
|
||||||
#- uses: actions/checkout@v3
|
|
||||||
- uses: RouxAntoine/checkout@v3.5.4
|
|
||||||
with:
|
|
||||||
ref: 'master'
|
|
||||||
|
|
||||||
# get part of the tag after the `v`
|
|
||||||
- name: Extract tag version number
|
|
||||||
id: get_version
|
|
||||||
uses: battila7/get-version-action@v2
|
|
||||||
|
|
||||||
# Substitute the Manifest and Download URLs in the module.json
|
|
||||||
- name: Substitute Manifest and Download Links For Versioned Ones
|
|
||||||
id: sub_manifest_link_version
|
|
||||||
uses: microsoft/variable-substitution@v1
|
|
||||||
with:
|
|
||||||
files: 'system.json'
|
|
||||||
env:
|
|
||||||
version: ${{steps.get_version.outputs.version-without-v}}
|
|
||||||
url: https://www.uberwald.me/gitea/public/fvtt-ecryme
|
|
||||||
manifest: https://www.uberwald.me/gitea/public/fvtt-ecryme/releases/latest/system.json
|
|
||||||
download: https://www.uberwald.me/gitea/public/fvtt-ecryme/releases/download/${{github.event.release.tag_name}}/fvtt-ecryme.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-ecryme.zip system.json template.json README.md LICENSE.txt fonts/ images/ lang/ modules/ packs/ styles/ templates/ translated/
|
|
||||||
|
|
||||||
- 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-ecryme.zip
|
|
||||||
system.json
|
|
||||||
api_key: '${{secrets.RELEASE_TOKEN_UBERWALD}}'
|
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
name: Release Creation
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- run: echo "💡 The ${{ gitea.repository }} repository will be cloned to the runner."
|
||||||
|
|
||||||
|
- uses: https://github.com/RouxAntoine/checkout@v3.5.4
|
||||||
|
|
||||||
|
# get part of the tag after the `v`
|
||||||
|
- name: Extract tag version number
|
||||||
|
id: get_version
|
||||||
|
uses: https://github.com/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: https://github.com/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/${{gitea.repository}}/releases/download/latest/system.json
|
||||||
|
download: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-ecryme-${{github.event.release.tag_name}}.zip
|
||||||
|
|
||||||
|
# Build CSS from LESS
|
||||||
|
- uses: https://github.com/actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
- run: npm install && npm run build
|
||||||
|
|
||||||
|
# Create a zip file with all files required by the system to add to the release
|
||||||
|
- run: |
|
||||||
|
apt update -y
|
||||||
|
apt install -y zip jq
|
||||||
|
|
||||||
|
- run: zip -r ./fvtt-ecryme-${{github.event.release.tag_name}}.zip system.json README.md LICENSE.md changelog.md css/ fonts/ images/ lang/ modules/ styles/ packs/ templates/ translated/ welcome-message-ecryme.html
|
||||||
|
|
||||||
|
- name: Upload release assets
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.ALLOW_PUSH_RELEASE }}
|
||||||
|
TAG_NAME: ${{ github.event.release.tag_name }}
|
||||||
|
REPO: ${{ gitea.repository }}
|
||||||
|
run: |
|
||||||
|
RELEASE_ID=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
"https://www.uberwald.me/gitea/api/v1/repos/$REPO/releases/tags/$TAG_NAME" | jq -r '.id')
|
||||||
|
curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
-H "Content-Type: application/zip" \
|
||||||
|
--data-binary @./fvtt-ecryme-$TAG_NAME.zip \
|
||||||
|
"https://www.uberwald.me/gitea/api/v1/repos/$REPO/releases/$RELEASE_ID/assets?name=fvtt-ecryme-$TAG_NAME.zip"
|
||||||
|
curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--data-binary @./system.json \
|
||||||
|
"https://www.uberwald.me/gitea/api/v1/repos/$REPO/releases/$RELEASE_ID/assets?name=system.json"
|
||||||
|
|
||||||
|
- name: Publish to Foundry server
|
||||||
|
uses: https://github.com/djlechuck/foundryvtt-publish-package-action@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.FOUNDRYVTT_RELEASE_TOKEN }}
|
||||||
|
id: "fvtt-ecryme"
|
||||||
|
version: ${{steps.get_version.outputs.version-without-v}}
|
||||||
|
manifest: "https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/latest/system.json"
|
||||||
|
notes: "https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-ecryme-${{github.event.release.tag_name}}.zip"
|
||||||
|
compatibility-minimum: "13"
|
||||||
|
compatibility-verified: "14"
|
||||||
@@ -1 +1,3 @@
|
|||||||
.history/
|
.history/
|
||||||
|
node_modules/
|
||||||
|
css/ecryme.css
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# Ecryme (FoundryVTT) — agent notes
|
||||||
|
|
||||||
|
**This is a FoundryVTT Game System** (not a module), id `fvtt-ecryme`. Compatible with Foundry v13–v14. Requires `babele` and `lib-wrapper`.
|
||||||
|
|
||||||
|
## Quick commands
|
||||||
|
|
||||||
|
| Command | What |
|
||||||
|
|---------|------|
|
||||||
|
| `npm run build` | Compile `styles/ecryme.less` → `css/ecryme.css` via Gulp |
|
||||||
|
| `npm run watch` | Watch `styles/**/*.less` and rebuild |
|
||||||
|
|
||||||
|
No other npm scripts exist. **No tests, no linter, no typechecker, no TypeScript.** Pure JS ES modules, no bundling.
|
||||||
|
|
||||||
|
## Project structure
|
||||||
|
|
||||||
|
```
|
||||||
|
modules/ # JS source (loaded directly by Foundry, no build step)
|
||||||
|
ecryme-main.js # Entry point — registers documents, sheets, hooks, templates
|
||||||
|
actors/ # Actor document + sheet classes (pc, npc, annency)
|
||||||
|
items/ # Item document + sheet classes (equipment, weapon, trait, spec, maneuver)
|
||||||
|
models/ # Foundry DataModels (extends TypeDataModel) — schema definitions
|
||||||
|
dialogs/ # Roll/confrontation dialog classes
|
||||||
|
app/ # Combat, commands, hotbar, summary app
|
||||||
|
common/ # Config constants + utility helpers (798-line utility)
|
||||||
|
templates/ # Handlebars sheets (actors/, items/, chat/, dialogs/)
|
||||||
|
styles/ # LESS source files (ecryme.less imports all partials)
|
||||||
|
lang/ # fr.json, en.json localization
|
||||||
|
packs/ # LevelDB compendium packs (specialisation, equipment, traits, scenes, maneuvers, help)
|
||||||
|
translated/fr/ # Babele translation JSON files for compendium content
|
||||||
|
images/ # Assets, icons, UI
|
||||||
|
css/ # Compiled CSS output (committed despite being in .gitignore)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
- **App v1 sheets** (`foundry.appv1.sheets.ActorSheet`/`ItemSheet`), not ApplicationV2
|
||||||
|
- **DataModels** replace the deprecated `template.json` (kept as `template.json.SAVED`)
|
||||||
|
- Actor types: `pc`, `npc`, `annency`
|
||||||
|
- Item types: `equipment`, `weapon`, `trait`, `specialization`, `maneuver`
|
||||||
|
- ES module imports use relative paths with `.js` extension
|
||||||
|
- Custom combat class extends `Combat` with its own initiative formula
|
||||||
|
- Socket enabled (`"socket": true` in `system.json`)
|
||||||
|
|
||||||
|
## Conventions (verified from codebase)
|
||||||
|
|
||||||
|
- **JS files**: kebab-case (`ecryme-actor.js`)
|
||||||
|
- **Classes**: PascalCase (`EcrymeActor`)
|
||||||
|
- **Templates**: kebab-case `.hbs` (`actor-sheet.hbs`)
|
||||||
|
- **Barrel files**: `_module.js`
|
||||||
|
- **Hooks**: init → register classes/sheets/templates; ready → welcome msg/scene import; babele.init → register translation dir
|
||||||
|
|
||||||
|
## Release
|
||||||
|
|
||||||
|
Gitea CI (`.gitea/workflows/release.yaml`) triggers on published release. Zips the source tree directly — JS is used as-is, no build step for JS. CSS must be pre-compiled before release.
|
||||||
+393
@@ -0,0 +1,393 @@
|
|||||||
|
Creative Commons Legal Code
|
||||||
|
|
||||||
|
CC BY-NC-SA 4.0
|
||||||
|
|
||||||
|
Attribution-NonCommercial-ShareAlike 4.0 International
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||||
|
does not provide legal services or legal advice. Distribution of
|
||||||
|
Creative Commons public licenses does not create a lawyer-client or
|
||||||
|
other relationship. Creative Commons makes its licenses and related
|
||||||
|
information available on an "as-is" basis. Creative Commons gives no
|
||||||
|
warranties regarding its licenses, any material licensed under their
|
||||||
|
terms and conditions, or any related information. Creative Commons
|
||||||
|
disclaims all liability for damages resulting from their use to the
|
||||||
|
fullest extent possible.
|
||||||
|
|
||||||
|
By exercising the Licensed Rights (defined below), You accept and agree
|
||||||
|
to be bound by the terms and conditions of this Creative Commons
|
||||||
|
Attribution-NonCommercial-ShareAlike 4.0 International Public License
|
||||||
|
("Public License"). To the extent this Public License may be interpreted as
|
||||||
|
a contract, You are granted the Licensed Rights in consideration of Your
|
||||||
|
acceptance of these terms and conditions, and the Licensor grants You
|
||||||
|
such rights in consideration of benefits the Licensor receives from
|
||||||
|
making the Licensed Material available under these terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
|
||||||
|
Section 1 -- Definitions.
|
||||||
|
|
||||||
|
a. Adapted Material means material subject to Copyright and Similar
|
||||||
|
Rights that is derived from or based upon the Licensed Material
|
||||||
|
and in which the Licensed Material is translated, altered,
|
||||||
|
arranged, transformed, or otherwise modified in a manner requiring
|
||||||
|
permission under the Copyright and Similar Rights held by the
|
||||||
|
Licensor. For purposes of this Public License, where the Licensed
|
||||||
|
Material is a musical work, performance, or sound recording,
|
||||||
|
Adapted Material is always produced where the Licensed Material is
|
||||||
|
synched in timed relation with a moving image.
|
||||||
|
|
||||||
|
b. Adapter's License means the license You apply to Your Copyright and
|
||||||
|
Similar Rights in Your contributions to Adapted Material in
|
||||||
|
accordance with the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
c. BY-NC-SA Compatible License means a license listed at
|
||||||
|
creativecommons.org/compatiblelicenses, approved by Creative
|
||||||
|
Commons as essentially the equivalent of this Public License.
|
||||||
|
|
||||||
|
d. Copyright and Similar Rights means copyright and/or similar rights
|
||||||
|
closely related to copyright including, without limitation, performance,
|
||||||
|
broadcast, sound recording, and Sui Generis Database Rights, without
|
||||||
|
regard to how the rights are labeled or categorized. For purposes of
|
||||||
|
this Public License, the rights specified in Section 2(b)(1)-(2) are
|
||||||
|
not Copyright and Similar Rights.
|
||||||
|
|
||||||
|
e. Effective Technological Measures means those measures that, in the
|
||||||
|
absence of proper authority, may not be circumvented under laws
|
||||||
|
fulfilling obligations under Article 11 of the WIPO Copyright Treaty
|
||||||
|
adopted on December 20, 1996, and/or similar international agreements.
|
||||||
|
|
||||||
|
f. Exceptions and Limitations means fair use, fair dealing, and/or any
|
||||||
|
other exception or limitation to Copyright and Similar Rights that
|
||||||
|
apply to Your use of the Licensed Material.
|
||||||
|
|
||||||
|
g. Licensed Material means the artistic or literary work, database, or
|
||||||
|
other material to which the Licensor applied this Public License.
|
||||||
|
|
||||||
|
h. Licensed Rights means the rights granted to You subject to the
|
||||||
|
terms and conditions of this Public License, which have as their
|
||||||
|
object the Licensed Material and which include all Copyright and
|
||||||
|
Similar Rights that apply to Your use of the Licensed Material and
|
||||||
|
that the Licensor has authority to license.
|
||||||
|
|
||||||
|
i. Licensor means the individual(s) or entity(ies) granting rights
|
||||||
|
under this Public License.
|
||||||
|
|
||||||
|
j. NonCommercial means not primarily intended for or directed towards
|
||||||
|
commercial advantage or monetary compensation. For purposes of
|
||||||
|
this Public License, the exchange of the Licensed Material for a
|
||||||
|
fee or other remuneration is considered NonCommercial if the fee or
|
||||||
|
remuneration is solely intended to compensate the Licensor for the
|
||||||
|
Licensor's time and effort in producing the Licensed Material or to
|
||||||
|
provide a financial contribution to the Licensor's non-commercial
|
||||||
|
operations, and the exchange is separate and independent from the
|
||||||
|
Licensed Material such that the Licensor's commercial operations are
|
||||||
|
not enhanced by the exchange.
|
||||||
|
|
||||||
|
k. Original Work means the work to which the Licensor applied this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
l. Share means to provide material to the public by any means or
|
||||||
|
process that requires permission under the Licensed Rights, such as
|
||||||
|
reproduction, public display, public performance, distribution,
|
||||||
|
dissemination, communication, or importation, and to make material
|
||||||
|
available to the public including in ways that members of the public
|
||||||
|
may access the material from a place and at a time individually chosen
|
||||||
|
by them.
|
||||||
|
|
||||||
|
m. Shared with You means the Licensed Material has been provided to
|
||||||
|
You by the Licensor, or by a recipient of the Licensed Material from
|
||||||
|
the Licensor, under this Public License.
|
||||||
|
|
||||||
|
n. Sui Generis Database Rights means rights other than copyright
|
||||||
|
resulting from Directive 96/9/EC of the European Parliament and of the
|
||||||
|
Council of 11 March 1996 on the legal protection of databases, as
|
||||||
|
amended and/or succeeded, as well as other essentially equivalent rights
|
||||||
|
anywhere in the world.
|
||||||
|
|
||||||
|
o. This Public License does not apply to Sui Generis Database Rights to
|
||||||
|
the extent they do not fall under Section 2(a)(5).
|
||||||
|
|
||||||
|
p. You means the individual or entity exercising the Licensed Rights
|
||||||
|
under this Public License. Your has a corresponding meaning in the
|
||||||
|
context of Your acting as the Licensor.
|
||||||
|
|
||||||
|
|
||||||
|
Section 2 -- Scope.
|
||||||
|
|
||||||
|
a. License grant.
|
||||||
|
|
||||||
|
1. Subject to the terms and conditions of this Public License, the
|
||||||
|
Licensor hereby grants You a worldwide, royalty-free, non-sublicensable,
|
||||||
|
non-exclusive, irrevocable license to exercise the Licensed Rights in
|
||||||
|
the Licensed Material to:
|
||||||
|
|
||||||
|
a. reproduce and Share the Licensed Material, in whole or in part;
|
||||||
|
|
||||||
|
b. create and reproduce Adapted Material and Share Adapted Material.
|
||||||
|
|
||||||
|
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||||
|
Exceptions and Limitations apply to Your use, this Public License
|
||||||
|
does not apply, and You do not need to comply with its terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
3. Term. The term of this Public License is specified in Section 6(a).
|
||||||
|
|
||||||
|
4. Media and formats; technical modifications allowed. The Licensor
|
||||||
|
authorizes You to exercise the Licensed Rights in all media and
|
||||||
|
formats whether now known or hereafter created, and to make technical
|
||||||
|
modifications necessary to do so. The Licensor waives and/or agrees
|
||||||
|
not to assert any right or authority to forbid You from making
|
||||||
|
technical modifications necessary to exercise the Licensed Rights,
|
||||||
|
including technical modifications necessary to circumvent Effective
|
||||||
|
Technological Measures. For purposes of this Public License, simply as a
|
||||||
|
consequence of modifying the Licensed Material, You do not become a
|
||||||
|
Licensor of the Licensed Material, and the Adapted Material You create
|
||||||
|
is not subject to the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
5. Downstream recipients.
|
||||||
|
|
||||||
|
a. Offer from the Licensor -- Licensed Material: The Licensor
|
||||||
|
offers to the recipient of Licensed Material a license to the
|
||||||
|
Licensed Material on the same terms and conditions as granted
|
||||||
|
to You under this Public License.
|
||||||
|
|
||||||
|
b. Additional offer from the Licensor -- Adapted Material: The
|
||||||
|
Licensor offers to the recipient of Adapted Material a license
|
||||||
|
to the Adapted Material on the terms and conditions of the
|
||||||
|
Adapter's License You apply to Your Adapted Material.
|
||||||
|
|
||||||
|
c. No downstream restrictions. You may not offer or impose any
|
||||||
|
additional or different terms or conditions on, or apply any
|
||||||
|
Effective Technological Measures to, the Licensed Material if doing
|
||||||
|
so restricts exercise of the Licensed Rights by any recipient of
|
||||||
|
the Licensed Material.
|
||||||
|
|
||||||
|
b. No endorsement. Nothing in this Public License constitutes or may be
|
||||||
|
construed as permission to assert or imply that You are, or that Your
|
||||||
|
use of the Licensed Material is, connected with, or sponsored by, the
|
||||||
|
Licensor, or any other person.
|
||||||
|
|
||||||
|
c. Fair use; other user rights. Nothing in this Public License is intended
|
||||||
|
to reduce, limit, or restrict any uses free from copyright or rights
|
||||||
|
arising from limitations or exceptions that are provided for in
|
||||||
|
connection with the copyright and other similar rights applicable to
|
||||||
|
the particular use or which cannot be waived.
|
||||||
|
|
||||||
|
d. Patent and trademark notice. This Public License does not grant
|
||||||
|
permission to use the trade name, trademark, service mark, or similar
|
||||||
|
branding of the Licensor, except as required for reasonable and customary
|
||||||
|
notice of attribution when You engage in the reproduction or distribution
|
||||||
|
of the Licensed Material. This Public License does not grant permission to
|
||||||
|
use the patent rights of the Licensor.
|
||||||
|
|
||||||
|
|
||||||
|
Section 3 -- License Conditions.
|
||||||
|
|
||||||
|
Your exercise of the Licensed Rights is expressly made subject to the
|
||||||
|
following conditions:
|
||||||
|
|
||||||
|
a. Attribution.
|
||||||
|
|
||||||
|
1. If You Share the Licensed Material (including in modified form), You
|
||||||
|
must:
|
||||||
|
|
||||||
|
a. retain the following if it is supplied by the Licensor with the
|
||||||
|
Licensed Material:
|
||||||
|
|
||||||
|
i. identification of the creator(s) of the Licensed Material and
|
||||||
|
any others designated to receive attribution, in any reasonable
|
||||||
|
manner requested by the Licensor (including by pseudonym if
|
||||||
|
designated);
|
||||||
|
|
||||||
|
ii. a copyright notice;
|
||||||
|
|
||||||
|
iii. a notice that refers to this Public License;
|
||||||
|
|
||||||
|
iv. a notice that refers to the disclaimer of warranties;
|
||||||
|
|
||||||
|
v. a URI or hyperlink to the Licensed Material to the extent
|
||||||
|
reasonably practicable;
|
||||||
|
|
||||||
|
b. indicate if You modified the Licensed Material and retain an
|
||||||
|
indication of any previous modifications; and
|
||||||
|
|
||||||
|
c. indicate the Licensed Material is licensed under this Public
|
||||||
|
License, and include the text of, or the URI or hyperlink to, this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
2. You may satisfy the conditions in Section 3(a)(1) in any reasonable
|
||||||
|
manner based on the medium, means, and context in which You Share the
|
||||||
|
Licensed Material. For example, it may be reasonable to satisfy the
|
||||||
|
conditions by providing a URI or hyperlink to a resource that includes
|
||||||
|
the required information.
|
||||||
|
|
||||||
|
3. If requested by the Licensor, You must remove any of the information
|
||||||
|
required by Section 3(a)(1)(A) to the extent reasonably practicable.
|
||||||
|
|
||||||
|
b. NonCommercial.
|
||||||
|
You may not exercise the Licensed Rights for Commercial Purposes.
|
||||||
|
|
||||||
|
c. ShareAlike.
|
||||||
|
In addition to the conditions in Section 3(a) and (b), if You Share
|
||||||
|
Adapted Material You produce, the following conditions also apply:
|
||||||
|
|
||||||
|
1. The Adapter's License You apply must be a BY-NC-SA Compatible License
|
||||||
|
with terms that are equivalent to this Public License.
|
||||||
|
|
||||||
|
2. You must include the text of, or the URI or hyperlink to, the
|
||||||
|
Adapter's License You apply. You may satisfy this condition in any
|
||||||
|
reasonable manner based on the medium, means, and context in which You
|
||||||
|
Share Adapted Material.
|
||||||
|
|
||||||
|
3. You may not offer or impose any additional or different terms or
|
||||||
|
conditions on, or apply any Effective Technological Measures to,
|
||||||
|
Adapted Material that restrict exercise of the rights granted under
|
||||||
|
the Adapter's License You apply.
|
||||||
|
|
||||||
|
|
||||||
|
Section 4 -- Sui Generis Database Rights.
|
||||||
|
|
||||||
|
Where the Licensed Rights include Sui Generis Database Rights that apply to
|
||||||
|
Your use of the Licensed Material:
|
||||||
|
|
||||||
|
a. for the avoidance of doubt, Section 2(a)(1) grants You the right to
|
||||||
|
extract, reuse, reproduce, and Share all or a substantial portion of the
|
||||||
|
contents of the database for NonCommercial purposes only;
|
||||||
|
|
||||||
|
b. if You include all or a substantial portion of the database contents in
|
||||||
|
Adapted Material, You must comply with the conditions in Section
|
||||||
|
3(a) and (c) of this Public License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||||
|
|
||||||
|
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE EXTENT
|
||||||
|
POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS AND AS-AVAILABLE,
|
||||||
|
AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND, EXPRESS, IMPLIED,
|
||||||
|
STATUTORY OR OTHERWISE, AND DISCLAIMS ALL RESPONSIBILITY FOR ANY HARM OR
|
||||||
|
DAMAGE ARISING OUT OF OR IN CONNECTION WITH THE LICENSED MATERIAL OR
|
||||||
|
THIS PUBLIC LICENSE, INCLUDING WITHOUT LIMITATION DAMAGES FOR LOSS OF
|
||||||
|
INCOME, PROFITS, BUSINESS INTERRUPTION, OR OTHER PECUNIARY LOSS, OR FOR
|
||||||
|
ANY INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE, OR EXEMPLARY
|
||||||
|
DAMAGES, WHETHER ARISING UNDER CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY FROM THE USE OF THE
|
||||||
|
LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
b. WHERE THE LICENSED RIGHTS INCLUDE SUI GENERIS DATABASE RIGHTS THAT
|
||||||
|
APPLY TO YOUR USE OF THE LICENSED MATERIAL, THE LICENSOR MAKES NO
|
||||||
|
REPRESENTATIONS OR WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||||
|
AS TO THE DATA INCLUDED IN THE LICENSED MATERIAL; THE LICENSOR MAKES NO
|
||||||
|
REPRESENTATIONS OR WARRANTIES AS TO THE ACCURACY OR COMPLETENESS OF THE
|
||||||
|
DATA; THE LICENSOR DISCLAIMS ALL LIABILITY FOR ANY HARM OR DAMAGE ARISING
|
||||||
|
OUT OF INACCURACIES OR OMITTIONS IN THE DATA; AND THE LICENSOR MAKES NO
|
||||||
|
COMMITMENT TO CONTINUE TO SUPPLY, MAINTAIN, OR CORRECT THE DATA.
|
||||||
|
|
||||||
|
c. OTHER THAN AS EXPRESSLY AGREED TO BY THE PARTIES IN WRITING, THE LICENSOR
|
||||||
|
PROVIDES THE LICENSED MATERIAL ON AN "AS-IS" AND "AS-AVAILABLE" BASIS AND
|
||||||
|
WITHOUT CONDITIONS OR WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF TITLE, MERCHANTABILITY,
|
||||||
|
OR FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE SOLE RISK OF DETERMINING
|
||||||
|
WHETHER THE LICENSED MATERIAL IS SUITABLE FOR YOUR PURPOSES AND OF THE
|
||||||
|
CONSEQUENCES OF USING THE LICENSED MATERIAL. IN ALL CIRCUMSTANCES, UNLESS
|
||||||
|
OTHERWISE AGREED IN WRITING, THE LICENSOR SHALL NOT BE LIABLE TO YOU OR
|
||||||
|
TO ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING WITHOUT LIMITATION SPECIAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES. IN NO EVENT SHALL THE LICENSOR BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES ARISING OUT OF THIS
|
||||||
|
PUBLIC LICENSE OR THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||||
|
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
d. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL THE
|
||||||
|
LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT
|
||||||
|
LIMITATION, NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||||
|
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, OR EXEMPLARY DAMAGES, INCLUDING WITHOUT
|
||||||
|
LIMITATION DAMAGES FOR LOSS OF PROFITS, DATA, OR GOODWILL, EVEN IF THE
|
||||||
|
LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
|
||||||
|
Section 6 -- Term and Termination.
|
||||||
|
|
||||||
|
a. This Public License applies for the duration of any applicable
|
||||||
|
copyright and Similar Rights licensed here under. However, if You
|
||||||
|
violate this Public License, the Licensor's grant of rights to You
|
||||||
|
under this Public License terminates automatically.
|
||||||
|
|
||||||
|
b. Where Your right to use the Licensed Material has terminated under
|
||||||
|
Section 6(a), it reinstates:
|
||||||
|
|
||||||
|
1. automatically as of the date the violation is cured, provided it is
|
||||||
|
cured within 30 days of Your discovery of the violation; or
|
||||||
|
|
||||||
|
2. upon express reinstatement by the Licensor.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 6(b) does not affect any right
|
||||||
|
the Licensor may have to seek remedies for Your violation of this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
c. For the avoidance of doubt, the Licensor may also terminate this Public
|
||||||
|
License for all uses of the Licensed Material by You if You fail to
|
||||||
|
comply with the Licensor's requirement to remove a reference to the
|
||||||
|
Licensor or attribution information, as requested under Section
|
||||||
|
3(a)(1)(A)(v), from any cue or companion material to the Licensed
|
||||||
|
Material.
|
||||||
|
|
||||||
|
d. Who may terminate this Public License? Only the Licensor or an
|
||||||
|
individual or entity authorized to act on behalf of the Licensor.
|
||||||
|
|
||||||
|
|
||||||
|
Section 7 -- Other Rights.
|
||||||
|
|
||||||
|
a. Moral rights, such as the right of integrity, are not licensed under
|
||||||
|
this Public License, nor are publicity, privacy, and/or other similar
|
||||||
|
personality rights; however, to the extent possible, the Licensor waives
|
||||||
|
and/or agrees not to assert any such rights held by the Licensor to the
|
||||||
|
extent necessary to allow You to exercise the Licensed Rights, but not
|
||||||
|
otherwise.
|
||||||
|
|
||||||
|
b. Patent rights. This Public License does not grant permissions to use,
|
||||||
|
sell, or license patent claims or patented inventions in any work
|
||||||
|
based on the Licensed Material, and the Licensor reserves all patent and
|
||||||
|
similar rights in the Licensed Material.
|
||||||
|
|
||||||
|
c. Trademark rights. This Public License does not grant permissions to
|
||||||
|
use the trade name, trademark, service mark, or other similar branding
|
||||||
|
of the Licensor, except as required for reasonable and customary use in
|
||||||
|
describing the origin of the Licensed Material and describing the use
|
||||||
|
of the Licensed Material, including Modified Versions of You.
|
||||||
|
|
||||||
|
d. No additional restrictions. You may not impose any technological
|
||||||
|
restrictions or attempt to impose technological restrictions through legal
|
||||||
|
or other means that restrict other Users from exercising the Licensed
|
||||||
|
Rights.
|
||||||
|
|
||||||
|
|
||||||
|
Section 8 -- Interpretation.
|
||||||
|
|
||||||
|
a. For the avoidance of doubt, this Public License does not, and shall be
|
||||||
|
interpreted not to, create or imply any grant of patent or trademark
|
||||||
|
rights to You.
|
||||||
|
|
||||||
|
b. This Public License does not address the permissions and restrictions
|
||||||
|
that apply to Private Rights or Other Rights, as such terms are defined
|
||||||
|
under Section 2(a)(4).
|
||||||
|
|
||||||
|
c. No waiver. Any failure by the Licensor to comply with a term or
|
||||||
|
condition of this Public License or to seek remedies for violation of
|
||||||
|
this Public License does not constitute a waiver of the Licensor's
|
||||||
|
right to enforce that term, condition, or remedy.
|
||||||
|
|
||||||
|
d. Severability. If any provision of this Public License is invalid or
|
||||||
|
unenforceable under applicable law, it shall not affect the validity or
|
||||||
|
enforceability of the remainder of the terms and conditions of this
|
||||||
|
Public License without that provision.
|
||||||
|
|
||||||
|
e. No surrender of rights. This Public License does not require You or any
|
||||||
|
User to surrender any rights, including moral rights or copyright,
|
||||||
|
they may have in the Licensed Material or Adapted Material.
|
||||||
|
|
||||||
|
f. All rights not explicitly granted. Any use of the Licensed Material
|
||||||
|
not expressly permitted by this Public License is reserved and
|
||||||
|
prohibited.
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
Copyright 2023 Open Sesame Games
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
@@ -28,7 +28,22 @@ The game system in Foundry offers the following features :
|
|||||||
|
|
||||||
English translation by Conal Longden and Ian McClung
|
English translation by Conal Longden and Ian McClung
|
||||||
|
|
||||||
# Copyright mentions
|
# License
|
||||||
|
|
||||||
|
This work is licensed under **Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)**.
|
||||||
|
|
||||||
|
You are free to:
|
||||||
|
- **Share** — copy and redistribute the material in any medium or format
|
||||||
|
- **Adapt** — remix, transform, and build upon the material
|
||||||
|
|
||||||
|
Under the following terms:
|
||||||
|
- **Attribution** — You must give appropriate credit, provide a link to the license, and indicate if changes were made
|
||||||
|
- **NonCommercial** — You may not use the material for commercial purposes
|
||||||
|
- **ShareAlike** — If you remix, transform, or build upon the material, you must distribute your contributions under the same license
|
||||||
|
|
||||||
|
For the full legal text, see [LICENSE.md](LICENSE.md).
|
||||||
|
|
||||||
|
## Copyright mentions
|
||||||
|
|
||||||
Copyright 2023 Open Sesame Games
|
Copyright 2023 Open Sesame Games
|
||||||
All rights reserved
|
All rights reserved
|
||||||
|
|||||||
@@ -1,3 +1,27 @@
|
|||||||
|
## [Version à venir] - Migration DataModels
|
||||||
|
|
||||||
|
### 🔄 Changements majeurs
|
||||||
|
- **Migration complète vers DataModels** : Le système n'utilise plus `template.json` pour définir les structures de données
|
||||||
|
- Tous les types d'acteurs (PC, NPC, Annency) utilisent maintenant des DataModels
|
||||||
|
- Tous les types d'items (Equipment, Weapon, Trait, Specialization, Maneuver, Scar, Annency, Boheme, Contact, Confrontation) utilisent maintenant des DataModels
|
||||||
|
|
||||||
|
### ✨ Améliorations
|
||||||
|
- Validation automatique des types de données
|
||||||
|
- Valeurs par défaut cohérentes pour tous les champs
|
||||||
|
- Meilleure performance grâce aux optimisations internes de Foundry VTT
|
||||||
|
- Code mieux organisé dans `modules/models/`
|
||||||
|
|
||||||
|
### 🔧 Technique
|
||||||
|
- Ajout du dossier `modules/models/` avec 14 fichiers DataModel
|
||||||
|
- `template.json` est maintenant marqué comme deprecated mais conservé pour référence
|
||||||
|
- Compatibilité ascendante : les données existantes sont automatiquement migrées
|
||||||
|
|
||||||
|
### 📚 Documentation
|
||||||
|
- Ajout d'un README dans `modules/models/` expliquant la structure et l'utilisation
|
||||||
|
- Guide de développement pour ajouter de nouveaux types
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
v12.0.0
|
v12.0.0
|
||||||
|
|
||||||
- Support Foundry v11/v12
|
- Support Foundry v11/v12
|
||||||
|
|||||||
+26
-20
@@ -1,25 +1,31 @@
|
|||||||
var gulp = require('gulp');
|
const gulp = require('gulp');
|
||||||
|
const less = require('gulp-less');
|
||||||
|
|
||||||
var postcss = require('gulp-postcss');
|
/* ----------------------------------------- */
|
||||||
|
/* Compile LESS
|
||||||
var autoprefixer = require('autoprefixer');
|
/* ----------------------------------------- */
|
||||||
var cssnext = require('cssnext');
|
function compileLESS() {
|
||||||
var precss = require('precss');
|
return gulp.src("styles/ecryme.less")
|
||||||
|
.pipe(less()).on('error', console.log.bind(console))
|
||||||
gulp.task('css', function () {
|
.pipe(gulp.dest("./css"));
|
||||||
|
}
|
||||||
var processors = [
|
const css = gulp.series(compileLESS);
|
||||||
autoprefixer,
|
|
||||||
cssnext,
|
|
||||||
precss
|
|
||||||
];
|
|
||||||
|
|
||||||
return gulp.src('./postcss/*.css')
|
|
||||||
.pipe(postcss(processors))
|
|
||||||
.pipe(gulp.dest('./styles'));
|
|
||||||
});
|
|
||||||
|
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* Watch Updates
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
const LESS_FILES = ["styles/**/*.less"];
|
||||||
|
|
||||||
function watchUpdates() {
|
function watchUpdates() {
|
||||||
gulp.watch('./postcss/*.css', css);
|
gulp.watch(LESS_FILES, css);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* Export Tasks
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
exports.default = gulp.series(
|
||||||
|
gulp.parallel(css),
|
||||||
|
watchUpdates
|
||||||
|
);
|
||||||
|
exports.css = css;
|
||||||
|
exports.watchUpdates = watchUpdates;
|
||||||
|
|||||||
+20
-3
@@ -19,7 +19,8 @@
|
|||||||
"cephaly": "Cephaly",
|
"cephaly": "Cephaly",
|
||||||
"boheme": "Boheme",
|
"boheme": "Boheme",
|
||||||
"amertume": "Amertume",
|
"amertume": "Amertume",
|
||||||
"gamelevel": "Game level"
|
"gamelevel": "Game level",
|
||||||
|
"gamelevelhelp": "Choose the game level (Cogs, Cephaly, Boheme, Amertume)"
|
||||||
},
|
},
|
||||||
"chat": {
|
"chat": {
|
||||||
"formula": "Formula",
|
"formula": "Formula",
|
||||||
@@ -42,15 +43,18 @@
|
|||||||
"cephaly-success-4": "Duration : 1 week - Impact : Light - Bonus : 2 - Elegy : 2",
|
"cephaly-success-4": "Duration : 1 week - Impact : Light - Bonus : 2 - Elegy : 2",
|
||||||
"cephaly-success-6": "Duration : 1 month - Impact : Serious - Bonus : 3 - Elegy : 3",
|
"cephaly-success-6": "Duration : 1 month - Impact : Serious - Bonus : 3 - Elegy : 3",
|
||||||
"cephaly-success-8": "Duration : 1 year - Impact : Major - Bonus : 4 - Elegy : 4",
|
"cephaly-success-8": "Duration : 1 year - Impact : Major - Bonus : 4 - Elegy : 4",
|
||||||
|
"cephaly-success-9": "Duration : Permanent - Impact : Major - Bonus : 4 - Elegy : 4",
|
||||||
"cephaly-success-10": "Duration : Permanent - Impact : Dead - Bonus : 5 - Elegy : 5",
|
"cephaly-success-10": "Duration : Permanent - Impact : Dead - Bonus : 5 - Elegy : 5",
|
||||||
"cephaly-failure-2": "Duration : 1 scene - Impact : Superficial - Malus : 1",
|
"cephaly-failure-2": "Duration : 1 scene - Impact : Superficial - Malus : 1",
|
||||||
"cephaly-failure-4": "Duration : 1 week - Impact : Light - Malus : 2",
|
"cephaly-failure-4": "Duration : 1 week - Impact : Light - Malus : 2",
|
||||||
"cephaly-failure-6": "Duration : 1 month - Impact : Serious - Malus : 3",
|
"cephaly-failure-6": "Duration : 1 month - Impact : Serious - Malus : 3",
|
||||||
"cephaly-failure-8": "Duration : 1 year - Impact : Major - Malus : 4",
|
"cephaly-failure-8": "Duration : 1 year - Impact : Major - Malus : 4",
|
||||||
|
"cephaly-failure-9": "Duration : Permanent - Impact : Major - Malus : 4",
|
||||||
"cephaly-failure-10": "Duration : Permanent - Impact : Death/Madness - Malus : 5"
|
"cephaly-failure-10": "Duration : Permanent - Impact : Death/Madness - Malus : 5"
|
||||||
},
|
},
|
||||||
"warn": {
|
"warn": {
|
||||||
"notenoughdice": "Execution and Preservation must have 2 dices allocated"
|
"notenoughdice": "Execution and Preservation must have 2 dices allocated",
|
||||||
|
"confrontalready": "Confrontation already in progress with this roll"
|
||||||
},
|
},
|
||||||
"ui": {
|
"ui": {
|
||||||
"equipmentfree": "Equipments (free input)",
|
"equipmentfree": "Equipments (free input)",
|
||||||
@@ -112,6 +116,7 @@
|
|||||||
"applyspleen": "Apply spleen",
|
"applyspleen": "Apply spleen",
|
||||||
"skilltranscendence": "Self Transcendence",
|
"skilltranscendence": "Self Transcendence",
|
||||||
"confrontation": "Confrontation",
|
"confrontation": "Confrontation",
|
||||||
|
"confrontresult": "Confrontation Result",
|
||||||
"rollnormal": "Normal (4d6)",
|
"rollnormal": "Normal (4d6)",
|
||||||
"rollspleen": "With Spleen (5d6, worst 4 are kept)",
|
"rollspleen": "With Spleen (5d6, worst 4 are kept)",
|
||||||
"rollideal": "With Ideal (5d6, best 4 are kept)",
|
"rollideal": "With Ideal (5d6, best 4 are kept)",
|
||||||
@@ -168,7 +173,19 @@
|
|||||||
"residence": "Residence",
|
"residence": "Residence",
|
||||||
"origin": "Origin",
|
"origin": "Origin",
|
||||||
"childhood": "Childhood",
|
"childhood": "Childhood",
|
||||||
"bonus": "Bonus"
|
"bonus": "Bonus",
|
||||||
|
"details": "Details",
|
||||||
|
"quantity": "Quantity",
|
||||||
|
"background": "Background",
|
||||||
|
"gmnotes": "GM Notes",
|
||||||
|
"age": "Age",
|
||||||
|
"profession": "Profession",
|
||||||
|
"level": "Level",
|
||||||
|
"create": "Create",
|
||||||
|
"delete": "Delete",
|
||||||
|
"edit": "Edit",
|
||||||
|
"spleen": "Spleen",
|
||||||
|
"ideal": "Ideal"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+22
-5
@@ -19,7 +19,8 @@
|
|||||||
"cephaly": "Céphalie",
|
"cephaly": "Céphalie",
|
||||||
"boheme": "Bohême",
|
"boheme": "Bohême",
|
||||||
"amertume": "Amertume",
|
"amertume": "Amertume",
|
||||||
"gamelevel": "Niveau de jeu"
|
"gamelevel": "Niveau de jeu",
|
||||||
|
"gamelevelhelp": "Choisissez le niveau de jeu (Engrenages, Céphalie, Bohême, Amertume)"
|
||||||
},
|
},
|
||||||
"chat": {
|
"chat": {
|
||||||
"formula": "Formule",
|
"formula": "Formule",
|
||||||
@@ -34,24 +35,27 @@
|
|||||||
"traitmalus": "Trait malus",
|
"traitmalus": "Trait malus",
|
||||||
"bonusmalustraits": "Bonus/Malus des Traits",
|
"bonusmalustraits": "Bonus/Malus des Traits",
|
||||||
"spectranscend": "Dépassement de soi : ",
|
"spectranscend": "Dépassement de soi : ",
|
||||||
"confrontselected": "Confrontation selectionnée",
|
"confrontselect": "Sélectionné pour la confrontation",
|
||||||
"sentogm": "La confrontation a été envoyée au MJ"
|
"sentogm": "La confrontation a été envoyée au MJ"
|
||||||
},
|
},
|
||||||
"rule": {
|
"rule": {
|
||||||
"cephaly-success-12": "Durée : 1 scène - Impact : Superficiel - Bonus : 1 - Elegie : 1",
|
"cephaly-success-2": "Durée : 1 scène - Impact : Superficiel - Bonus : 1 - Elegie : 1",
|
||||||
"cephaly-success-4": "Durée : 1 semaine - Impact : Léger - Bonus : 2 - Elegie : 2",
|
"cephaly-success-4": "Durée : 1 semaine - Impact : Léger - Bonus : 2 - Elegie : 2",
|
||||||
"cephaly-success-6": "Durée : 1 mois - Impact : Grave - Bonus : 3 - Elegie : 3",
|
"cephaly-success-6": "Durée : 1 mois - Impact : Grave - Bonus : 3 - Elegie : 3",
|
||||||
"cephaly-success-8": "Durée : 1 année - Impact : Majeur - Bonus : 4 - Elegie : 4",
|
"cephaly-success-8": "Durée : 1 année - Impact : Majeur - Bonus : 4 - Elegie : 4",
|
||||||
|
"cephaly-success-9": "Durée : Permanent - Impact : Majeur - Bonus : 4 - Elegie : 4",
|
||||||
"cephaly-success-10": "Durée : Permanent - Impact : Mort - Bonus : 5 - Elegie : 5",
|
"cephaly-success-10": "Durée : Permanent - Impact : Mort - Bonus : 5 - Elegie : 5",
|
||||||
"cephaly-failure-2": "Durée : 1 scène - Impact : Superficiel - Malus : 1 - Symptôme non visible et sans gravité - Altération bégigne difficilement repérable",
|
"cephaly-failure-2": "Durée : 1 scène - Impact : Superficiel - Malus : 1 - Symptôme non visible et sans gravité - Altération bégigne difficilement repérable",
|
||||||
"cephaly-failure-4": "Durée : 1 semaine - Impact : Léger - Malus : 2 - Symptôme visible non incapacitant - Altération repérable",
|
"cephaly-failure-4": "Durée : 1 semaine - Impact : Léger - Malus : 2 - Symptôme visible non incapacitant - Altération repérable",
|
||||||
"cephaly-failure-6": "Durée : 1 mois - Impact : Grave - Malus : 3 - Symptôme incapacitant - Altération repérable et fâcheuse",
|
"cephaly-failure-6": "Durée : 1 mois - Impact : Grave - Malus : 3 - Symptôme incapacitant - Altération repérable et fâcheuse",
|
||||||
"cephaly-failure-8": "Durée : 1 année - Impact : Majeur - Malus : 4 - Symptôme très incapacitant - Altération dangereuse",
|
"cephaly-failure-8": "Durée : 1 année - Impact : Majeur - Malus : 4 - Symptôme très incapacitant - Altération dangereuse",
|
||||||
|
"cephaly-failure-9": "Durée : Permanent - Impact : Majeur - Malus : 4 - Symptôme très incapacitant - Altération dangereuse",
|
||||||
"cephaly-failure-10": "Durée : Permanent - Impact : Mort/Folie - Malus : 5 - Symptôme spectaculaire et repoussant - Altération dangereuse globalement"
|
"cephaly-failure-10": "Durée : Permanent - Impact : Mort/Folie - Malus : 5 - Symptôme spectaculaire et repoussant - Altération dangereuse globalement"
|
||||||
|
|
||||||
},
|
},
|
||||||
"warn": {
|
"warn": {
|
||||||
"notenoughdice": "L'Accomplissement et la Préservation doivent avoir 2 dés chacun"
|
"notenoughdice": "L'Accomplissement et la Préservation doivent avoir 2 dés chacun",
|
||||||
|
"confrontalready": "Confrontation déjà en cours avec ce jet"
|
||||||
},
|
},
|
||||||
"ui": {
|
"ui": {
|
||||||
"equipmentfree": "Equipements (saisie libre)",
|
"equipmentfree": "Equipements (saisie libre)",
|
||||||
@@ -113,6 +117,7 @@
|
|||||||
"applyspleen": "Utiliser le spleen",
|
"applyspleen": "Utiliser le spleen",
|
||||||
"skilltranscendence": "Dépassement de soi",
|
"skilltranscendence": "Dépassement de soi",
|
||||||
"confrontation": "Confrontation",
|
"confrontation": "Confrontation",
|
||||||
|
"confrontresult": "Résultat de Confrontation",
|
||||||
"rollnormal": "Normal (4d6)",
|
"rollnormal": "Normal (4d6)",
|
||||||
"rollspleen": "Avec le Spleen (5d6, 4 plus bas conservés)",
|
"rollspleen": "Avec le Spleen (5d6, 4 plus bas conservés)",
|
||||||
"rollideal": "Avec l'Idéal (5d6, 4 plus haut conservés)",
|
"rollideal": "Avec l'Idéal (5d6, 4 plus haut conservés)",
|
||||||
@@ -169,7 +174,19 @@
|
|||||||
"residence": "Résidence",
|
"residence": "Résidence",
|
||||||
"origin": "Origine",
|
"origin": "Origine",
|
||||||
"childhood": "Enfance",
|
"childhood": "Enfance",
|
||||||
"bonus": "Bonus"
|
"bonus": "Bonus",
|
||||||
|
"details": "Détails",
|
||||||
|
"quantity": "Quantité",
|
||||||
|
"background": "Background",
|
||||||
|
"gmnotes": "Notes GM",
|
||||||
|
"age": "Âge",
|
||||||
|
"profession": "Profession",
|
||||||
|
"level": "Niveau",
|
||||||
|
"create": "Créer",
|
||||||
|
"delete": "Supprimer",
|
||||||
|
"edit": "Éditer",
|
||||||
|
"spleen": "Spleen",
|
||||||
|
"ideal": "Idéal"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ export class EcrymeActorSheet extends foundry.appv1.sheets.ActorSheet {
|
|||||||
}
|
}
|
||||||
this.formData = formData;
|
this.formData = formData;
|
||||||
|
|
||||||
console.log("PC : ", formData, this.object);
|
//console.log("PC : ", formData, this.object);
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -379,9 +379,9 @@ export class EcrymeActor extends Actor {
|
|||||||
rollData.img = this.img
|
rollData.img = this.img
|
||||||
rollData.isReroll = false
|
rollData.isReroll = false
|
||||||
rollData.config = game.system.ecryme.config
|
rollData.config = game.system.ecryme.config
|
||||||
rollData.traits = foundry.utils.duplicate(this.getRollTraits())
|
rollData.traits = this.getRollTraits().map(t => ({ _id: t.id, name: t.name, img: t.img, system: { level: t.system.level, traitype: t.system.traitype } }))
|
||||||
rollData.spleen = foundry.utils.duplicate(this.getSpleen() || {})
|
rollData.spleen = this.getSpleen() ? foundry.utils.duplicate(this.getSpleen()) : null
|
||||||
rollData.ideal = foundry.utils.duplicate(this.getIdeal() || {})
|
rollData.ideal = this.getIdeal() ? foundry.utils.duplicate(this.getIdeal()) : null
|
||||||
rollData.confrontBonus = this.getBonusList()
|
rollData.confrontBonus = this.getBonusList()
|
||||||
|
|
||||||
return rollData
|
return rollData
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export { default as EcrymeActorSheet } from "./pc-npc-sheet.js"
|
||||||
|
export { default as EcrymeAnnencySheet } from "./annency-sheet.js"
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
import EcrymeBaseActorSheet from "./base-actor-sheet.js"
|
||||||
|
import { EcrymeUtility } from "../../common/ecryme-utility.js"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actor sheet for the Annency type using Application V2.
|
||||||
|
*/
|
||||||
|
export default class EcrymeAnnencySheet extends EcrymeBaseActorSheet {
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["annency"],
|
||||||
|
position: { width: 640, height: 600 },
|
||||||
|
actions: {
|
||||||
|
actorEdit: EcrymeAnnencySheet.#onActorEdit,
|
||||||
|
actorDelete: EcrymeAnnencySheet.#onActorDelete,
|
||||||
|
itemEdit: EcrymeAnnencySheet.#onItemEdit,
|
||||||
|
itemDelete: EcrymeAnnencySheet.#onItemDelete,
|
||||||
|
itemCreate: EcrymeAnnencySheet.#onItemCreate,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
header: { template: "systems/fvtt-ecryme/templates/actors/partials/actor-header.hbs" },
|
||||||
|
tabs: { template: "templates/generic/tab-navigation.hbs" },
|
||||||
|
annency: { template: "systems/fvtt-ecryme/templates/actors/annency-annency.hbs" },
|
||||||
|
boheme: { template: "systems/fvtt-ecryme/templates/actors/annency-boheme.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
tabGroups = { primary: "annency" }
|
||||||
|
|
||||||
|
/** Build tabs conditionally based on active modules */
|
||||||
|
_getTabs() {
|
||||||
|
const tabs = {}
|
||||||
|
if (EcrymeUtility.hasCephaly()) {
|
||||||
|
tabs.annency = { id: "annency", group: "primary", label: "ECRY.ui.annency" }
|
||||||
|
}
|
||||||
|
if (EcrymeUtility.hasBoheme()) {
|
||||||
|
tabs.boheme = { id: "boheme", group: "primary", label: "ECRY.ui.boheme" }
|
||||||
|
}
|
||||||
|
// Ensure initial tab is valid
|
||||||
|
if (!tabs[this.tabGroups.primary]) {
|
||||||
|
this.tabGroups.primary = Object.keys(tabs)[0] ?? "annency"
|
||||||
|
}
|
||||||
|
for (const tab of Object.values(tabs)) {
|
||||||
|
tab.active = this.tabGroups[tab.group] === tab.id
|
||||||
|
tab.cssClass = tab.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext() {
|
||||||
|
const actor = this.document
|
||||||
|
return {
|
||||||
|
actor,
|
||||||
|
system: actor.system,
|
||||||
|
source: actor.toObject(),
|
||||||
|
fields: actor.schema.fields,
|
||||||
|
systemFields: actor.system.schema.fields,
|
||||||
|
type: actor.type,
|
||||||
|
img: actor.img,
|
||||||
|
name: actor.name,
|
||||||
|
isEditable: this.isEditable,
|
||||||
|
config: game.system.ecryme.config,
|
||||||
|
hasCephaly: EcrymeUtility.hasCephaly(),
|
||||||
|
hasBoheme: EcrymeUtility.hasBoheme(),
|
||||||
|
characters: actor.buildAnnencyActorList(),
|
||||||
|
owner: this.document.isOwner,
|
||||||
|
isGM: game.user.isGM,
|
||||||
|
tabs: this._getTabs(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _preparePartContext(partId, context) {
|
||||||
|
context = await super._preparePartContext(partId, context)
|
||||||
|
if (partId === "annency" || partId === "boheme") {
|
||||||
|
context.tab = context.tabs[partId]
|
||||||
|
}
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _onDrop(event) {
|
||||||
|
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)
|
||||||
|
if (data.type === "Actor") {
|
||||||
|
const actor = await fromUuid(data.uuid)
|
||||||
|
if (actor) {
|
||||||
|
this.actor.addAnnencyActor(actor.id)
|
||||||
|
} else {
|
||||||
|
ui.notifications.warn("Actor not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #region Static Action Handlers
|
||||||
|
|
||||||
|
static #onActorEdit(event, target) {
|
||||||
|
const li = target.closest("[data-actor-id]")
|
||||||
|
game.actors.get(li?.dataset.actorId)?.sheet.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
static async #onActorDelete(event, target) {
|
||||||
|
const li = target.closest("[data-actor-id]")
|
||||||
|
this.actor.removeAnnencyActor(li?.dataset.actorId)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onItemEdit(event, target) {
|
||||||
|
const li = target.closest("[data-item-id]")
|
||||||
|
const itemId = li?.dataset.itemId ?? target.dataset.itemId
|
||||||
|
this.document.items.get(itemId)?.sheet.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
static async #onItemDelete(event, target) {
|
||||||
|
const li = target.closest("[data-item-id]")
|
||||||
|
EcrymeUtility.confirmDelete(this, $(li)).catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onItemCreate(event, target) {
|
||||||
|
const dataType = target.dataset.type
|
||||||
|
this.document.createEmbeddedDocuments("Item", [{ name: "NewItem", type: dataType }], { renderSheet: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base actor sheet for Ecryme using Application V2.
|
||||||
|
* Provides common drag-drop, image editing, and shared structure.
|
||||||
|
*/
|
||||||
|
export default class EcrymeBaseActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
|
||||||
|
|
||||||
|
constructor(options = {}) {
|
||||||
|
super(options)
|
||||||
|
this.#dragDrop = this.#createDragDropHandlers()
|
||||||
|
}
|
||||||
|
|
||||||
|
#dragDrop
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["fvtt-ecryme", "sheet", "actor"],
|
||||||
|
position: {
|
||||||
|
width: 860,
|
||||||
|
height: 680,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
submitOnChange: true,
|
||||||
|
},
|
||||||
|
window: {
|
||||||
|
resizable: true,
|
||||||
|
},
|
||||||
|
dragDrop: [{ dragSelector: ".item-list .item[data-item-id]", dropSelector: null }],
|
||||||
|
actions: {
|
||||||
|
editImage: EcrymeBaseActorSheet.#onEditImage,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
_onRender(context, options) {
|
||||||
|
this.#dragDrop.forEach((d) => d.bind(this.element))
|
||||||
|
}
|
||||||
|
|
||||||
|
// #region Drag-and-Drop
|
||||||
|
#createDragDropHandlers() {
|
||||||
|
return this.options.dragDrop.map((d) => {
|
||||||
|
d.permissions = {
|
||||||
|
dragstart: this._canDragStart.bind(this),
|
||||||
|
drop: this._canDragDrop.bind(this),
|
||||||
|
}
|
||||||
|
d.callbacks = {
|
||||||
|
dragstart: this._onDragStart.bind(this),
|
||||||
|
dragover: this._onDragOver.bind(this),
|
||||||
|
drop: this._onDrop.bind(this),
|
||||||
|
}
|
||||||
|
return new foundry.applications.ux.DragDrop.implementation(d)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_canDragStart(selector) { return this.isEditable }
|
||||||
|
_canDragDrop(selector) { return this.isEditable && this.document.isOwner }
|
||||||
|
_onDragStart(event) {}
|
||||||
|
_onDragOver(event) {}
|
||||||
|
async _onDrop(event) {}
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region Actions
|
||||||
|
static async #onEditImage(event, target) {
|
||||||
|
const attr = target.dataset.edit
|
||||||
|
const current = foundry.utils.getProperty(this.document, attr)
|
||||||
|
const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}
|
||||||
|
const fp = new FilePicker({
|
||||||
|
current,
|
||||||
|
type: "image",
|
||||||
|
redirectToRoot: img ? [img] : [],
|
||||||
|
callback: (path) => {
|
||||||
|
this.document.update({ [attr]: path })
|
||||||
|
},
|
||||||
|
top: this.position.top + 40,
|
||||||
|
left: this.position.left + 10,
|
||||||
|
})
|
||||||
|
return fp.browse()
|
||||||
|
}
|
||||||
|
// #endregion
|
||||||
|
}
|
||||||
@@ -0,0 +1,255 @@
|
|||||||
|
import EcrymeBaseActorSheet from "./base-actor-sheet.js"
|
||||||
|
import { EcrymeUtility } from "../../common/ecryme-utility.js"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actor sheet for PC and NPC types using Application V2.
|
||||||
|
*/
|
||||||
|
export default class EcrymeActorSheet extends EcrymeBaseActorSheet {
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["pc-npc"],
|
||||||
|
position: { width: 860, height: 680 },
|
||||||
|
actions: {
|
||||||
|
openAnnency: EcrymeActorSheet.#onOpenAnnency,
|
||||||
|
itemEdit: EcrymeActorSheet.#onItemEdit,
|
||||||
|
itemDelete: EcrymeActorSheet.#onItemDelete,
|
||||||
|
itemCreate: EcrymeActorSheet.#onItemCreate,
|
||||||
|
subactorEdit: EcrymeActorSheet.#onSubactorEdit,
|
||||||
|
subactorDelete: EcrymeActorSheet.#onSubactorDelete,
|
||||||
|
rollSkill: EcrymeActorSheet.#onRollSkill,
|
||||||
|
rollSpec: EcrymeActorSheet.#onRollSpec,
|
||||||
|
rollSkillConfront: EcrymeActorSheet.#onRollSkillConfront,
|
||||||
|
rollCephaly: EcrymeActorSheet.#onRollCephaly,
|
||||||
|
rollWeaponConfront:EcrymeActorSheet.#onRollWeaponConfront,
|
||||||
|
impactModify: EcrymeActorSheet.#onImpactModify,
|
||||||
|
rollWeapon: EcrymeActorSheet.#onRollWeapon,
|
||||||
|
lockUnlock: EcrymeActorSheet.#onLockUnlock,
|
||||||
|
equipItem: EcrymeActorSheet.#onEquipItem,
|
||||||
|
quantityMinus: EcrymeActorSheet.#onQuantityMinus,
|
||||||
|
quantityPlus: EcrymeActorSheet.#onQuantityPlus,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
header: { template: "systems/fvtt-ecryme/templates/actors/partials/actor-header.hbs" },
|
||||||
|
tabs: { template: "templates/generic/tab-navigation.hbs" },
|
||||||
|
skills: { template: "systems/fvtt-ecryme/templates/actors/actor-skills.hbs" },
|
||||||
|
traits: { template: "systems/fvtt-ecryme/templates/actors/actor-traits.hbs" },
|
||||||
|
combat: { template: "systems/fvtt-ecryme/templates/actors/actor-combat.hbs" },
|
||||||
|
cephaly: { template: "systems/fvtt-ecryme/templates/actors/actor-cephaly.hbs" },
|
||||||
|
equipements:{ template: "systems/fvtt-ecryme/templates/actors/actor-equipements.hbs" },
|
||||||
|
biodata: { template: "systems/fvtt-ecryme/templates/actors/actor-biodata.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
tabGroups = { primary: "skills" }
|
||||||
|
|
||||||
|
/** Build tabs, conditionally adding cephaly if the module is active */
|
||||||
|
_getTabs() {
|
||||||
|
const hasCephaly = EcrymeUtility.hasCephaly()
|
||||||
|
const tabs = {
|
||||||
|
skills: { id: "skills", group: "primary", label: "ECRY.ui.skills" },
|
||||||
|
traits: { id: "traits", group: "primary", label: "ECRY.ui.traits" },
|
||||||
|
combat: { id: "combat", group: "primary", label: "ECRY.ui.healthcombat" },
|
||||||
|
equipements:{ id: "equipements", group: "primary", label: "ECRY.ui.equipment" },
|
||||||
|
biodata: { id: "biodata", group: "primary", label: "ECRY.ui.bionotes" },
|
||||||
|
}
|
||||||
|
if (hasCephaly) {
|
||||||
|
// Insert cephaly after combat, rebuilding the object to preserve insertion order
|
||||||
|
const ordered = {}
|
||||||
|
for (const [k, v] of Object.entries(tabs)) {
|
||||||
|
ordered[k] = v
|
||||||
|
if (k === "combat") ordered.cephaly = { id: "cephaly", group: "primary", label: "ECRY.ui.cephaly" }
|
||||||
|
}
|
||||||
|
for (const tab of Object.values(ordered)) {
|
||||||
|
tab.active = this.tabGroups[tab.group] === tab.id
|
||||||
|
tab.cssClass = tab.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return ordered
|
||||||
|
}
|
||||||
|
for (const tab of Object.values(tabs)) {
|
||||||
|
tab.active = this.tabGroups[tab.group] === tab.id
|
||||||
|
tab.cssClass = tab.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext() {
|
||||||
|
const actor = this.document
|
||||||
|
return {
|
||||||
|
actor,
|
||||||
|
system: actor.system,
|
||||||
|
source: actor.toObject(),
|
||||||
|
fields: actor.schema.fields,
|
||||||
|
systemFields: actor.system.schema.fields,
|
||||||
|
type: actor.type,
|
||||||
|
img: actor.img,
|
||||||
|
name: actor.name,
|
||||||
|
isEditable: this.isEditable,
|
||||||
|
config: game.system.ecryme.config,
|
||||||
|
hasCephaly: EcrymeUtility.hasCephaly(),
|
||||||
|
hasBoheme: EcrymeUtility.hasBoheme(),
|
||||||
|
hasAmertume: EcrymeUtility.hasAmertume(),
|
||||||
|
skills: actor.prepareSkills(),
|
||||||
|
traits: actor.getRollTraits(),
|
||||||
|
ideal: actor.getIdeal(),
|
||||||
|
spleen: actor.getSpleen(),
|
||||||
|
weapons: actor.getWeapons(),
|
||||||
|
maneuvers: actor.getManeuvers(),
|
||||||
|
impactsMalus: actor.getImpactsMalus(),
|
||||||
|
equipments: actor.getEquipments(),
|
||||||
|
cephalySkills:actor.getCephalySkills(),
|
||||||
|
confrontations: actor.getConfrontations(),
|
||||||
|
subActors: actor.getSubActors(),
|
||||||
|
annency: actor.getAnnency(),
|
||||||
|
owner: this.document.isOwner,
|
||||||
|
isGM: game.user.isGM,
|
||||||
|
editScore: this.options.editScore ?? true,
|
||||||
|
tabs: this._getTabs(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _preparePartContext(partId, context) {
|
||||||
|
context = await super._preparePartContext(partId, context)
|
||||||
|
switch (partId) {
|
||||||
|
case "skills":
|
||||||
|
case "traits":
|
||||||
|
case "combat":
|
||||||
|
case "cephaly":
|
||||||
|
case "equipements":
|
||||||
|
context.tab = context.tabs[partId] ?? { cssClass: "" }
|
||||||
|
break
|
||||||
|
case "biodata":
|
||||||
|
context.tab = context.tabs.biodata
|
||||||
|
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||||
|
this.document.system.biodata.description, { async: true }
|
||||||
|
)
|
||||||
|
context.enrichedGmnotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||||
|
this.document.system.biodata.gmnotes, { async: true }
|
||||||
|
)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
// #region Drag and Drop
|
||||||
|
|
||||||
|
/** Handle incoming drops: Items from sidebar/compendium, Actors as subactors */
|
||||||
|
async _onDrop(event) {
|
||||||
|
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)
|
||||||
|
if (!data?.type) return
|
||||||
|
|
||||||
|
if (data.type === "Item") {
|
||||||
|
const item = await fromUuid(data.uuid)
|
||||||
|
if (!item) return
|
||||||
|
await this.document.createEmbeddedDocuments("Item", [item.toObject()])
|
||||||
|
} else if (data.type === "Actor") {
|
||||||
|
const actor = fromUuidSync(data.uuid)
|
||||||
|
if (actor) await this.actor.addSubActor(actor.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handle outgoing drag from embedded item rows */
|
||||||
|
_onDragStart(event) {
|
||||||
|
const li = event.currentTarget.closest("[data-item-id]")
|
||||||
|
if (!li) return
|
||||||
|
const item = this.document.items.get(li.dataset.itemId)
|
||||||
|
if (!item) return
|
||||||
|
event.dataTransfer.setData("text/plain", JSON.stringify(item.toDragData()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region Static Action Handlers
|
||||||
|
|
||||||
|
static #onOpenAnnency(event, target) {
|
||||||
|
const actorId = target.dataset.annencyId
|
||||||
|
game.actors.get(actorId)?.sheet.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onItemEdit(event, target) {
|
||||||
|
const li = target.closest("[data-item-id]")
|
||||||
|
const itemId = li?.dataset.itemId ?? target.dataset.itemId
|
||||||
|
this.document.items.get(itemId)?.sheet.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
static async #onItemDelete(event, target) {
|
||||||
|
const li = target.closest("[data-item-id]")
|
||||||
|
EcrymeUtility.confirmDelete(this, $(li)).catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onItemCreate(event, target) {
|
||||||
|
const dataType = target.dataset.type
|
||||||
|
this.document.createEmbeddedDocuments("Item", [{ name: "NewItem", type: dataType }], { renderSheet: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onSubactorEdit(event, target) {
|
||||||
|
const li = target.closest("[data-actor-id]")
|
||||||
|
game.actors.get(li?.dataset.actorId)?.sheet.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onSubactorDelete(event, target) {
|
||||||
|
const li = target.closest("[data-actor-id]")
|
||||||
|
this.actor.delSubActor(li?.dataset.actorId)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onRollSkill(event, target) {
|
||||||
|
this.actor.rollSkill(target.dataset.categoryKey, target.dataset.skillKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onRollSpec(event, target) {
|
||||||
|
this.actor.rollSpec(target.dataset.categoryKey, target.dataset.skillKey, target.dataset.specId)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onRollSkillConfront(event, target) {
|
||||||
|
this.actor.rollSkillConfront(target.dataset.categoryKey, target.dataset.skillKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onRollCephaly(event, target) {
|
||||||
|
this.actor.rollCephalySkillConfront(target.dataset.skillKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onRollWeaponConfront(event, target) {
|
||||||
|
const li = target.closest("[data-item-id]")
|
||||||
|
this.actor.rollWeaponConfront(li?.dataset.itemId)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onImpactModify(event, target) {
|
||||||
|
this.actor.modifyImpact(
|
||||||
|
target.dataset.impactType,
|
||||||
|
target.dataset.impactLevel,
|
||||||
|
Number(target.dataset.impactModifier)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onRollWeapon(event, target) {
|
||||||
|
this.actor.rollArme(target.dataset.armeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onLockUnlock(event, target) {
|
||||||
|
this.options.editScore = !this.options.editScore
|
||||||
|
this.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onEquipItem(event, target) {
|
||||||
|
const li = target.closest("[data-item-id]")
|
||||||
|
this.actor.equipItem(li?.dataset.itemId)
|
||||||
|
this.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onQuantityMinus(event, target) {
|
||||||
|
const li = target.closest("[data-item-id]")
|
||||||
|
this.actor.incDecQuantity(li?.dataset.itemId, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
static #onQuantityPlus(event, target) {
|
||||||
|
const li = target.closest("[data-item-id]")
|
||||||
|
this.actor.incDecQuantity(li?.dataset.itemId, +1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
}
|
||||||
@@ -1,8 +1,32 @@
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
import { EcrymeUtility } from "../common/ecryme-utility.js";
|
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class EcrymeCharacterSummary extends Application {
|
export class EcrymeCharacterSummary extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) {
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
id: "ecryme-character-summary",
|
||||||
|
classes: ["fvtt-ecryme", "dialog"],
|
||||||
|
position: { width: 920 },
|
||||||
|
window: { title: "ECRY.ui.charactersummary", resizable: true },
|
||||||
|
actions: {
|
||||||
|
actorOpen: EcrymeCharacterSummary.#onActorOpen,
|
||||||
|
summaryRoll: EcrymeCharacterSummary.#onSummaryRoll,
|
||||||
|
actorDelete: EcrymeCharacterSummary.#onActorDelete,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static PARTS = {
|
||||||
|
content: { template: "systems/fvtt-ecryme/templates/dialogs/character-summary.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
constructor(options = {}) {
|
||||||
|
super(options)
|
||||||
|
this.settings = game.settings.get("fvtt-ecryme", "character-summary-data")
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static displayPCSummary() {
|
static displayPCSummary() {
|
||||||
@@ -16,18 +40,13 @@ export class EcrymeCharacterSummary extends Application {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
updatePCSummary() {
|
updatePCSummary() {
|
||||||
if (this.rendered) {
|
if (this.rendered) {
|
||||||
this.render(true)
|
this.render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static createSummaryPos() {
|
|
||||||
return { top: 200, left: 200 };
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static ready() {
|
static ready() {
|
||||||
if (!game.user.isGM) { // Uniquement si GM
|
if (!game.user.isGM) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let charSummary = new EcrymeCharacterSummary()
|
let charSummary = new EcrymeCharacterSummary()
|
||||||
@@ -35,100 +54,81 @@ export class EcrymeCharacterSummary extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor() {
|
async _prepareContext() {
|
||||||
super();
|
let pcs = game.actors.filter(ac => ac.type == "pc" && ac.hasPlayerOwner)
|
||||||
//game.settings.set("world", "character-summary-data", {npcList: [], x:0, y:0})
|
let npcs = []
|
||||||
//this.settings = game.settings.get("world", "character-summary-data")
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static get defaultOptions() {
|
|
||||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
|
||||||
template: "systems/fvtt-ecryme/templates/dialogs/character-summary.hbs",
|
|
||||||
popOut: true,
|
|
||||||
resizable: true,
|
|
||||||
dragDrop: [{ dragSelector: ".items-list .item", dropSelector: null }],
|
|
||||||
classes: ["bol", "dialog"], width: 920, height: 'fit-content'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getData() {
|
|
||||||
let formData = super.getData();
|
|
||||||
|
|
||||||
formData.pcs = game.actors.filter(ac => ac.type == "personnage" && ac.hasPlayerOwner)
|
|
||||||
formData.npcs = []
|
|
||||||
let newList = []
|
let newList = []
|
||||||
let toUpdate = false
|
let toUpdate = false
|
||||||
for (let actorId of this.settings.npcList) {
|
for (let actorId of this.settings.npcList) {
|
||||||
let actor = game.actors.get(actorId)
|
let actor = game.actors.get(actorId)
|
||||||
if (actor) {
|
if (actor) {
|
||||||
formData.npcs.push(actor)
|
npcs.push(actor)
|
||||||
newList.push(actorId)
|
newList.push(actorId)
|
||||||
} else {
|
} else {
|
||||||
toUpdate = true
|
toUpdate = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
formData.config = game.system.ecryme.config
|
|
||||||
|
|
||||||
if (toUpdate) {
|
if (toUpdate) {
|
||||||
this.settings.npcList = newList
|
this.settings.npcList = newList
|
||||||
//console.log("Going to update ...", this.settings)
|
game.settings.set("fvtt-ecryme", "character-summary-data", this.settings)
|
||||||
game.settings.set("world", "character-summary-data", this.settings)
|
}
|
||||||
|
return {
|
||||||
|
pcs,
|
||||||
|
npcs,
|
||||||
|
config: game.system.ecryme.config,
|
||||||
}
|
}
|
||||||
|
|
||||||
return formData
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
updateNPC() {
|
updateNPC() {
|
||||||
game.settings.set("world", "character-summary-data", game.system.ecryme.charSummary.settings)
|
game.settings.set("fvtt-ecryme", "character-summary-data", this.settings)
|
||||||
game.system.ecryme.charSummary.close()
|
this.close()
|
||||||
setTimeout(function () { game.system.ecryme.charSummary.render(true) }, 500)
|
setTimeout(() => this.render(true), 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _onDrop(event) {
|
_onDragOver(event) {
|
||||||
//console.log("Dragged data are : ", dragData)
|
event.preventDefault()
|
||||||
let data = event.dataTransfer.getData('text/plain')
|
}
|
||||||
let dataItem = JSON.parse(data)
|
|
||||||
let actor = fromUuidSync(dataItem.uuid)
|
|
||||||
if (actor) {
|
|
||||||
game.system.ecryme.charSummary.settings.npcList.push(actor.id)
|
|
||||||
game.system.ecryme.charSummary.updateNPC()
|
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
_onDrop(event) {
|
||||||
|
let data
|
||||||
|
try { data = JSON.parse(event.dataTransfer.getData('text/plain')) } catch(e) { return }
|
||||||
|
let actor = fromUuidSync(data.uuid)
|
||||||
|
if (actor) {
|
||||||
|
this.settings.npcList.push(actor.id)
|
||||||
|
this.updateNPC()
|
||||||
} else {
|
} else {
|
||||||
ui.notifications.warn("Pas d'acteur trouvé")
|
ui.notifications.warn("Pas d'acteur trouvé")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/** @override */
|
_onRender(context, options) {
|
||||||
async activateListeners(html) {
|
super._onRender(context, options)
|
||||||
super.activateListeners(html);
|
this.element.addEventListener("dragover", this._onDragOver.bind(this))
|
||||||
|
this.element.addEventListener("drop", this._onDrop.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
html.find('.actor-open').click((event) => {
|
/* -------------------------------------------- */
|
||||||
const li = $(event.currentTarget).parents(".item")
|
static #onActorOpen(event, target) {
|
||||||
const actor = game.actors.get(li.data("actor-id"))
|
const actorId = target.closest("[data-actor-id]").dataset.actorId
|
||||||
actor.sheet.render(true)
|
game.actors.get(actorId)?.sheet.render(true)
|
||||||
})
|
}
|
||||||
|
|
||||||
html.find('.summary-roll').click((event) => {
|
/* -------------------------------------------- */
|
||||||
const li = $(event.currentTarget).parents(".item")
|
static #onSummaryRoll(event, target) {
|
||||||
const actor = game.actors.get(li.data("actor-id"))
|
const actorId = target.closest("[data-actor-id]").dataset.actorId
|
||||||
let type = $(event.currentTarget).data("type")
|
const key = target.dataset.key
|
||||||
let key = $(event.currentTarget).data("key")
|
game.actors.get(actorId)?.rollAttribut(key)
|
||||||
actor.rollAttribut(key)
|
}
|
||||||
})
|
|
||||||
|
|
||||||
html.find('.actor-delete').click(event => {
|
|
||||||
const li = $(event.currentTarget).parents(".item");
|
|
||||||
let actorId = li.data("actor-id")
|
|
||||||
let newList = game.system.ecryme.charSummary.settings.npcList.filter(id => id != actorId)
|
|
||||||
game.system.ecryme.charSummary.settings.npcList = newList
|
|
||||||
game.system.ecryme.charSummary.updateNPC()
|
|
||||||
})
|
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static #onActorDelete(event, target) {
|
||||||
|
const actorId = target.closest("[data-actor-id]").dataset.actorId
|
||||||
|
this.settings.npcList = this.settings.npcList.filter(id => id !== actorId)
|
||||||
|
this.updateNPC()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -101,6 +101,13 @@ export class EcrymeUtility {
|
|||||||
restricted: true
|
restricted: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
game.settings.register("fvtt-ecryme", "character-summary-data", {
|
||||||
|
scope: 'world',
|
||||||
|
config: false,
|
||||||
|
type: Object,
|
||||||
|
default: { npcList: [] }
|
||||||
|
})
|
||||||
|
|
||||||
this.buildSkillConfig()
|
this.buildSkillConfig()
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -123,12 +130,47 @@ export class EcrymeUtility {
|
|||||||
|
|
||||||
/*-------------------------------------------- */
|
/*-------------------------------------------- */
|
||||||
static buildSkillConfig() {
|
static buildSkillConfig() {
|
||||||
|
// Build skill configuration from DataModel structure
|
||||||
game.system.ecryme.config.skills = {}
|
game.system.ecryme.config.skills = {}
|
||||||
for (let categKey in game.data.template.Actor.templates.core.skills) {
|
|
||||||
let category = game.data.template.Actor.templates.core.skills[categKey]
|
const skillCategories = {
|
||||||
|
physical: {
|
||||||
|
name: "ECRY.ui.physical",
|
||||||
|
skilllist: {
|
||||||
|
athletics: { key: "athletics", name: "ECRY.ui.athletics", max: 0, value: 0 },
|
||||||
|
driving: { key: "driving", name: "ECRY.ui.driving", max: 0, value: 0 },
|
||||||
|
fencing: { key: "fencing", name: "ECRY.ui.fencing", max: 0, value: 0 },
|
||||||
|
brawling: { key: "brawling", name: "ECRY.ui.brawling", max: 0, value: 0 },
|
||||||
|
shooting: { key: "shooting", name: "ECRY.ui.shooting", max: 0, value: 0 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mental: {
|
||||||
|
name: "ECRY.ui.mental",
|
||||||
|
skilllist: {
|
||||||
|
anthropomecanology: { key: "anthropomecanology", name: "ECRY.ui.anthropomecanology", max: 10, value: 0 },
|
||||||
|
ecrymology: { key: "ecrymology", name: "ECRY.ui.ecrymology", max: 10, value: 0 },
|
||||||
|
traumatology: { key: "traumatology", name: "ECRY.ui.traumatology", max: 10, value: 0 },
|
||||||
|
traversology: { key: "traversology", name: "ECRY.ui.traversology", max: 10, value: 0 },
|
||||||
|
urbatechnology: { key: "urbatechnology", name: "ECRY.ui.urbatechnology", max: 10, value: 0 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
social: {
|
||||||
|
name: "ECRY.ui.social",
|
||||||
|
skilllist: {
|
||||||
|
quibbling: { key: "quibbling", name: "ECRY.ui.quibbling", max: 10, value: 0 },
|
||||||
|
creativity: { key: "creativity", name: "ECRY.ui.creativity", max: 10, value: 0 },
|
||||||
|
loquacity: { key: "loquacity", name: "ECRY.ui.loquacity", max: 10, value: 0 },
|
||||||
|
guile: { key: "guile", name: "ECRY.ui.guile", max: 10, value: 0 },
|
||||||
|
performance: { key: "performance", name: "ECRY.ui.performance", max: 10, value: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let categKey in skillCategories) {
|
||||||
|
let category = skillCategories[categKey]
|
||||||
for (let skillKey in category.skilllist) {
|
for (let skillKey in category.skilllist) {
|
||||||
let skill = foundry.utils.duplicate(category.skilllist[skillKey])
|
let skill = foundry.utils.duplicate(category.skilllist[skillKey])
|
||||||
skill.categKey = categKey // Auto reference the category
|
skill.categKey = categKey
|
||||||
game.system.ecryme.config.skills[skillKey] = skill
|
game.system.ecryme.config.skills[skillKey] = skill
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,8 +197,8 @@ export class EcrymeUtility {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getActorFromRollData(rollData) {
|
static getActorFromRollData(rollData) {
|
||||||
let actor = game.actors.get(rollData.actorId)
|
let actor = game.actors.get(rollData.actorId)
|
||||||
if (rollData.tokenId) {
|
if (rollData.defenderTokenId) {
|
||||||
let token = canvas.tokens.placeables.find(t => t.id == rollData.tokenId)
|
let token = canvas.tokens.placeables.find(t => t.id == rollData.defenderTokenId)
|
||||||
if (token) {
|
if (token) {
|
||||||
actor = token.actor
|
actor = token.actor
|
||||||
}
|
}
|
||||||
@@ -176,6 +218,8 @@ export class EcrymeUtility {
|
|||||||
type: "confront-data",
|
type: "confront-data",
|
||||||
rollData1: this.confrontData1,
|
rollData1: this.confrontData1,
|
||||||
rollData2: this.confrontData2,
|
rollData2: this.confrontData2,
|
||||||
|
alias: this.confrontData1.alias,
|
||||||
|
actorImg: this.confrontData1.actorImg,
|
||||||
}
|
}
|
||||||
// Compute margin
|
// Compute margin
|
||||||
confront.marginExecution = this.confrontData1.executionTotal - this.confrontData2.preservationTotal
|
confront.marginExecution = this.confrontData1.executionTotal - this.confrontData2.preservationTotal
|
||||||
@@ -311,7 +355,15 @@ export class EcrymeUtility {
|
|||||||
$(html).on("click", '.button-apply-impact', event => {
|
$(html).on("click", '.button-apply-impact', event => {
|
||||||
let messageId = EcrymeUtility.findChatMessageId(event.currentTarget)
|
let messageId = EcrymeUtility.findChatMessageId(event.currentTarget)
|
||||||
let message = game.messages.get(messageId)
|
let message = game.messages.get(messageId)
|
||||||
let actor = game.actors.get($(event.currentTarget).data("actor-id"))
|
let tokenId = $(event.currentTarget).data("token-id")
|
||||||
|
let actor
|
||||||
|
if (!tokenId) {
|
||||||
|
actorId = $(event.currentTarget).data("actor-id")
|
||||||
|
actor = game.actors.get(actorId)
|
||||||
|
} else {
|
||||||
|
let token = canvas.tokens.placeables.find(t => t.id == tokenId)
|
||||||
|
actor = token?.actor
|
||||||
|
}
|
||||||
actor.modifyImpact($(event.currentTarget).data("impact-type"), $(event.currentTarget).data("impact"), 1)
|
actor.modifyImpact($(event.currentTarget).data("impact-type"), $(event.currentTarget).data("impact"), 1)
|
||||||
})
|
})
|
||||||
$(html).on("click", '.button-apply-bonus', event => {
|
$(html).on("click", '.button-apply-bonus', event => {
|
||||||
@@ -335,6 +387,9 @@ export class EcrymeUtility {
|
|||||||
'systems/fvtt-ecryme/templates/dialogs/partial-confront-dice-area.hbs',
|
'systems/fvtt-ecryme/templates/dialogs/partial-confront-dice-area.hbs',
|
||||||
'systems/fvtt-ecryme/templates/dialogs/partial-confront-bonus-area.hbs',
|
'systems/fvtt-ecryme/templates/dialogs/partial-confront-bonus-area.hbs',
|
||||||
'systems/fvtt-ecryme/templates/actors/partial-impacts.hbs',
|
'systems/fvtt-ecryme/templates/actors/partial-impacts.hbs',
|
||||||
|
'systems/fvtt-ecryme/templates/actors/partials/actor-header.hbs',
|
||||||
|
'systems/fvtt-ecryme/templates/items/partials/item-header.hbs',
|
||||||
|
'systems/fvtt-ecryme/templates/items/partials/item-description.hbs',
|
||||||
]
|
]
|
||||||
return foundry.applications.handlebars.loadTemplates(templatePaths);
|
return foundry.applications.handlebars.loadTemplates(templatePaths);
|
||||||
}
|
}
|
||||||
@@ -715,11 +770,11 @@ export class EcrymeUtility {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async confirmDelete(actorSheet, li) {
|
static async confirmDelete(actorSheet, li) {
|
||||||
let itemId = li.data("item-id");
|
let itemId = li.data("item-id");
|
||||||
let msgTxt = "<p>Are you sure to remove this Item ?";
|
let msgTxt = "<p>Etes vous certain de souhaiter envoyer cet item dans les limbes ?";
|
||||||
let buttons = {
|
let buttons = {
|
||||||
delete: {
|
delete: {
|
||||||
icon: '<i class="fas fa-check"></i>',
|
icon: '<i class="fas fa-check"></i>',
|
||||||
label: "Yes, remove it",
|
label: "Oui, retirez-le",
|
||||||
callback: () => {
|
callback: () => {
|
||||||
actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]);
|
actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]);
|
||||||
li.slideUp(200, () => actorSheet.render(false));
|
li.slideUp(200, () => actorSheet.render(false));
|
||||||
@@ -727,7 +782,7 @@ export class EcrymeUtility {
|
|||||||
},
|
},
|
||||||
cancel: {
|
cancel: {
|
||||||
icon: '<i class="fas fa-times"></i>',
|
icon: '<i class="fas fa-times"></i>',
|
||||||
label: "Cancel"
|
label: "Annuler"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msgTxt += "</p>";
|
msgTxt += "</p>";
|
||||||
|
|||||||
@@ -1,168 +1,191 @@
|
|||||||
import { EcrymeUtility } from "../common/ecryme-utility.js";
|
import { EcrymeUtility } from "../common/ecryme-utility.js";
|
||||||
import { EcrymeRollDialog } from "./ecryme-roll-dialog.js";
|
|
||||||
|
|
||||||
export class EcrymeConfrontDialog extends Dialog {
|
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main confrontation dialog — Application V2 version.
|
||||||
|
* Features drag-and-drop of dice from the pool to execution/preservation slots.
|
||||||
|
* All event listeners (change + drag-drop) are bound once via _listenersAdded guard.
|
||||||
|
*/
|
||||||
|
export class EcrymeConfrontDialog extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) {
|
||||||
|
|
||||||
|
#dragDrop
|
||||||
|
_listenersAdded = false
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
constructor(actor, rollData, options = {}) {
|
||||||
|
super(options)
|
||||||
|
this.actor = actor
|
||||||
|
this.rollData = rollData
|
||||||
|
this.buttonDisabled = true
|
||||||
|
this.#dragDrop = this.#createDragDropHandlers()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["fvtt-ecryme", "ecryme-confrontation-dialog"],
|
||||||
|
position: { width: 640 },
|
||||||
|
window: { title: "ECRY.ui.confront" },
|
||||||
|
dragDrop: [{ dragSelector: ".confront-dice-container", dropSelector: null }],
|
||||||
|
actions: {
|
||||||
|
launchConfront: EcrymeConfrontDialog.#onLaunchConfront,
|
||||||
|
cancel: EcrymeConfrontDialog.#onCancel,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
content: { template: "systems/fvtt-ecryme/templates/dialogs/confront-dialog.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async create(actor, rollData) {
|
static async create(actor, rollData) {
|
||||||
|
return new EcrymeConfrontDialog(actor, rollData)
|
||||||
let options = foundry.utils.mergeObject(super.defaultOptions, {
|
|
||||||
classes: ["fvtt-ecryme ecryme-confrontation-dialog"],
|
|
||||||
dragDrop: [{ dragSelector: ".confront-dice-container", dropSelector: null }],
|
|
||||||
width: 620, height: 'fit-content', 'z-index': 99999
|
|
||||||
});
|
|
||||||
|
|
||||||
let html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-ecryme/templates/dialogs/confront-dialog.hbs', rollData);
|
|
||||||
return new EcrymeConfrontDialog(actor, rollData, html, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(actor, rollData, html, options, close = undefined) {
|
async _prepareContext() {
|
||||||
let conf = {
|
return {
|
||||||
title: game.i18n.localize("ECRY.ui.confront"),
|
...this.rollData,
|
||||||
content: html,
|
config: game.system.ecryme.config,
|
||||||
buttons: {
|
buttonDisabled: this.buttonDisabled,
|
||||||
launchConfront: {
|
|
||||||
icon: '<i class="fas fa-check"></i>',
|
|
||||||
label: game.i18n.localize("ECRY.ui.launchconfront"),
|
|
||||||
callback: () => { this.launchConfront().catch("Error when launching Confrontation") }
|
|
||||||
},
|
|
||||||
cancel: {
|
|
||||||
icon: '<i class="fas fa-times"></i>',
|
|
||||||
label: game.i18n.localize("ECRY.ui.cancel"),
|
|
||||||
callback: () => { this.close() }
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
close: close
|
|
||||||
}
|
|
||||||
|
|
||||||
super(conf, options);
|
|
||||||
|
|
||||||
this.actor = actor;
|
|
||||||
this.rollData = rollData;
|
|
||||||
|
|
||||||
// Ensure button is disabled
|
|
||||||
setTimeout(function () { $(".launchConfront").attr("disabled", true) }, 180)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async launchConfront() {
|
/** Bind drag-drop and form-change listeners once; re-bind DragDrop on each render. */
|
||||||
let msg = await EcrymeUtility.createChatMessage(this.rollData.alias, "blindroll", {
|
_onRender(context, options) {
|
||||||
content: await renderTemplate(`systems/fvtt-ecryme/templates/chat/chat-confrontation-pending.hbs`, this.rollData)
|
// DragDrop must be re-bound each render because the DOM is replaced
|
||||||
|
this.#dragDrop.forEach(d => d.bind(this.element))
|
||||||
|
|
||||||
|
// Form-change listener is bound once (event delegation survives DOM re-renders)
|
||||||
|
if (!this._listenersAdded) {
|
||||||
|
this._listenersAdded = true
|
||||||
|
this.element.addEventListener('change', this.#onFormChange.bind(this))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
#onFormChange(event) {
|
||||||
|
const target = event.target
|
||||||
|
switch (target.id) {
|
||||||
|
case 'bonusMalusPerso':
|
||||||
|
this.rollData.bonusMalusPerso = Number(target.value)
|
||||||
|
this.computeTotals()
|
||||||
|
break
|
||||||
|
case 'roll-specialization':
|
||||||
|
this.rollData.selectedSpecs = Array.from(target.selectedOptions).map(o => o.value)
|
||||||
|
this.computeTotals()
|
||||||
|
break
|
||||||
|
case 'roll-trait-bonus':
|
||||||
|
this.rollData.traitsBonusSelected = Array.from(target.selectedOptions).map(o => o.value)
|
||||||
|
this.computeTotals()
|
||||||
|
break
|
||||||
|
case 'roll-trait-malus':
|
||||||
|
this.rollData.traitsMalusSelected = Array.from(target.selectedOptions).map(o => o.value)
|
||||||
|
this.computeTotals()
|
||||||
|
break
|
||||||
|
case 'roll-select-transcendence':
|
||||||
|
this.rollData.skillTranscendence = Number(target.value)
|
||||||
|
this.computeTotals()
|
||||||
|
break
|
||||||
|
case 'roll-apply-transcendence':
|
||||||
|
this.rollData.applyTranscendence = target.value
|
||||||
|
this.computeTotals()
|
||||||
|
break
|
||||||
|
case 'annency-bonus':
|
||||||
|
this.rollData.annencyBonus = Number(target.value)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #region Drag-and-Drop
|
||||||
|
|
||||||
|
#createDragDropHandlers() {
|
||||||
|
return this.options.dragDrop.map(d => {
|
||||||
|
d.permissions = {
|
||||||
|
dragstart: () => true,
|
||||||
|
drop: () => true,
|
||||||
|
}
|
||||||
|
d.callbacks = {
|
||||||
|
dragstart: this._onDragStart.bind(this),
|
||||||
|
dragover: this._onDragOver.bind(this),
|
||||||
|
drop: this._onDrop.bind(this),
|
||||||
|
}
|
||||||
|
return new foundry.applications.ux.DragDrop.implementation(d)
|
||||||
})
|
})
|
||||||
EcrymeUtility.blindMessageToGM( { rollData: this.rollData, template: "systems/fvtt-ecryme/templates/chat/chat-confrontation-pending.hbs" })
|
|
||||||
console.log("MSG", this.rollData)
|
|
||||||
msg.setFlag("world", "ecryme-rolldata", this.rollData)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async refreshDice() {
|
|
||||||
this.rollData.filter = "execution"
|
|
||||||
let content = await renderTemplate("systems/fvtt-ecryme/templates/dialogs/partial-confront-dice-area.hbs", this.rollData )
|
|
||||||
content += await renderTemplate("systems/fvtt-ecryme/templates/dialogs/partial-confront-bonus-area.hbs", this.rollData )
|
|
||||||
$("#confront-execution").html(content)
|
|
||||||
|
|
||||||
this.rollData.filter = "preservation"
|
|
||||||
content = await renderTemplate("systems/fvtt-ecryme/templates/dialogs/partial-confront-dice-area.hbs", this.rollData )
|
|
||||||
content += await renderTemplate("systems/fvtt-ecryme/templates/dialogs/partial-confront-bonus-area.hbs", this.rollData )
|
|
||||||
$("#confront-preservation").html(content)
|
|
||||||
|
|
||||||
this.rollData.filter = "mainpool"
|
|
||||||
content = await renderTemplate("systems/fvtt-ecryme/templates/dialogs/partial-confront-dice-area.hbs", this.rollData )
|
|
||||||
$("#confront-dice-pool").html(content)
|
|
||||||
content = await renderTemplate("systems/fvtt-ecryme/templates/dialogs/partial-confront-bonus-area.hbs", this.rollData )
|
|
||||||
$("#confront-bonus-pool").html(content)
|
|
||||||
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async refreshDialog() {
|
|
||||||
const content = await renderTemplate("systems/fvtt-ecryme/templates/dialogs/confront-dialog.hbs", this.rollData)
|
|
||||||
this.data.content = content
|
|
||||||
this.render(true)
|
|
||||||
|
|
||||||
let button = this.buttonDisabled
|
|
||||||
setTimeout(function () { $(".launchConfront").attr("disabled", button) }, 180)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------ -------------------------- */
|
|
||||||
_canDragStart(selector) {
|
|
||||||
console.log("CAN DRAG START", selector, super._canDragStart(selector) )
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
_canDragDrop(selector) {
|
|
||||||
console.log("CAN DRAG DROP", selector, super._canDragDrop(selector) )
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_onDragStart(event) {
|
_onDragStart(event) {
|
||||||
console.log("DRAGSTART::::", event)
|
const target = event.target
|
||||||
super._onDragStart(event)
|
const dragType = target.dataset.dragType
|
||||||
let dragType = $(event.srcElement).data("drag-type")
|
let diceData
|
||||||
let diceData = {}
|
|
||||||
console.log("DRAGTYPE", dragType)
|
if (dragType === "dice") {
|
||||||
if (dragType == "dice") {
|
|
||||||
diceData = {
|
diceData = {
|
||||||
dragType: "dice",
|
dragType: "dice",
|
||||||
diceIndex: $(event.srcElement).data("dice-idx"),
|
diceIndex: target.dataset.diceIdx,
|
||||||
diceValue: $(event.srcElement).data("dice-value"),
|
diceValue: target.dataset.diceValue,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
diceData = {
|
diceData = {
|
||||||
dragType: "bonus",
|
dragType: "bonus",
|
||||||
bonusIndex: $(event.srcElement).data("bonus-idx"),
|
bonusIndex: target.dataset.bonusIdx,
|
||||||
bonusValue: 1
|
bonusValue: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
event.dataTransfer.setData("text/plain", JSON.stringify(diceData));
|
event.dataTransfer.setData("text/plain", JSON.stringify(diceData))
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
_onDragOver(event) {
|
||||||
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_onDrop(event) {
|
_onDrop(event) {
|
||||||
let dataJSON = event.dataTransfer.getData('text/plain')
|
let data
|
||||||
let data = JSON.parse(dataJSON)
|
try { data = JSON.parse(event.dataTransfer.getData("text/plain")) }
|
||||||
if ( data.dragType == "dice") {
|
catch (e) { return }
|
||||||
let idx = Number(data.diceIndex)
|
|
||||||
console.log("DATA", data, event, event.srcElement.className)
|
// Walk up the DOM to find a meaningful drop area
|
||||||
if (event.srcElement.className.includes("execution") &&
|
const executionArea = event.target.closest('.confront-execution-area')
|
||||||
this.rollData.availableDices.filter(d => d.location == "execution").length < 2) {
|
const preservationArea = event.target.closest('.confront-preservation-area')
|
||||||
|
const diceList = event.target.closest('.confrontation-dice-list')
|
||||||
|
const bonusList = event.target.closest('.confrontation-bonus-list')
|
||||||
|
|
||||||
|
if (data.dragType === "dice") {
|
||||||
|
const idx = Number(data.diceIndex)
|
||||||
|
if (executionArea && this.rollData.availableDices.filter(d => d.location === "execution").length < 2) {
|
||||||
this.rollData.availableDices[idx].location = "execution"
|
this.rollData.availableDices[idx].location = "execution"
|
||||||
}
|
} else if (preservationArea && this.rollData.availableDices.filter(d => d.location === "preservation").length < 2) {
|
||||||
if (event.srcElement.className.includes("preservation") &&
|
|
||||||
this.rollData.availableDices.filter(d => d.location == "preservation").length < 2) {
|
|
||||||
this.rollData.availableDices[idx].location = "preservation"
|
this.rollData.availableDices[idx].location = "preservation"
|
||||||
}
|
} else if (diceList) {
|
||||||
if (event.srcElement.className.includes("dice-list")) {
|
|
||||||
this.rollData.availableDices[idx].location = "mainpool"
|
this.rollData.availableDices[idx].location = "mainpool"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.rollData.availableDices.filter(d => d.location == "execution").length == 2 && this.rollData.availableDices.filter(d => d.location == "preservation").length == 2) {
|
const execCount = this.rollData.availableDices.filter(d => d.location === "execution").length
|
||||||
this.buttonDisabled = false
|
const presCount = this.rollData.availableDices.filter(d => d.location === "preservation").length
|
||||||
} else {
|
this.buttonDisabled = !(execCount === 2 && presCount === 2)
|
||||||
this.buttonDisabled = true
|
|
||||||
}
|
} else if (data.dragType === "bonus") {
|
||||||
} else {
|
const idx = Number(data.bonusIndex)
|
||||||
let idx = Number(data.bonusIndex)
|
if (executionArea) this.rollData.confrontBonus[idx].location = "execution"
|
||||||
if (event.srcElement.className.includes("execution")) {
|
else if (preservationArea) this.rollData.confrontBonus[idx].location = "preservation"
|
||||||
this.rollData.confrontBonus[idx].location = "execution"
|
else if (bonusList) this.rollData.confrontBonus[idx].location = "mainpool"
|
||||||
}
|
|
||||||
if (event.srcElement.className.includes("preservation")) {
|
|
||||||
this.rollData.confrontBonus[idx].location = "preservation"
|
|
||||||
}
|
|
||||||
if (event.srcElement.className.includes("bonus-list")) {
|
|
||||||
this.rollData.confrontBonus[idx].location = "mainpool"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manage total values
|
|
||||||
this.computeTotals()
|
this.computeTotals()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
processTranscendence() {
|
processTranscendence() {
|
||||||
// Apply Transcend if needed
|
|
||||||
if (this.rollData.skillTranscendence > 0) {
|
if (this.rollData.skillTranscendence > 0) {
|
||||||
if (this.rollData.applyTranscendence == "execution") {
|
if (this.rollData.applyTranscendence === "execution") {
|
||||||
this.rollData.executionTotal += Number(this.rollData.skillTranscendence)
|
this.rollData.executionTotal += Number(this.rollData.skillTranscendence)
|
||||||
} else {
|
} else {
|
||||||
this.rollData.preservationTotal += Number(this.rollData.skillTranscendence)
|
this.rollData.preservationTotal += Number(this.rollData.skillTranscendence)
|
||||||
@@ -172,94 +195,78 @@ export class EcrymeConfrontDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
computeTotals() {
|
computeTotals() {
|
||||||
let rollData = this.rollData
|
const rollData = this.rollData
|
||||||
let actor = game.actors.get(rollData.actorId)
|
const actor = game.actors.get(rollData.actorId)
|
||||||
|
|
||||||
rollData.executionTotal = rollData.availableDices.filter(d => d.location == "execution").reduce((previous, current) => {
|
rollData.executionTotal = rollData.availableDices
|
||||||
return previous + current.result
|
.filter(d => d.location === "execution")
|
||||||
}, rollData.skill.value)
|
.reduce((acc, d) => acc + d.result, rollData.skill.value)
|
||||||
rollData.executionTotal = rollData.confrontBonus.filter(d => d.location == "execution").reduce((previous, current) => {
|
rollData.executionTotal = rollData.confrontBonus
|
||||||
return previous + 1
|
.filter(d => d.location === "execution")
|
||||||
}, rollData.executionTotal)
|
.reduce((acc) => acc + 1, rollData.executionTotal)
|
||||||
|
|
||||||
rollData.preservationTotal = rollData.availableDices.filter(d => d.location == "preservation").reduce((previous, current) => {
|
rollData.preservationTotal = rollData.availableDices
|
||||||
return previous + current.result
|
.filter(d => d.location === "preservation")
|
||||||
}, rollData.skill.value)
|
.reduce((acc, d) => acc + d.result, rollData.skill.value)
|
||||||
rollData.preservationTotal = rollData.confrontBonus.filter(d => d.location == "preservation").reduce((previous, current) => {
|
rollData.preservationTotal = rollData.confrontBonus
|
||||||
return previous + 1
|
.filter(d => d.location === "preservation")
|
||||||
}, rollData.preservationTotal)
|
.reduce((acc) => acc + 1, rollData.preservationTotal)
|
||||||
|
|
||||||
this.processTranscendence()
|
this.processTranscendence()
|
||||||
|
|
||||||
if (rollData.selectedSpecs && rollData.selectedSpecs.length > 0) {
|
// Specialization
|
||||||
|
if (rollData.selectedSpecs?.length > 0) {
|
||||||
rollData.spec = foundry.utils.duplicate(actor.getSpecialization(rollData.selectedSpecs[0]))
|
rollData.spec = foundry.utils.duplicate(actor.getSpecialization(rollData.selectedSpecs[0]))
|
||||||
rollData.specApplied = true
|
rollData.specApplied = true
|
||||||
rollData.executionTotal += 2
|
rollData.executionTotal += 2
|
||||||
rollData.preservationTotal += 2
|
rollData.preservationTotal += 2
|
||||||
}
|
}
|
||||||
if ( rollData.specApplied && rollData.selectedSpecs.length == 0) {
|
if (rollData.specApplied && rollData.selectedSpecs?.length === 0) {
|
||||||
rollData.spec = undefined
|
rollData.spec = undefined
|
||||||
rollData.specApplied = false
|
rollData.specApplied = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Traits bonus/malus
|
||||||
rollData.bonusMalusTraits = 0
|
rollData.bonusMalusTraits = 0
|
||||||
for (let t of rollData.traitsBonus) {
|
for (const t of rollData.traitsBonus) t.activated = false
|
||||||
t.activated = false
|
for (const t of rollData.traitsMalus) t.activated = false
|
||||||
}
|
|
||||||
for (let t of rollData.traitsMalus) {
|
for (const id of (rollData.traitsBonusSelected ?? [])) {
|
||||||
t.activated = false
|
const trait = rollData.traitsBonus.find(t => t._id === id)
|
||||||
}
|
if (trait) { trait.activated = true; rollData.bonusMalusTraits += Number(trait.system.level) }
|
||||||
if (rollData.traitsBonusSelected && rollData.traitsBonusSelected.length > 0) {
|
|
||||||
for (let id of rollData.traitsBonusSelected) {
|
|
||||||
let trait = rollData.traitsBonus.find(t => t._id == id)
|
|
||||||
trait.activated = true
|
|
||||||
rollData.bonusMalusTraits += Number(trait.system.level)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rollData.traitsMalusSelected && rollData.traitsMalusSelected.length > 0) {
|
|
||||||
for (let id of rollData.traitsMalusSelected) {
|
|
||||||
let trait = rollData.traitsMalus.find(t => t._id == id)
|
|
||||||
trait.activated = true
|
|
||||||
rollData.bonusMalusTraits -= Number(trait.system.level)
|
|
||||||
}
|
}
|
||||||
|
for (const id of (rollData.traitsMalusSelected ?? [])) {
|
||||||
|
const trait = rollData.traitsMalus.find(t => t._id === id)
|
||||||
|
if (trait) { trait.activated = true; rollData.bonusMalusTraits -= Number(trait.system.level) }
|
||||||
}
|
}
|
||||||
|
|
||||||
rollData.executionTotal += Number(rollData.bonusMalusTraits) + Number(rollData.bonusMalusPerso)
|
rollData.executionTotal += Number(rollData.bonusMalusTraits) + Number(rollData.bonusMalusPerso)
|
||||||
rollData.preservationTotal += Number(rollData.bonusMalusTraits) + Number(rollData.bonusMalusPerso)
|
rollData.preservationTotal += Number(rollData.bonusMalusTraits) + Number(rollData.bonusMalusPerso)
|
||||||
|
|
||||||
this.refreshDialog()
|
this.render()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
activateListeners(html) {
|
async launchConfront() {
|
||||||
super.activateListeners(html);
|
const msg = await EcrymeUtility.createChatMessage(this.rollData.alias, "blindroll", {
|
||||||
|
content: await foundry.applications.handlebars.renderTemplate(
|
||||||
|
`systems/fvtt-ecryme/templates/chat/chat-confrontation-pending.hbs`, this.rollData
|
||||||
|
),
|
||||||
|
})
|
||||||
|
EcrymeUtility.blindMessageToGM({
|
||||||
|
rollData: this.rollData,
|
||||||
|
template: "systems/fvtt-ecryme/templates/chat/chat-confrontation-pending.hbs",
|
||||||
|
})
|
||||||
|
msg.setFlag("world", "ecryme-rolldata", this.rollData)
|
||||||
|
}
|
||||||
|
|
||||||
html.find('#bonusMalusPerso').change((event) => {
|
/* -------------------------------------------- */
|
||||||
this.rollData.bonusMalusPerso = event.currentTarget.value
|
static async #onLaunchConfront(event, target) {
|
||||||
this.computeTotals()
|
await this.launchConfront()
|
||||||
})
|
this.close()
|
||||||
html.find('#roll-specialization').change((event) => {
|
}
|
||||||
this.rollData.selectedSpecs = $('#roll-specialization').val()
|
|
||||||
this.computeTotals()
|
|
||||||
})
|
|
||||||
html.find('#roll-trait-bonus').change((event) => {
|
|
||||||
this.rollData.traitsBonusSelected = $('#roll-trait-bonus').val()
|
|
||||||
this.computeTotals()
|
|
||||||
})
|
|
||||||
html.find('#roll-trait-malus').change((event) => {
|
|
||||||
this.rollData.traitsMalusSelected = $('#roll-trait-malus').val()
|
|
||||||
this.computeTotals()
|
|
||||||
})
|
|
||||||
html.find('#roll-select-transcendence').change((event) => {
|
|
||||||
this.rollData.skillTranscendence = Number($('#roll-select-transcendence').val())
|
|
||||||
this.computeTotals()
|
|
||||||
})
|
|
||||||
html.find('#roll-apply-transcendence').change((event) => {
|
|
||||||
this.rollData.applyTranscendence = $('#roll-apply-transcendence').val()
|
|
||||||
this.computeTotals()
|
|
||||||
})
|
|
||||||
html.find('#annency-bonus').change((event) => {
|
|
||||||
this.rollData.annencyBonus = Number(event.currentTarget.value)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
static #onCancel(event, target) {
|
||||||
|
this.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,74 +1,80 @@
|
|||||||
import { EcrymeUtility } from "../common/ecryme-utility.js";
|
import { EcrymeUtility } from "../common/ecryme-utility.js";
|
||||||
import { EcrymeConfrontDialog } from "./ecryme-confront-dialog.js";
|
import { EcrymeConfrontDialog } from "./ecryme-confront-dialog.js";
|
||||||
|
|
||||||
export class EcrymeConfrontStartDialog extends Dialog {
|
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confrontation start dialog — Application V2 version.
|
||||||
|
* Player picks which dice formula to roll (normal / spleen / ideal),
|
||||||
|
* the dice are rolled and the main EcrymeConfrontDialog is opened.
|
||||||
|
*/
|
||||||
|
export class EcrymeConfrontStartDialog extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) {
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["fvtt-ecryme", "ecryme-confront-start-dialog"],
|
||||||
|
position: { width: 540 },
|
||||||
|
window: { title: "ECRY.ui.confront" },
|
||||||
|
actions: {
|
||||||
|
rollNormal: EcrymeConfrontStartDialog.#onRollNormal,
|
||||||
|
rollSpleen: EcrymeConfrontStartDialog.#onRollSpleen,
|
||||||
|
rollIdeal: EcrymeConfrontStartDialog.#onRollIdeal,
|
||||||
|
cancel: EcrymeConfrontStartDialog.#onCancel,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
content: { template: "systems/fvtt-ecryme/templates/dialogs/confront-start-dialog.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
constructor(actor, rollData, options = {}) {
|
||||||
|
super(options)
|
||||||
|
this.actor = actor?.token?.actor ?? actor
|
||||||
|
this.rollData = rollData
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async create(actor, rollData) {
|
static async create(actor, rollData) {
|
||||||
|
if (!actor) throw new Error("Ecryme | No actor provided for confront dialog")
|
||||||
let options = { classes: ["fvtt-ecryme ecryme-confront-dialog"], width: 540, height: 'fit-content', 'z-index': 99999 }
|
if (!rollData) throw new Error("Ecryme | No roll data provided for confront dialog")
|
||||||
let html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-ecryme/templates/dialogs/confront-start-dialog.hbs', rollData);
|
if (actor?.token) rollData.tokenId = actor.token.id
|
||||||
return new EcrymeConfrontStartDialog(actor, rollData, html, options);
|
return new EcrymeConfrontStartDialog(actor, rollData)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(actor, rollData, html, options, close = undefined) {
|
async _prepareContext() {
|
||||||
let conf = {
|
return {
|
||||||
title: game.i18n.localize("ECRY.ui.confront"),
|
...this.rollData,
|
||||||
content: html,
|
config: game.system.ecryme.config,
|
||||||
buttons: {
|
|
||||||
rollNormal: {
|
|
||||||
icon: '<i class="fas fa-check"></i>',
|
|
||||||
label: game.i18n.localize("ECRY.ui.rollnormal"),
|
|
||||||
callback: () => { this.rollConfront("4d6") }
|
|
||||||
},
|
|
||||||
rollSpleen: {
|
|
||||||
icon: '<i class="fas fa-check"></i>',
|
|
||||||
label: game.i18n.localize("ECRY.ui.rollspleen"),
|
|
||||||
callback: () => { this.rollConfront("5d6kl4") }
|
|
||||||
},
|
|
||||||
rollIdeal: {
|
|
||||||
icon: '<i class="fas fa-check"></i>',
|
|
||||||
label: game.i18n.localize("ECRY.ui.rollideal"),
|
|
||||||
callback: () => { this.rollConfront("5d6kh4") }
|
|
||||||
},
|
|
||||||
cancel: {
|
|
||||||
icon: '<i class="fas fa-times"></i>',
|
|
||||||
label: game.i18n.localize("ECRY.ui.cancel"),
|
|
||||||
callback: () => { this.close() }
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
close: close
|
|
||||||
}
|
|
||||||
|
|
||||||
super(conf, options);
|
|
||||||
|
|
||||||
this.actor = actor;
|
|
||||||
this.rollData = rollData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async rollConfront( diceFormula ) {
|
async #rollConfront(diceFormula) {
|
||||||
// Do the initial roll
|
const myRoll = await new Roll(diceFormula).roll()
|
||||||
let myRoll = await new Roll(diceFormula).roll()
|
|
||||||
await EcrymeUtility.showDiceSoNice(myRoll, game.settings.get("core", "rollMode"))
|
await EcrymeUtility.showDiceSoNice(myRoll, game.settings.get("core", "rollMode"))
|
||||||
// Fill the available dice table
|
|
||||||
let rollData = this.rollData
|
const rollData = this.rollData
|
||||||
rollData.roll = foundry.utils.duplicate(myRoll)
|
rollData.roll = foundry.utils.duplicate(myRoll)
|
||||||
rollData.availableDices = []
|
rollData.availableDices = []
|
||||||
for (let result of myRoll.terms[0].results) {
|
for (const result of myRoll.terms[0].results) {
|
||||||
if (!result.discarded) {
|
if (!result.discarded) {
|
||||||
let resultDup = foundry.utils.duplicate(result)
|
const dup = foundry.utils.duplicate(result)
|
||||||
resultDup.location = "mainpool"
|
dup.location = "mainpool"
|
||||||
rollData.availableDices.push(resultDup)
|
rollData.availableDices.push(dup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let confrontDialog = await EcrymeConfrontDialog.create(this.actor, rollData)
|
|
||||||
|
const confrontDialog = await EcrymeConfrontDialog.create(this.actor, rollData)
|
||||||
confrontDialog.render(true)
|
confrontDialog.render(true)
|
||||||
|
this.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
activateListeners(html) {
|
static async #onRollNormal(event, target) { await this.#rollConfront("4d6") }
|
||||||
super.activateListeners(html);
|
static async #onRollSpleen(event, target) { await this.#rollConfront("5d6kl4") }
|
||||||
}
|
static async #onRollIdeal(event, target) { await this.#rollConfront("5d6kh4") }
|
||||||
|
static #onCancel(event, target) { this.close() }
|
||||||
}
|
}
|
||||||
@@ -1,86 +1,78 @@
|
|||||||
import { EcrymeUtility } from "../common/ecryme-utility.js";
|
import { EcrymeUtility } from "../common/ecryme-utility.js";
|
||||||
|
|
||||||
export class EcrymeRollDialog extends Dialog {
|
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Roll dialog — Application V2 version.
|
||||||
|
* Reads all form values at roll time (no live tracking needed).
|
||||||
|
*/
|
||||||
|
export class EcrymeRollDialog extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) {
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["fvtt-ecryme", "ecryme-roll-dialog"],
|
||||||
|
position: { width: 540 },
|
||||||
|
window: { title: "ECRY.ui.rolltitle" },
|
||||||
|
actions: {
|
||||||
|
roll: EcrymeRollDialog.#onRoll,
|
||||||
|
cancel: EcrymeRollDialog.#onCancel,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
content: { template: "systems/fvtt-ecryme/templates/dialogs/roll-dialog-generic.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
constructor(actor, rollData, options = {}) {
|
||||||
|
super(options)
|
||||||
|
this.actor = actor
|
||||||
|
this.rollData = rollData
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async create(actor, rollData) {
|
static async create(actor, rollData) {
|
||||||
|
return new EcrymeRollDialog(actor, rollData)
|
||||||
let options = { classes: ["ecryme-roll-dialog"], width: 540, height: 'fit-content', 'z-index': 99999 }
|
|
||||||
let html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-ecryme/templates/dialogs/roll-dialog-generic.hbs', rollData);
|
|
||||||
return new EcrymeRollDialog(actor, rollData, html, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(actor, rollData, html, options, close = undefined) {
|
async _prepareContext() {
|
||||||
let conf = {
|
return {
|
||||||
title: game.i18n.localize("ECRY.ui.rolltitle"),
|
...this.rollData,
|
||||||
content: html,
|
config: game.system.ecryme.config,
|
||||||
buttons: {
|
|
||||||
roll: {
|
|
||||||
icon: '<i class="fas fa-check"></i>',
|
|
||||||
label: game.i18n.localize("ECRY.ui.roll"),
|
|
||||||
callback: () => { this.roll() }
|
|
||||||
},
|
|
||||||
cancel: {
|
|
||||||
icon: '<i class="fas fa-times"></i>',
|
|
||||||
label: game.i18n.localize("ECRY.ui.cancel"),
|
|
||||||
callback: () => { this.close() }
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
close: close
|
|
||||||
}
|
|
||||||
|
|
||||||
super(conf, options);
|
|
||||||
|
|
||||||
this.actor = actor;
|
|
||||||
this.rollData = rollData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
roll() {
|
/** Read all form values at roll time, then execute. */
|
||||||
|
static #onRoll(event, target) {
|
||||||
|
const el = this.element
|
||||||
|
|
||||||
|
const bonusEl = el.querySelector('#bonusMalusPerso')
|
||||||
|
const diffEl = el.querySelector('#roll-difficulty')
|
||||||
|
const specEl = el.querySelector('#roll-specialization')
|
||||||
|
const traitBonusEl = el.querySelector('#roll-trait-bonus')
|
||||||
|
const traitMalusEl = el.querySelector('#roll-trait-malus')
|
||||||
|
const transcEl = el.querySelector('#roll-select-transcendence')
|
||||||
|
const spleenEl = el.querySelector('#roll-use-spleen')
|
||||||
|
const idealEl = el.querySelector('#roll-use-ideal')
|
||||||
|
|
||||||
|
if (bonusEl) this.rollData.bonusMalusPerso = Number(bonusEl.value)
|
||||||
|
if (diffEl) this.rollData.difficulty = Number(diffEl.value) || 0
|
||||||
|
if (specEl) this.rollData.selectedSpecs = Array.from(specEl.selectedOptions).map(o => o.value)
|
||||||
|
if (traitBonusEl) this.rollData.traitsBonus = Array.from(traitBonusEl.selectedOptions).map(o => o.value)
|
||||||
|
if (traitMalusEl) this.rollData.traitsMalus = Array.from(traitMalusEl.selectedOptions).map(o => o.value)
|
||||||
|
if (transcEl) this.rollData.skillTranscendence = Number(transcEl.value)
|
||||||
|
if (spleenEl) this.rollData.useSpleen = spleenEl.checked
|
||||||
|
if (idealEl) this.rollData.useIdeal = idealEl.checked
|
||||||
|
|
||||||
EcrymeUtility.rollEcryme(this.rollData)
|
EcrymeUtility.rollEcryme(this.rollData)
|
||||||
|
this.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async refreshDialog() {
|
static #onCancel(event, target) {
|
||||||
const content = await renderTemplate("systems/fvtt-ecryme/templates/dialogs/roll-dialog-generic.hbs", this.rollData)
|
this.close()
|
||||||
this.data.content = content
|
|
||||||
this.render(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
|
|
||||||
function onLoad() {
|
|
||||||
}
|
|
||||||
$(function () { onLoad(); });
|
|
||||||
|
|
||||||
html.find('#bonusMalusPerso').change((event) => {
|
|
||||||
console.log("DIFF", event.currentTarget.value)
|
|
||||||
this.rollData.bonusMalusPerso = Number(event.currentTarget.value)
|
|
||||||
})
|
|
||||||
html.find('#roll-difficulty').change((event) => {
|
|
||||||
this.rollData.difficulty = Number(event.currentTarget.value) || 0
|
|
||||||
})
|
|
||||||
html.find('#roll-specialization').change((event) => {
|
|
||||||
this.rollData.selectedSpecs = $('#roll-specialization').val()
|
|
||||||
})
|
|
||||||
html.find('#roll-trait-bonus').change((event) => {
|
|
||||||
this.rollData.traitsBonus = $('#roll-trait-bonus').val()
|
|
||||||
})
|
|
||||||
html.find('#roll-trait-malus').change((event) => {
|
|
||||||
this.rollData.traitsMalus = $('#roll-trait-malus').val()
|
|
||||||
})
|
|
||||||
html.find('#roll-select-transcendence').change((event) => {
|
|
||||||
this.rollData.skillTranscendence = Number($('#roll-select-transcendence').val())
|
|
||||||
})
|
|
||||||
html.find('#roll-use-spleen').change((event) => {
|
|
||||||
this.rollData.useSpleen = event.currentTarget.checked
|
|
||||||
})
|
|
||||||
html.find('#roll-use-ideal').change((event) => {
|
|
||||||
this.rollData.useIdeal = event.currentTarget.checked
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+60
-15
@@ -5,19 +5,30 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
const ECRYME_WELCOME_MESSAGE_URL = "https://www.uberwald.me/gitea/public/fvtt-ecryme/raw/branch/master/welcome-message-ecryme.html"
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// Import Modules
|
// Import Modules
|
||||||
import { EcrymeActor } from "./actors/ecryme-actor.js";
|
import { EcrymeActor } from "./actors/ecryme-actor.js";
|
||||||
import { EcrymeItemSheet } from "./items/ecryme-item-sheet.js";
|
import { EcrymeItemSheet } from "./items/ecryme-item-sheet.js";
|
||||||
import { EcrymeActorSheet } from "./actors/ecryme-actor-sheet.js";
|
import {
|
||||||
import { EcrymeAnnencySheet } from "./actors/ecryme-annency-sheet.js";
|
EcrymeEquipmentSheet,
|
||||||
|
EcrymeWeaponSheet,
|
||||||
|
EcrymeTraitSheet,
|
||||||
|
EcrymeSpecializationSheet,
|
||||||
|
EcrymeManeuverSheet
|
||||||
|
} from "./items/sheets/_module.js";
|
||||||
|
import {
|
||||||
|
EcrymeActorSheet,
|
||||||
|
EcrymeAnnencySheet
|
||||||
|
} from "./actors/sheets/_module.js";
|
||||||
import { EcrymeUtility } from "./common/ecryme-utility.js";
|
import { EcrymeUtility } from "./common/ecryme-utility.js";
|
||||||
import { EcrymeCombat } from "./app/ecryme-combat.js";
|
import { EcrymeCombat } from "./app/ecryme-combat.js";
|
||||||
import { EcrymeItem } from "./items/ecryme-item.js";
|
import { EcrymeItem } from "./items/ecryme-item.js";
|
||||||
import { EcrymeHotbar } from "./app/ecryme-hotbar.js"
|
import { EcrymeHotbar } from "./app/ecryme-hotbar.js"
|
||||||
import { EcrymeCharacterSummary } from "./app/ecryme-summary-app.js"
|
import { EcrymeCharacterSummary } from "./app/ecryme-summary-app.js"
|
||||||
import { ECRYME_CONFIG } from "./common/ecryme-config.js"
|
import { ECRYME_CONFIG } from "./common/ecryme-config.js"
|
||||||
|
import * as models from "./models/_module.js"
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Foundry VTT Initialization */
|
/* Foundry VTT Initialization */
|
||||||
@@ -26,12 +37,7 @@ import { ECRYME_CONFIG } from "./common/ecryme-config.js"
|
|||||||
/************************************************************************************/
|
/************************************************************************************/
|
||||||
Hooks.once("init", async function () {
|
Hooks.once("init", async function () {
|
||||||
|
|
||||||
console.log(`Initializing Ecryme RPG`);
|
console.log(`Initializing Ecryme RPG System`);
|
||||||
|
|
||||||
game.system.ecryme = {
|
|
||||||
config: ECRYME_CONFIG,
|
|
||||||
EcrymeHotbar
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// preload handlebars templates
|
// preload handlebars templates
|
||||||
@@ -53,17 +59,40 @@ Hooks.once("init", async function () {
|
|||||||
// Define custom Entity classes
|
// Define custom Entity classes
|
||||||
CONFIG.Combat.documentClass = EcrymeCombat
|
CONFIG.Combat.documentClass = EcrymeCombat
|
||||||
CONFIG.Actor.documentClass = EcrymeActor
|
CONFIG.Actor.documentClass = EcrymeActor
|
||||||
|
CONFIG.Actor.dataModels = {
|
||||||
|
pc: models.EcrymePCDataModel,
|
||||||
|
npc: models.EcrymeNPCDataModel,
|
||||||
|
annency: models.EcrymeAnnencyDataModel
|
||||||
|
}
|
||||||
|
|
||||||
CONFIG.Item.documentClass = EcrymeItem
|
CONFIG.Item.documentClass = EcrymeItem
|
||||||
|
CONFIG.Item.dataModels = {
|
||||||
|
equipment: models.EcrymeEquipmentDataModel,
|
||||||
|
weapon: models.EcrymeWeaponDataModel,
|
||||||
|
trait: models.EcrymeTraitDataModel,
|
||||||
|
specialization: models.EcrymeSpecializationDataModel,
|
||||||
|
maneuver: models.EcrymeManeuverDataModel
|
||||||
|
}
|
||||||
|
|
||||||
|
game.system.ecryme = {
|
||||||
|
config: ECRYME_CONFIG,
|
||||||
|
models,
|
||||||
|
EcrymeHotbar
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// Register sheet application classes
|
// Register sheet application classes
|
||||||
foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet);
|
foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet);
|
||||||
foundry.documents.collections.Actors.registerSheet("fvtt-ecryme", EcrymeActorSheet, { types: ["pc"], makeDefault: true });
|
foundry.documents.collections.Actors.registerSheet("fvtt-ecryme", EcrymeActorSheet, { types: ["pc"], makeDefault: true });
|
||||||
foundry.documents.collections.Actors.registerSheet("fvtt-ecryme", EcrymeActorSheet, { types: ["npc"], makeDefault: true });
|
foundry.documents.collections.Actors.registerSheet("fvtt-ecryme", EcrymeActorSheet, { types: ["npc"], makeDefault: true });
|
||||||
foundry.documents.collections.Actors.registerSheet("fvtt-ecryme", EcrymeAnnencySheet, { types: ["annency"], makeDefault: false });
|
foundry.documents.collections.Actors.registerSheet("fvtt-ecryme", EcrymeAnnencySheet, { types: ["annency"], makeDefault: true });
|
||||||
|
|
||||||
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet);
|
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet);
|
||||||
foundry.documents.collections.Items.registerSheet("fvtt-ecryme", EcrymeItemSheet, { makeDefault: true });
|
foundry.documents.collections.Items.registerSheet("fvtt-ecryme", EcrymeEquipmentSheet, { types: ["equipment"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-ecryme", EcrymeWeaponSheet, { types: ["weapon"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-ecryme", EcrymeTraitSheet, { types: ["trait"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-ecryme", EcrymeSpecializationSheet, { types: ["specialization"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-ecryme", EcrymeManeuverSheet, { types: ["maneuver"], makeDefault: true });
|
||||||
|
|
||||||
EcrymeUtility.init()
|
EcrymeUtility.init()
|
||||||
|
|
||||||
@@ -72,11 +101,25 @@ Hooks.once("init", async function () {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
function welcomeMessage() {
|
function welcomeMessage() {
|
||||||
if (game.user.isGM) {
|
if (game.user.isGM) {
|
||||||
|
// Try to fetch the welcome message from the github repo "welcome-message-ecryme.html"
|
||||||
|
fetch(ECRYME_WELCOME_MESSAGE_URL)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(html => {
|
||||||
|
//console.log("Fetched welcome message:", html);
|
||||||
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-ecryme"><span class="rdd-roll-part">
|
content: html
|
||||||
<strong>Bienvenu dans Ecryme !</strong>` });
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("Error fetching welcome message:", error);
|
||||||
|
ChatMessage.create({
|
||||||
|
user: game.user.id,
|
||||||
|
whisper: [game.user.id],
|
||||||
|
content: "<b>Bienvenue dans Ecryme RPG !</b><br>Visitez le site officiel pour plus d'informations."
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,11 +161,13 @@ Hooks.once("ready", function () {
|
|||||||
EcrymeCharacterSummary.ready();
|
EcrymeCharacterSummary.ready();
|
||||||
importDefaultScene();
|
importDefaultScene();
|
||||||
|
|
||||||
// Load translations
|
|
||||||
Babele.get().setSystemTranslationsDir("translated")
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
Hooks.once("babele.init", (babele) => {
|
||||||
|
console.log("Initializing Babele translations")
|
||||||
|
babele.setSystemTranslationsDir("translated");
|
||||||
|
});
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Foundry VTT Initialization */
|
/* Foundry VTT Initialization */
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export { default as EcrymeBaseItemSheet } from "./base-item-sheet.js"
|
||||||
|
export { default as EcrymeEquipmentSheet } from "./equipment-sheet.js"
|
||||||
|
export { default as EcrymeWeaponSheet } from "./weapon-sheet.js"
|
||||||
|
export { default as EcrymeTraitSheet } from "./trait-sheet.js"
|
||||||
|
export { default as EcrymeSpecializationSheet } from "./specialization-sheet.js"
|
||||||
|
export { default as EcrymeManeuverSheet } from "./maneuver-sheet.js"
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base item sheet for Ecryme using Application V2.
|
||||||
|
* Subclasses must define static PARTS including header, tabs, description, and optionally details.
|
||||||
|
*/
|
||||||
|
export default class EcrymeBaseItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
|
||||||
|
|
||||||
|
constructor(options = {}) {
|
||||||
|
super(options)
|
||||||
|
this.#dragDrop = this.#createDragDropHandlers()
|
||||||
|
}
|
||||||
|
|
||||||
|
#dragDrop
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["fvtt-ecryme", "item"],
|
||||||
|
position: {
|
||||||
|
width: 520,
|
||||||
|
height: "auto",
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
submitOnChange: true,
|
||||||
|
},
|
||||||
|
window: {
|
||||||
|
resizable: true,
|
||||||
|
},
|
||||||
|
dragDrop: [{ dragSelector: "[data-drag]", dropSelector: null }],
|
||||||
|
actions: {
|
||||||
|
editImage: EcrymeBaseItemSheet.#onEditImage,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Active tab group tracking */
|
||||||
|
tabGroups = {
|
||||||
|
primary: "description",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the tabs definition, adding a "details" tab only if the subclass has a "details" PART.
|
||||||
|
* @returns {Record<string, object>}
|
||||||
|
*/
|
||||||
|
_getTabs() {
|
||||||
|
const tabs = {
|
||||||
|
description: { id: "description", group: "primary", label: "ECRY.ui.description" },
|
||||||
|
}
|
||||||
|
if (this.constructor.PARTS?.details) {
|
||||||
|
tabs.details = { id: "details", group: "primary", label: "ECRY.ui.details" }
|
||||||
|
}
|
||||||
|
for (const tab of Object.values(tabs)) {
|
||||||
|
tab.active = this.tabGroups[tab.group] === tab.id
|
||||||
|
tab.cssClass = tab.active ? "active" : ""
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @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(),
|
||||||
|
config: game.system.ecryme.config,
|
||||||
|
isEditable: this.isEditable,
|
||||||
|
tabs: this._getTabs(),
|
||||||
|
}
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _preparePartContext(partId, context) {
|
||||||
|
context = await super._preparePartContext(partId, context)
|
||||||
|
if (partId === "description") {
|
||||||
|
context.tab = context.tabs.description
|
||||||
|
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||||
|
this.document.system.description, { async: true }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
_onRender(context, options) {
|
||||||
|
this.#dragDrop.forEach((d) => d.bind(this.element))
|
||||||
|
}
|
||||||
|
|
||||||
|
// #region Drag-and-Drop
|
||||||
|
#createDragDropHandlers() {
|
||||||
|
return this.options.dragDrop.map((d) => {
|
||||||
|
d.permissions = {
|
||||||
|
dragstart: this._canDragStart.bind(this),
|
||||||
|
drop: this._canDragDrop.bind(this),
|
||||||
|
}
|
||||||
|
d.callbacks = {
|
||||||
|
dragstart: this._onDragStart.bind(this),
|
||||||
|
dragover: this._onDragOver.bind(this),
|
||||||
|
drop: this._onDrop.bind(this),
|
||||||
|
}
|
||||||
|
return new foundry.applications.ux.DragDrop.implementation(d)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_canDragStart(selector) { return this.isEditable }
|
||||||
|
_canDragDrop(selector) { return this.isEditable && this.document.isOwner }
|
||||||
|
_onDragStart(event) {}
|
||||||
|
_onDragOver(event) {}
|
||||||
|
async _onDrop(event) {}
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region Actions
|
||||||
|
static async #onEditImage(event, target) {
|
||||||
|
const attr = target.dataset.edit
|
||||||
|
const current = foundry.utils.getProperty(this.document, attr)
|
||||||
|
const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}
|
||||||
|
const fp = new FilePicker({
|
||||||
|
current,
|
||||||
|
type: "image",
|
||||||
|
redirectToRoot: img ? [img] : [],
|
||||||
|
callback: (path) => {
|
||||||
|
this.document.update({ [attr]: path })
|
||||||
|
},
|
||||||
|
top: this.position.top + 40,
|
||||||
|
left: this.position.left + 10,
|
||||||
|
})
|
||||||
|
return fp.browse()
|
||||||
|
}
|
||||||
|
// #endregion
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import EcrymeBaseItemSheet from "./base-item-sheet.js"
|
||||||
|
|
||||||
|
export default class EcrymeEquipmentSheet extends EcrymeBaseItemSheet {
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["equipment"],
|
||||||
|
position: { width: 520 },
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
header: { template: "systems/fvtt-ecryme/templates/items/partials/item-header.hbs" },
|
||||||
|
tabs: { template: "templates/generic/tab-navigation.hbs" },
|
||||||
|
description: { template: "systems/fvtt-ecryme/templates/items/partials/item-description.hbs" },
|
||||||
|
details: { template: "systems/fvtt-ecryme/templates/items/item-equipment-details.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _preparePartContext(partId, context) {
|
||||||
|
context = await super._preparePartContext(partId, context)
|
||||||
|
if (partId === "details") context.tab = context.tabs.details
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import EcrymeBaseItemSheet from "./base-item-sheet.js"
|
||||||
|
|
||||||
|
export default class EcrymeManeuverSheet extends EcrymeBaseItemSheet {
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["maneuver"],
|
||||||
|
position: { width: 520 },
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
header: { template: "systems/fvtt-ecryme/templates/items/partials/item-header.hbs" },
|
||||||
|
tabs: { template: "templates/generic/tab-navigation.hbs" },
|
||||||
|
description: { template: "systems/fvtt-ecryme/templates/items/partials/item-description.hbs" },
|
||||||
|
details: { template: "systems/fvtt-ecryme/templates/items/item-maneuver-details.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _preparePartContext(partId, context) {
|
||||||
|
context = await super._preparePartContext(partId, context)
|
||||||
|
if (partId === "details") context.tab = context.tabs.details
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import EcrymeBaseItemSheet from "./base-item-sheet.js"
|
||||||
|
|
||||||
|
export default class EcrymeSpecializationSheet extends EcrymeBaseItemSheet {
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["specialization"],
|
||||||
|
position: { width: 520 },
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
header: { template: "systems/fvtt-ecryme/templates/items/partials/item-header.hbs" },
|
||||||
|
tabs: { template: "templates/generic/tab-navigation.hbs" },
|
||||||
|
description: { template: "systems/fvtt-ecryme/templates/items/partials/item-description.hbs" },
|
||||||
|
details: { template: "systems/fvtt-ecryme/templates/items/item-specialization-details.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _preparePartContext(partId, context) {
|
||||||
|
context = await super._preparePartContext(partId, context)
|
||||||
|
if (partId === "details") context.tab = context.tabs.details
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import EcrymeBaseItemSheet from "./base-item-sheet.js"
|
||||||
|
|
||||||
|
export default class EcrymeTraitSheet extends EcrymeBaseItemSheet {
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["trait"],
|
||||||
|
position: { width: 520 },
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
header: { template: "systems/fvtt-ecryme/templates/items/partials/item-header.hbs" },
|
||||||
|
tabs: { template: "templates/generic/tab-navigation.hbs" },
|
||||||
|
description: { template: "systems/fvtt-ecryme/templates/items/partials/item-description.hbs" },
|
||||||
|
details: { template: "systems/fvtt-ecryme/templates/items/item-trait-details.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _preparePartContext(partId, context) {
|
||||||
|
context = await super._preparePartContext(partId, context)
|
||||||
|
if (partId === "details") context.tab = context.tabs.details
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import EcrymeBaseItemSheet from "./base-item-sheet.js"
|
||||||
|
|
||||||
|
export default class EcrymeWeaponSheet extends EcrymeBaseItemSheet {
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["weapon"],
|
||||||
|
position: { width: 540 },
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
header: { template: "systems/fvtt-ecryme/templates/items/partials/item-header.hbs" },
|
||||||
|
tabs: { template: "templates/generic/tab-navigation.hbs" },
|
||||||
|
description: { template: "systems/fvtt-ecryme/templates/items/partials/item-description.hbs" },
|
||||||
|
details: { template: "systems/fvtt-ecryme/templates/items/item-weapon-details.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _preparePartContext(partId, context) {
|
||||||
|
context = await super._preparePartContext(partId, context)
|
||||||
|
if (partId === "details") context.tab = context.tabs.details
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# This file ensures the models directory is tracked by git
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
# DataModels Ecryme
|
||||||
|
|
||||||
|
## Vue d'ensemble
|
||||||
|
|
||||||
|
Ce dossier contient les DataModels pour le système Ecryme. Les DataModels sont la méthode moderne de Foundry VTT (v10+) pour définir les structures de données des acteurs et des items.
|
||||||
|
|
||||||
|
## Migration depuis template.json
|
||||||
|
|
||||||
|
Le système Ecryme a été migré de l'ancien système `template.json` vers les DataModels. Le fichier `template.json` est conservé pour référence mais est maintenant marqué comme deprecated.
|
||||||
|
|
||||||
|
## Structure des fichiers
|
||||||
|
|
||||||
|
### Modèles d'Items
|
||||||
|
|
||||||
|
- **equipment.js** - Équipements génériques
|
||||||
|
- **weapon.js** - Armes (mêlée et distance)
|
||||||
|
- **trait.js** - Traits de personnage
|
||||||
|
- **specialization.js** - Spécialisations de compétences
|
||||||
|
- **maneuver.js** - Manœuvres de combat
|
||||||
|
|
||||||
|
### Modèles d'Acteurs
|
||||||
|
|
||||||
|
- **pc.js** - Personnages joueurs (PC)
|
||||||
|
- **npc.js** - Personnages non-joueurs (NPC)
|
||||||
|
- **annency.js** - Annency (acteurs spéciaux)
|
||||||
|
|
||||||
|
### Fichier d'index
|
||||||
|
|
||||||
|
- **_module.js** - Centralise tous les exports des DataModels
|
||||||
|
|
||||||
|
## Utilisation
|
||||||
|
|
||||||
|
Les DataModels sont automatiquement enregistrés dans `CONFIG.Actor.dataModels` et `CONFIG.Item.dataModels` lors de l'initialisation du système dans `ecryme-main.js`.
|
||||||
|
|
||||||
|
### Accès aux données
|
||||||
|
|
||||||
|
Dans les acteurs et items, les données du système sont accessibles via `actor.system` ou `item.system` :
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Exemple avec un PC
|
||||||
|
const athletics = actor.system.skills.physical.skilllist.athletics.value;
|
||||||
|
|
||||||
|
// Exemple avec une arme
|
||||||
|
const weaponType = item.system.weapontype;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Avantages des DataModels
|
||||||
|
|
||||||
|
1. **Validation automatique** - Les types de champs sont vérifiés automatiquement
|
||||||
|
2. **Valeurs par défaut** - Chaque champ a une valeur initiale définie
|
||||||
|
3. **Type safety** - Meilleure autocomplete dans les IDEs
|
||||||
|
4. **Performance** - Optimisation interne de Foundry VTT
|
||||||
|
5. **Maintenance** - Code plus propre et organisé
|
||||||
|
|
||||||
|
## Compatibilité
|
||||||
|
|
||||||
|
Les DataModels sont rétrocompatibles avec les données existantes. Les acteurs et items créés avec l'ancien système `template.json` seront automatiquement migrés vers les nouveaux DataModels lors de leur chargement.
|
||||||
|
|
||||||
|
## Développement
|
||||||
|
|
||||||
|
Pour ajouter un nouveau type d'acteur ou d'item :
|
||||||
|
|
||||||
|
1. Créer un nouveau fichier DataModel dans ce dossier
|
||||||
|
2. Définir le schema avec `static defineSchema()`
|
||||||
|
3. Exporter le modèle dans `_module.js`
|
||||||
|
4. Enregistrer le modèle dans `ecryme-main.js` (CONFIG.Actor.dataModels ou CONFIG.Item.dataModels)
|
||||||
|
|
||||||
|
### Exemple minimal
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export default class MyNewItemDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true, min: 0 })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation Foundry VTT
|
||||||
|
|
||||||
|
Pour plus d'informations sur les DataModels :
|
||||||
|
https://foundryvtt.com/article/system-data-models/
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Index des DataModels pour Ecryme
|
||||||
|
* Ce fichier centralise tous les exports des modèles de données
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Modèles d'items (uniquement les types définis dans template.json types array)
|
||||||
|
export { default as EcrymeEquipmentDataModel } from './equipment.js';
|
||||||
|
export { default as EcrymeWeaponDataModel } from './weapon.js';
|
||||||
|
export { default as EcrymeTraitDataModel } from './trait.js';
|
||||||
|
export { default as EcrymeSpecializationDataModel } from './specialization.js';
|
||||||
|
export { default as EcrymeManeuverDataModel } from './maneuver.js';
|
||||||
|
|
||||||
|
// Modèles d'acteurs
|
||||||
|
export { default as EcrymePCDataModel } from './pc.js';
|
||||||
|
export { default as EcrymeNPCDataModel } from './npc.js';
|
||||||
|
export { default as EcrymeAnnencyDataModel } from './annency.js';
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les Annency (acteurs)
|
||||||
|
*/
|
||||||
|
export default class EcrymeAnnencyDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
|
||||||
|
return {
|
||||||
|
base: new fields.SchemaField({
|
||||||
|
iscollective: new fields.BooleanField({ initial: false }),
|
||||||
|
ismultiple: new fields.BooleanField({ initial: false }),
|
||||||
|
characters: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||||
|
location: new fields.SchemaField({
|
||||||
|
"1": new fields.StringField({ initial: "" }),
|
||||||
|
"2": new fields.StringField({ initial: "" }),
|
||||||
|
"3": new fields.StringField({ initial: "" }),
|
||||||
|
"4": new fields.StringField({ initial: "" }),
|
||||||
|
"5": new fields.StringField({ initial: "" })
|
||||||
|
}),
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
enhancements: new fields.StringField({ initial: "" })
|
||||||
|
}),
|
||||||
|
|
||||||
|
boheme: new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ initial: "" }),
|
||||||
|
ideals: new fields.StringField({ initial: "" }),
|
||||||
|
politic: new fields.StringField({ initial: "" }),
|
||||||
|
description: new fields.HTMLField({ initial: "" })
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les équipements
|
||||||
|
*/
|
||||||
|
export default class EcrymeEquipmentDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
weight: new fields.NumberField({ initial: 0, integer: true, min: 0 }),
|
||||||
|
cost: new fields.NumberField({ initial: 0, integer: true, min: 0 }),
|
||||||
|
costunit: new fields.StringField({ initial: "" }),
|
||||||
|
quantity: new fields.NumberField({ initial: 1, integer: true, min: 0 })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les manœuvres
|
||||||
|
*/
|
||||||
|
export default class EcrymeManeuverDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les PNJs (NPC)
|
||||||
|
* Utilise la même structure que les PC
|
||||||
|
*/
|
||||||
|
import EcrymePCDataModel from './pc.js';
|
||||||
|
|
||||||
|
export default class EcrymeNPCDataModel extends EcrymePCDataModel {
|
||||||
|
// Les NPCs utilisent exactement la même structure que les PCs
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les personnages joueurs (PC)
|
||||||
|
*/
|
||||||
|
export default class EcrymePCDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
|
||||||
|
// Template biodata
|
||||||
|
const biodataSchema = {
|
||||||
|
age: new fields.StringField({ initial: "" }),
|
||||||
|
size: new fields.StringField({ initial: "" }),
|
||||||
|
lieunaissance: new fields.StringField({ initial: "" }),
|
||||||
|
nationalite: new fields.StringField({ initial: "" }),
|
||||||
|
profession: new fields.StringField({ initial: "" }),
|
||||||
|
residence: new fields.StringField({ initial: "" }),
|
||||||
|
milieusocial: new fields.StringField({ initial: "" }),
|
||||||
|
poids: new fields.StringField({ initial: "" }),
|
||||||
|
cheveux: new fields.StringField({ initial: "" }),
|
||||||
|
sexe: new fields.StringField({ initial: "" }),
|
||||||
|
yeux: new fields.StringField({ initial: "" }),
|
||||||
|
enfance: new fields.StringField({ initial: "" }),
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
gmnotes: new fields.HTMLField({ initial: "" })
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to create a skill schema (creates new instances each time)
|
||||||
|
const createSkillSchema = (keyValue, nameValue, maxValue = 0) => ({
|
||||||
|
key: new fields.StringField({ initial: keyValue }),
|
||||||
|
name: new fields.StringField({ initial: nameValue }),
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true, min: 0 }),
|
||||||
|
max: new fields.NumberField({ initial: maxValue, integer: true, min: 0 })
|
||||||
|
});
|
||||||
|
|
||||||
|
// Skills categories
|
||||||
|
const physicalSkills = {
|
||||||
|
athletics: new fields.SchemaField(createSkillSchema("athletics", "ECRY.ui.athletics")),
|
||||||
|
driving: new fields.SchemaField(createSkillSchema("driving", "ECRY.ui.driving")),
|
||||||
|
fencing: new fields.SchemaField(createSkillSchema("fencing", "ECRY.ui.fencing")),
|
||||||
|
brawling: new fields.SchemaField(createSkillSchema("brawling", "ECRY.ui.brawling")),
|
||||||
|
shooting: new fields.SchemaField(createSkillSchema("shooting", "ECRY.ui.shooting"))
|
||||||
|
};
|
||||||
|
|
||||||
|
const mentalSkills = {
|
||||||
|
anthropomecanology: new fields.SchemaField(createSkillSchema("anthropomecanology", "ECRY.ui.anthropomecanology", 10)),
|
||||||
|
ecrymology: new fields.SchemaField(createSkillSchema("ecrymology", "ECRY.ui.ecrymology", 10)),
|
||||||
|
traumatology: new fields.SchemaField(createSkillSchema("traumatology", "ECRY.ui.traumatology", 10)),
|
||||||
|
traversology: new fields.SchemaField(createSkillSchema("traversology", "ECRY.ui.traversology", 10)),
|
||||||
|
urbatechnology: new fields.SchemaField(createSkillSchema("urbatechnology", "ECRY.ui.urbatechnology", 10))
|
||||||
|
};
|
||||||
|
|
||||||
|
const socialSkills = {
|
||||||
|
quibbling: new fields.SchemaField(createSkillSchema("quibbling", "ECRY.ui.quibbling", 10)),
|
||||||
|
creativity: new fields.SchemaField(createSkillSchema("creativity", "ECRY.ui.creativity", 10)),
|
||||||
|
loquacity: new fields.SchemaField(createSkillSchema("loquacity", "ECRY.ui.loquacity", 10)),
|
||||||
|
guile: new fields.SchemaField(createSkillSchema("guile", "ECRY.ui.guile", 10)),
|
||||||
|
performance: new fields.SchemaField(createSkillSchema("performance", "ECRY.ui.performance", 10))
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to create a cephaly skill schema
|
||||||
|
const createCephalySkillSchema = (nameValue) => ({
|
||||||
|
name: new fields.StringField({ initial: nameValue }),
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true, min: 0 }),
|
||||||
|
max: new fields.NumberField({ initial: 10, integer: true })
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cephaly skills
|
||||||
|
const cephalySkills = {
|
||||||
|
elegy: new fields.SchemaField(createCephalySkillSchema("ECRY.ui.elegy")),
|
||||||
|
entelechy: new fields.SchemaField(createCephalySkillSchema("ECRY.ui.entelechy")),
|
||||||
|
mekany: new fields.SchemaField(createCephalySkillSchema("ECRY.ui.mekany")),
|
||||||
|
psyche: new fields.SchemaField(createCephalySkillSchema("ECRY.ui.psyche")),
|
||||||
|
scoria: new fields.SchemaField(createCephalySkillSchema("ECRY.ui.scoria"))
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to create an impact schema
|
||||||
|
const createImpactSchema = () => ({
|
||||||
|
superficial: new fields.NumberField({ initial: 0, integer: true, min: 0 }),
|
||||||
|
light: new fields.NumberField({ initial: 0, integer: true, min: 0 }),
|
||||||
|
serious: new fields.NumberField({ initial: 0, integer: true, min: 0 }),
|
||||||
|
major: new fields.NumberField({ initial: 0, integer: true, min: 0 })
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
// Biodata
|
||||||
|
biodata: new fields.SchemaField(biodataSchema),
|
||||||
|
|
||||||
|
// Core data
|
||||||
|
subactors: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||||
|
equipmentfree: new fields.StringField({ initial: "" }),
|
||||||
|
|
||||||
|
// Skills
|
||||||
|
skills: new fields.SchemaField({
|
||||||
|
physical: new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ initial: "ECRY.ui.physical" }),
|
||||||
|
pnjvalue: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
skilllist: new fields.SchemaField(physicalSkills)
|
||||||
|
}),
|
||||||
|
mental: new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ initial: "ECRY.ui.mental" }),
|
||||||
|
pnjvalue: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
skilllist: new fields.SchemaField(mentalSkills)
|
||||||
|
}),
|
||||||
|
social: new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ initial: "ECRY.ui.social" }),
|
||||||
|
pnjvalue: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
skilllist: new fields.SchemaField(socialSkills)
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Impacts
|
||||||
|
impacts: new fields.SchemaField({
|
||||||
|
physical: new fields.SchemaField(createImpactSchema()),
|
||||||
|
mental: new fields.SchemaField(createImpactSchema()),
|
||||||
|
social: new fields.SchemaField(createImpactSchema())
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Cephaly
|
||||||
|
cephaly: new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ initial: "ECRY.ui.cephaly" }),
|
||||||
|
skilllist: new fields.SchemaField(cephalySkills)
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Internals
|
||||||
|
internals: new fields.SchemaField({
|
||||||
|
confrontbonus: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les spécialisations
|
||||||
|
*/
|
||||||
|
export default class EcrymeSpecializationDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
bonus: new fields.NumberField({ initial: 2, integer: true }),
|
||||||
|
skillkey: new fields.StringField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les traits
|
||||||
|
*/
|
||||||
|
export default class EcrymeTraitDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
traitype: new fields.StringField({ initial: "normal" }),
|
||||||
|
level: new fields.NumberField({ initial: 1, integer: true, min: 1 })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les armes
|
||||||
|
*/
|
||||||
|
export default class EcrymeWeaponDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
weight: new fields.NumberField({ initial: 0, integer: true, min: 0 }),
|
||||||
|
cost: new fields.NumberField({ initial: 0, integer: true, min: 0 }),
|
||||||
|
costunit: new fields.StringField({ initial: "" }),
|
||||||
|
weapontype: new fields.StringField({ initial: "melee", choices: { melee: "Mêlée", ranged: "Distance" } }),
|
||||||
|
effect: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+2167
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "fvtt-ecryme",
|
||||||
|
"private": true,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Ecryme RPG system for Foundry Virtual TableTop",
|
||||||
|
"author": "LeRatierBretonnien",
|
||||||
|
"license": "CC-BY-NC-SA-4.0",
|
||||||
|
"main": "gulpfile.js",
|
||||||
|
"devDependencies": {
|
||||||
|
"gulp": "^5.0.0",
|
||||||
|
"gulp-less": "^5.0.0",
|
||||||
|
"less": "^4.1.3"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "gulp css",
|
||||||
|
"watch": "gulp"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://www.uberwald.me/gitea/uberwald/fvtt-ecryme.git"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
MANIFEST-000205
|
MANIFEST-000395
|
||||||
|
|||||||
+7
-7
@@ -1,7 +1,7 @@
|
|||||||
2025/05/01-23:23:34.950257 7f11177fe6c0 Recovering log #203
|
2026/07/21-23:37:06.398350 7f8f09fec6c0 Recovering log #393
|
||||||
2025/05/01-23:23:34.960390 7f11177fe6c0 Delete type=3 #201
|
2026/07/21-23:37:06.408503 7f8f09fec6c0 Delete type=3 #391
|
||||||
2025/05/01-23:23:34.960497 7f11177fe6c0 Delete type=0 #203
|
2026/07/21-23:37:06.408560 7f8f09fec6c0 Delete type=0 #393
|
||||||
2025/05/01-23:27:45.498796 7f11153ff6c0 Level-0 table #208: started
|
2026/07/21-23:58:26.140301 7f8f097eb6c0 Level-0 table #398: started
|
||||||
2025/05/01-23:27:45.498850 7f11153ff6c0 Level-0 table #208: 0 bytes OK
|
2026/07/21-23:58:26.140328 7f8f097eb6c0 Level-0 table #398: 0 bytes OK
|
||||||
2025/05/01-23:27:45.505411 7f11153ff6c0 Delete type=0 #206
|
2026/07/21-23:58:26.146757 7f8f097eb6c0 Delete type=0 #396
|
||||||
2025/05/01-23:27:45.518830 7f11153ff6c0 Manual compaction at level-0 from '!folders!1GrTlI1xWvaxdKRI' @ 72057594037927935 : 1 .. '!items!zs7krgXhDRndtqbl' @ 0 : 0; will stop at (end)
|
2026/07/21-23:58:26.160256 7f8f097eb6c0 Manual compaction at level-0 from '!folders!1GrTlI1xWvaxdKRI' @ 72057594037927935 : 1 .. '!items!zs7krgXhDRndtqbl' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
2025/05/01-23:18:27.056956 7f1115ffb6c0 Recovering log #199
|
2026/07/21-21:44:20.517858 7f8f0afee6c0 Recovering log #389
|
||||||
2025/05/01-23:18:27.067437 7f1115ffb6c0 Delete type=3 #197
|
2026/07/21-21:44:20.527213 7f8f0afee6c0 Delete type=3 #387
|
||||||
2025/05/01-23:18:27.067539 7f1115ffb6c0 Delete type=0 #199
|
2026/07/21-21:44:20.527291 7f8f0afee6c0 Delete type=0 #389
|
||||||
2025/05/01-23:23:12.722068 7f11153ff6c0 Level-0 table #204: started
|
2026/07/21-22:22:52.642955 7f8f097eb6c0 Level-0 table #394: started
|
||||||
2025/05/01-23:23:12.722089 7f11153ff6c0 Level-0 table #204: 0 bytes OK
|
2026/07/21-22:22:52.642974 7f8f097eb6c0 Level-0 table #394: 0 bytes OK
|
||||||
2025/05/01-23:23:12.728871 7f11153ff6c0 Delete type=0 #202
|
2026/07/21-22:22:52.649267 7f8f097eb6c0 Delete type=0 #392
|
||||||
2025/05/01-23:23:12.744842 7f11153ff6c0 Manual compaction at level-0 from '!folders!1GrTlI1xWvaxdKRI' @ 72057594037927935 : 1 .. '!items!zs7krgXhDRndtqbl' @ 0 : 0; will stop at (end)
|
2026/07/21-22:22:52.662877 7f8f097eb6c0 Manual compaction at level-0 from '!folders!1GrTlI1xWvaxdKRI' @ 72057594037927935 : 1 .. '!items!zs7krgXhDRndtqbl' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
|||||||
MANIFEST-000142
|
MANIFEST-000328
|
||||||
|
|||||||
+8
-8
@@ -1,8 +1,8 @@
|
|||||||
2025/05/01-23:23:35.002627 7f1116ffd6c0 Recovering log #140
|
2026/07/21-23:37:06.449926 7f8f0afee6c0 Recovering log #326
|
||||||
2025/05/01-23:23:35.013325 7f1116ffd6c0 Delete type=3 #138
|
2026/07/21-23:37:06.459731 7f8f0afee6c0 Delete type=3 #324
|
||||||
2025/05/01-23:23:35.013430 7f1116ffd6c0 Delete type=0 #140
|
2026/07/21-23:37:06.459790 7f8f0afee6c0 Delete type=0 #326
|
||||||
2025/05/01-23:27:45.532648 7f11153ff6c0 Level-0 table #145: started
|
2026/07/21-23:58:26.167099 7f8f097eb6c0 Level-0 table #331: started
|
||||||
2025/05/01-23:27:45.532688 7f11153ff6c0 Level-0 table #145: 0 bytes OK
|
2026/07/21-23:58:26.167127 7f8f097eb6c0 Level-0 table #331: 0 bytes OK
|
||||||
2025/05/01-23:27:45.540035 7f11153ff6c0 Delete type=0 #143
|
2026/07/21-23:58:26.173119 7f8f097eb6c0 Delete type=0 #329
|
||||||
2025/05/01-23:27:45.546611 7f11153ff6c0 Manual compaction at level-0 from '!journal!wooTFYjEwh83FwgT' @ 72057594037927935 : 1 .. '!journal.pages!wooTFYjEwh83FwgT.xhc7hqoL8kdW6lrD' @ 0 : 0; will stop at (end)
|
2026/07/21-23:58:26.183592 7f8f097eb6c0 Manual compaction at level-0 from '!journal!wooTFYjEwh83FwgT' @ 72057594037927935 : 1 .. '!journal.pages!wooTFYjEwh83FwgT.xhc7hqoL8kdW6lrD' @ 0 : 0; will stop at (end)
|
||||||
2025/05/01-23:27:45.546647 7f11153ff6c0 Manual compaction at level-1 from '!journal!wooTFYjEwh83FwgT' @ 72057594037927935 : 1 .. '!journal.pages!wooTFYjEwh83FwgT.xhc7hqoL8kdW6lrD' @ 0 : 0; will stop at (end)
|
2026/07/21-23:58:26.190269 7f8f097eb6c0 Manual compaction at level-1 from '!journal!wooTFYjEwh83FwgT' @ 72057594037927935 : 1 .. '!journal.pages!wooTFYjEwh83FwgT.xhc7hqoL8kdW6lrD' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
+8
-8
@@ -1,8 +1,8 @@
|
|||||||
2025/05/01-23:18:27.111839 7f1116ffd6c0 Recovering log #136
|
2026/07/21-21:44:20.567283 7f8f09fec6c0 Recovering log #322
|
||||||
2025/05/01-23:18:27.122280 7f1116ffd6c0 Delete type=3 #134
|
2026/07/21-21:44:20.578221 7f8f09fec6c0 Delete type=3 #320
|
||||||
2025/05/01-23:18:27.122337 7f1116ffd6c0 Delete type=0 #136
|
2026/07/21-21:44:20.578306 7f8f09fec6c0 Delete type=0 #322
|
||||||
2025/05/01-23:23:12.768196 7f11153ff6c0 Level-0 table #141: started
|
2026/07/21-22:22:52.669940 7f8f097eb6c0 Level-0 table #327: started
|
||||||
2025/05/01-23:23:12.768227 7f11153ff6c0 Level-0 table #141: 0 bytes OK
|
2026/07/21-22:22:52.669970 7f8f097eb6c0 Level-0 table #327: 0 bytes OK
|
||||||
2025/05/01-23:23:12.774547 7f11153ff6c0 Delete type=0 #139
|
2026/07/21-22:22:52.676090 7f8f097eb6c0 Delete type=0 #325
|
||||||
2025/05/01-23:23:12.774689 7f11153ff6c0 Manual compaction at level-0 from '!journal!wooTFYjEwh83FwgT' @ 72057594037927935 : 1 .. '!journal.pages!wooTFYjEwh83FwgT.xhc7hqoL8kdW6lrD' @ 0 : 0; will stop at (end)
|
2026/07/21-22:22:52.696989 7f8f097eb6c0 Manual compaction at level-0 from '!journal!wooTFYjEwh83FwgT' @ 72057594037927935 : 1 .. '!journal.pages!wooTFYjEwh83FwgT.xhc7hqoL8kdW6lrD' @ 0 : 0; will stop at (end)
|
||||||
2025/05/01-23:23:12.774707 7f11153ff6c0 Manual compaction at level-1 from '!journal!wooTFYjEwh83FwgT' @ 72057594037927935 : 1 .. '!journal.pages!wooTFYjEwh83FwgT.xhc7hqoL8kdW6lrD' @ 0 : 0; will stop at (end)
|
2026/07/21-22:22:52.707515 7f8f097eb6c0 Manual compaction at level-1 from '!journal!wooTFYjEwh83FwgT' @ 72057594037927935 : 1 .. '!journal.pages!wooTFYjEwh83FwgT.xhc7hqoL8kdW6lrD' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000205
|
MANIFEST-000393
|
||||||
|
|||||||
+7
-7
@@ -1,7 +1,7 @@
|
|||||||
2025/05/01-23:23:34.989243 7f11177fe6c0 Recovering log #203
|
2026/07/21-23:37:06.438745 7f8f0a7ed6c0 Recovering log #391
|
||||||
2025/05/01-23:23:34.999290 7f11177fe6c0 Delete type=3 #201
|
2026/07/21-23:37:06.448044 7f8f0a7ed6c0 Delete type=3 #389
|
||||||
2025/05/01-23:23:34.999338 7f11177fe6c0 Delete type=0 #203
|
2026/07/21-23:37:06.448110 7f8f0a7ed6c0 Delete type=0 #391
|
||||||
2025/05/01-23:27:45.505528 7f11153ff6c0 Level-0 table #208: started
|
2026/07/21-23:58:26.160548 7f8f097eb6c0 Level-0 table #396: started
|
||||||
2025/05/01-23:27:45.505551 7f11153ff6c0 Level-0 table #208: 0 bytes OK
|
2026/07/21-23:58:26.160599 7f8f097eb6c0 Level-0 table #396: 0 bytes OK
|
||||||
2025/05/01-23:27:45.512071 7f11153ff6c0 Delete type=0 #206
|
2026/07/21-23:58:26.166936 7f8f097eb6c0 Delete type=0 #394
|
||||||
2025/05/01-23:27:45.518845 7f11153ff6c0 Manual compaction at level-0 from '!items!13IYF6BPUTivFZzB' @ 72057594037927935 : 1 .. '!items!oSutlbe9wyBZccmf' @ 0 : 0; will stop at (end)
|
2026/07/21-23:58:26.183563 7f8f097eb6c0 Manual compaction at level-0 from '!items!13IYF6BPUTivFZzB' @ 72057594037927935 : 1 .. '!items!oSutlbe9wyBZccmf' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
2025/05/01-23:18:27.099266 7f1115ffb6c0 Recovering log #199
|
2026/07/21-21:44:20.555084 7f8f0b7ef6c0 Recovering log #387
|
||||||
2025/05/01-23:18:27.109501 7f1115ffb6c0 Delete type=3 #197
|
2026/07/21-21:44:20.564635 7f8f0b7ef6c0 Delete type=3 #385
|
||||||
2025/05/01-23:18:27.109566 7f1115ffb6c0 Delete type=0 #199
|
2026/07/21-21:44:20.564707 7f8f0b7ef6c0 Delete type=0 #387
|
||||||
2025/05/01-23:23:12.745080 7f11153ff6c0 Level-0 table #204: started
|
2026/07/21-22:22:52.662972 7f8f097eb6c0 Level-0 table #392: started
|
||||||
2025/05/01-23:23:12.745126 7f11153ff6c0 Level-0 table #204: 0 bytes OK
|
2026/07/21-22:22:52.663005 7f8f097eb6c0 Level-0 table #392: 0 bytes OK
|
||||||
2025/05/01-23:23:12.751818 7f11153ff6c0 Delete type=0 #202
|
2026/07/21-22:22:52.669773 7f8f097eb6c0 Delete type=0 #390
|
||||||
2025/05/01-23:23:12.774663 7f11153ff6c0 Manual compaction at level-0 from '!items!13IYF6BPUTivFZzB' @ 72057594037927935 : 1 .. '!items!oSutlbe9wyBZccmf' @ 0 : 0; will stop at (end)
|
2026/07/21-22:22:52.687465 7f8f097eb6c0 Manual compaction at level-0 from '!items!13IYF6BPUTivFZzB' @ 72057594037927935 : 1 .. '!items!oSutlbe9wyBZccmf' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000091
|
MANIFEST-000281
|
||||||
|
|||||||
+8
-8
@@ -1,8 +1,8 @@
|
|||||||
2025/05/01-23:23:34.977246 7f1116ffd6c0 Recovering log #88
|
2026/07/21-23:37:06.424077 7f8f0b7ef6c0 Recovering log #278
|
||||||
2025/05/01-23:23:34.986582 7f1116ffd6c0 Delete type=3 #86
|
2026/07/21-23:37:06.434900 7f8f0b7ef6c0 Delete type=3 #276
|
||||||
2025/05/01-23:23:34.986642 7f1116ffd6c0 Delete type=0 #88
|
2026/07/21-23:37:06.434963 7f8f0b7ef6c0 Delete type=0 #278
|
||||||
2025/05/01-23:27:45.512228 7f11153ff6c0 Level-0 table #94: started
|
2026/07/21-23:58:26.153514 7f8f097eb6c0 Level-0 table #284: started
|
||||||
2025/05/01-23:27:45.512262 7f11153ff6c0 Level-0 table #94: 0 bytes OK
|
2026/07/21-23:58:26.153548 7f8f097eb6c0 Level-0 table #284: 0 bytes OK
|
||||||
2025/05/01-23:27:45.518665 7f11153ff6c0 Delete type=0 #92
|
2026/07/21-23:58:26.160040 7f8f097eb6c0 Delete type=0 #282
|
||||||
2025/05/01-23:27:45.518856 7f11153ff6c0 Manual compaction at level-0 from '!scenes!DDibQQLAvyIq9y09' @ 72057594037927935 : 1 .. '!scenes!zvY1RwBhTfwdZIBa' @ 0 : 0; will stop at (end)
|
2026/07/21-23:58:26.167084 7f8f097eb6c0 Manual compaction at level-0 from '!scenes!DDibQQLAvyIq9y09' @ 72057594037927935 : 1 .. '!scenes.levels!zvY1RwBhTfwdZIBa.defaultLevel0000' @ 0 : 0; will stop at (end)
|
||||||
2025/05/01-23:27:45.518892 7f11153ff6c0 Manual compaction at level-1 from '!scenes!DDibQQLAvyIq9y09' @ 72057594037927935 : 1 .. '!scenes!zvY1RwBhTfwdZIBa' @ 0 : 0; will stop at (end)
|
2026/07/21-23:58:26.183582 7f8f097eb6c0 Manual compaction at level-1 from '!scenes!DDibQQLAvyIq9y09' @ 72057594037927935 : 1 .. '!scenes.levels!zvY1RwBhTfwdZIBa.defaultLevel0000' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
+15
-15
@@ -1,15 +1,15 @@
|
|||||||
2025/05/01-23:18:27.084819 7f1116ffd6c0 Recovering log #82
|
2026/07/21-21:44:20.541841 7f8f0afee6c0 Recovering log #274
|
||||||
2025/05/01-23:18:27.095491 7f1116ffd6c0 Delete type=3 #80
|
2026/07/21-21:44:20.552114 7f8f0afee6c0 Delete type=3 #272
|
||||||
2025/05/01-23:18:27.095539 7f1116ffd6c0 Delete type=0 #82
|
2026/07/21-21:44:20.552164 7f8f0afee6c0 Delete type=0 #274
|
||||||
2025/05/01-23:23:12.735355 7f11153ff6c0 Level-0 table #89: started
|
2026/07/21-22:22:52.649444 7f8f097eb6c0 Level-0 table #279: started
|
||||||
2025/05/01-23:23:12.738432 7f11153ff6c0 Level-0 table #89: 1551 bytes OK
|
2026/07/21-22:22:52.653578 7f8f097eb6c0 Level-0 table #279: 1805 bytes OK
|
||||||
2025/05/01-23:23:12.744606 7f11153ff6c0 Delete type=0 #87
|
2026/07/21-22:22:52.662677 7f8f097eb6c0 Delete type=0 #277
|
||||||
2025/05/01-23:23:12.744906 7f11153ff6c0 Manual compaction at level-0 from '!scenes!DDibQQLAvyIq9y09' @ 72057594037927935 : 1 .. '!scenes!zvY1RwBhTfwdZIBa' @ 0 : 0; will stop at (end)
|
2026/07/21-22:22:52.669921 7f8f097eb6c0 Manual compaction at level-0 from '!scenes!DDibQQLAvyIq9y09' @ 72057594037927935 : 1 .. '!scenes.levels!zvY1RwBhTfwdZIBa.defaultLevel0000' @ 0 : 0; will stop at (end)
|
||||||
2025/05/01-23:23:12.751899 7f11153ff6c0 Manual compaction at level-1 from '!scenes!DDibQQLAvyIq9y09' @ 72057594037927935 : 1 .. '!scenes!zvY1RwBhTfwdZIBa' @ 0 : 0; will stop at '!scenes!zvY1RwBhTfwdZIBa' @ 18 : 1
|
2026/07/21-22:22:52.687503 7f8f097eb6c0 Manual compaction at level-1 from '!scenes!DDibQQLAvyIq9y09' @ 72057594037927935 : 1 .. '!scenes.levels!zvY1RwBhTfwdZIBa.defaultLevel0000' @ 0 : 0; will stop at '!scenes.levels!zvY1RwBhTfwdZIBa.defaultLevel0000' @ 40 : 1
|
||||||
2025/05/01-23:23:12.751905 7f11153ff6c0 Compacting 1@1 + 1@2 files
|
2026/07/21-22:22:52.687516 7f8f097eb6c0 Compacting 1@1 + 1@2 files
|
||||||
2025/05/01-23:23:12.755259 7f11153ff6c0 Generated table #90@1: 2 keys, 1586 bytes
|
2026/07/21-22:22:52.690551 7f8f097eb6c0 Generated table #280@1: 4 keys, 1805 bytes
|
||||||
2025/05/01-23:23:12.755289 7f11153ff6c0 Compacted 1@1 + 1@2 files => 1586 bytes
|
2026/07/21-22:22:52.690566 7f8f097eb6c0 Compacted 1@1 + 1@2 files => 1805 bytes
|
||||||
2025/05/01-23:23:12.761436 7f11153ff6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
|
2026/07/21-22:22:52.696271 7f8f097eb6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
|
||||||
2025/05/01-23:23:12.761603 7f11153ff6c0 Delete type=2 #85
|
2026/07/21-22:22:52.696454 7f8f097eb6c0 Delete type=2 #247
|
||||||
2025/05/01-23:23:12.761813 7f11153ff6c0 Delete type=2 #89
|
2026/07/21-22:22:52.696927 7f8f097eb6c0 Delete type=2 #279
|
||||||
2025/05/01-23:23:12.774673 7f11153ff6c0 Manual compaction at level-1 from '!scenes!zvY1RwBhTfwdZIBa' @ 18 : 1 .. '!scenes!zvY1RwBhTfwdZIBa' @ 0 : 0; will stop at (end)
|
2026/07/21-22:22:52.707490 7f8f097eb6c0 Manual compaction at level-1 from '!scenes.levels!zvY1RwBhTfwdZIBa.defaultLevel0000' @ 40 : 1 .. '!scenes.levels!zvY1RwBhTfwdZIBa.defaultLevel0000' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000205
|
MANIFEST-000397
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
2025/05/01-23:23:34.938221 7f1116ffd6c0 Recovering log #203
|
2026/07/21-23:39:43.018556 7f86d23fe6c0 Recovering log #396
|
||||||
2025/05/01-23:23:34.947805 7f1116ffd6c0 Delete type=3 #201
|
2026/07/21-23:39:43.069296 7f86d23fe6c0 Delete type=0 #396
|
||||||
2025/05/01-23:23:34.947853 7f1116ffd6c0 Delete type=0 #203
|
2026/07/21-23:39:43.069385 7f86d23fe6c0 Delete type=3 #395
|
||||||
2025/05/01-23:27:45.491261 7f11153ff6c0 Level-0 table #208: started
|
|
||||||
2025/05/01-23:27:45.491305 7f11153ff6c0 Level-0 table #208: 0 bytes OK
|
|
||||||
2025/05/01-23:27:45.498558 7f11153ff6c0 Delete type=0 #206
|
|
||||||
2025/05/01-23:27:45.518813 7f11153ff6c0 Manual compaction at level-0 from '!folders!00Hn2nNarlL7b0DR' @ 72057594037927935 : 1 .. '!items!yozTUjNuc2rEGjFK' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
2025/05/01-23:18:27.043700 7f11167fc6c0 Recovering log #199
|
2026/07/21-23:39:38.357102 7ff068bfd6c0 Recovering log #394
|
||||||
2025/05/01-23:18:27.054373 7f11167fc6c0 Delete type=3 #197
|
2026/07/21-23:39:38.412635 7ff068bfd6c0 Delete type=0 #394
|
||||||
2025/05/01-23:18:27.054431 7f11167fc6c0 Delete type=0 #199
|
2026/07/21-23:39:38.412727 7ff068bfd6c0 Delete type=3 #393
|
||||||
2025/05/01-23:23:12.728954 7f11153ff6c0 Level-0 table #204: started
|
|
||||||
2025/05/01-23:23:12.728976 7f11153ff6c0 Level-0 table #204: 0 bytes OK
|
|
||||||
2025/05/01-23:23:12.735241 7f11153ff6c0 Delete type=0 #202
|
|
||||||
2025/05/01-23:23:12.744865 7f11153ff6c0 Manual compaction at level-0 from '!folders!00Hn2nNarlL7b0DR' @ 72057594037927935 : 1 .. '!items!yozTUjNuc2rEGjFK' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
MANIFEST-000002
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
2026/05/06-14:41:23.043596 7f0aceffd6c0 Delete type=3 #1
|
||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000205
|
MANIFEST-000395
|
||||||
|
|||||||
+7
-7
@@ -1,7 +1,7 @@
|
|||||||
2025/05/01-23:23:34.963229 7f1115ffb6c0 Recovering log #203
|
2026/07/21-23:37:06.411000 7f8f0a7ed6c0 Recovering log #393
|
||||||
2025/05/01-23:23:34.973922 7f1115ffb6c0 Delete type=3 #201
|
2026/07/21-23:37:06.421521 7f8f0a7ed6c0 Delete type=3 #391
|
||||||
2025/05/01-23:23:34.974025 7f1115ffb6c0 Delete type=0 #203
|
2026/07/21-23:37:06.421589 7f8f0a7ed6c0 Delete type=0 #393
|
||||||
2025/05/01-23:27:45.518950 7f11153ff6c0 Level-0 table #208: started
|
2026/07/21-23:58:26.146891 7f8f097eb6c0 Level-0 table #398: started
|
||||||
2025/05/01-23:27:45.518982 7f11153ff6c0 Level-0 table #208: 0 bytes OK
|
2026/07/21-23:58:26.146920 7f8f097eb6c0 Level-0 table #398: 0 bytes OK
|
||||||
2025/05/01-23:27:45.525989 7f11153ff6c0 Delete type=0 #206
|
2026/07/21-23:58:26.153371 7f8f097eb6c0 Delete type=0 #396
|
||||||
2025/05/01-23:27:45.546586 7f11153ff6c0 Manual compaction at level-0 from '!folders!DiwHbtGAkTYxtshX' @ 72057594037927935 : 1 .. '!items!zgNI2haxhBxBDBdl' @ 0 : 0; will stop at (end)
|
2026/07/21-23:58:26.160268 7f8f097eb6c0 Manual compaction at level-0 from '!folders!DiwHbtGAkTYxtshX' @ 72057594037927935 : 1 .. '!items!zgNI2haxhBxBDBdl' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
2025/05/01-23:18:27.070994 7f11167fc6c0 Recovering log #199
|
2026/07/21-21:44:20.529547 7f8f09fec6c0 Recovering log #389
|
||||||
2025/05/01-23:18:27.081264 7f11167fc6c0 Delete type=3 #197
|
2026/07/21-21:44:20.539682 7f8f09fec6c0 Delete type=3 #387
|
||||||
2025/05/01-23:18:27.081417 7f11167fc6c0 Delete type=0 #199
|
2026/07/21-21:44:20.539761 7f8f09fec6c0 Delete type=0 #389
|
||||||
2025/05/01-23:23:12.715522 7f11153ff6c0 Level-0 table #204: started
|
2026/07/21-22:22:52.637033 7f8f097eb6c0 Level-0 table #394: started
|
||||||
2025/05/01-23:23:12.715566 7f11153ff6c0 Level-0 table #204: 0 bytes OK
|
2026/07/21-22:22:52.637050 7f8f097eb6c0 Level-0 table #394: 0 bytes OK
|
||||||
2025/05/01-23:23:12.721964 7f11153ff6c0 Delete type=0 #202
|
2026/07/21-22:22:52.642866 7f8f097eb6c0 Delete type=0 #392
|
||||||
2025/05/01-23:23:12.744818 7f11153ff6c0 Manual compaction at level-0 from '!folders!DiwHbtGAkTYxtshX' @ 72057594037927935 : 1 .. '!items!zgNI2haxhBxBDBdl' @ 0 : 0; will stop at (end)
|
2026/07/21-22:22:52.662863 7f8f097eb6c0 Manual compaction at level-0 from '!folders!DiwHbtGAkTYxtshX' @ 72057594037927935 : 1 .. '!items!zgNI2haxhBxBDBdl' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
MANIFEST-000002
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
2026/05/06-14:41:23.014318 7f0acffff6c0 Delete type=3 #1
|
||||||
Binary file not shown.
+178
-31
@@ -46,13 +46,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fonts */
|
/* Fonts */
|
||||||
.sheet header.sheet-header h1 input, .window-app .window-header, #actors .directory-list, #navigation #scene-list .scene.nav-item {
|
.sheet header.sheet-header h1 input,
|
||||||
|
.window-app .window-header,
|
||||||
|
#actors .directory-list,
|
||||||
|
#navigation #scene-list .scene.nav-item {
|
||||||
font-size: 1.0rem;
|
font-size: 1.0rem;
|
||||||
} /* For title, sidebar character and scene */
|
}
|
||||||
|
|
||||||
|
/* For title, sidebar character and scene */
|
||||||
.sheet nav.sheet-tabs {
|
.sheet nav.sheet-tabs {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
} /* For nav and title */
|
}
|
||||||
.window-app input, .fvtt-ecryme .item-form, .sheet header.sheet-header .flex-group-center.flex-compteurs, .sheet header.sheet-header .flex-group-center.flex-fatigue, select, button, .item-checkbox, #sidebar, #players, #navigation #nav-toggle {
|
|
||||||
|
/* For nav and title */
|
||||||
|
.window-app input,
|
||||||
|
.fvtt-ecryme .item-form,
|
||||||
|
.sheet header.sheet-header .flex-group-center.flex-compteurs,
|
||||||
|
.sheet header.sheet-header .flex-group-center.flex-fatigue,
|
||||||
|
select,
|
||||||
|
button,
|
||||||
|
.item-checkbox,
|
||||||
|
#sidebar,
|
||||||
|
#players,
|
||||||
|
#navigation #nav-toggle {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,15 +80,19 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.strong-text {
|
.strong-text {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs .item.active, .blessures-list li ul li:first-child:hover, a:hover {
|
.tabs .item.active,
|
||||||
|
.blessures-list li ul li:first-child:hover,
|
||||||
|
a:hover {
|
||||||
text-shadow: 1px 0px 0px #ff6600;
|
text-shadow: 1px 0px 0px #ff6600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rollable:hover, .rollable:focus {
|
.rollable:hover,
|
||||||
|
.rollable:focus {
|
||||||
color: #000;
|
color: #000;
|
||||||
text-shadow: 0 0 10px red;
|
text-shadow: 0 0 10px red;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -86,12 +106,17 @@ input:hover {
|
|||||||
input:disabled {
|
input:disabled {
|
||||||
color: #1c2058;
|
color: #1c2058;
|
||||||
}
|
}
|
||||||
|
|
||||||
select:disabled {
|
select:disabled {
|
||||||
color: #1c2058;
|
color: #1c2058;
|
||||||
}
|
}
|
||||||
table {border: 1px solid #7a7971;}
|
|
||||||
|
|
||||||
.grid, .grid-2col {
|
table {
|
||||||
|
border: 1px solid #7a7971;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid,
|
||||||
|
.grid-2col {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-column: span 2 / span 2;
|
grid-column: span 2 / span 2;
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
@@ -235,6 +260,7 @@ table {border: 1px solid #7a7971;}
|
|||||||
object-position: 50% 0;
|
object-position: 50% 0;
|
||||||
border-width: 0px;
|
border-width: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-img-container {
|
.profile-img-container {
|
||||||
margin-right: 0.2rem;
|
margin-right: 0.2rem;
|
||||||
max-width: 140px;
|
max-width: 140px;
|
||||||
@@ -407,7 +433,8 @@ li.folder > .folder-header h3 {
|
|||||||
/*background: #494e6b;*/
|
/*background: #494e6b;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"], select[type="text"] {
|
input[type="text"],
|
||||||
|
select[type="text"] {
|
||||||
background: white;
|
background: white;
|
||||||
color: #494e6b;
|
color: #494e6b;
|
||||||
}
|
}
|
||||||
@@ -416,14 +443,22 @@ select {
|
|||||||
background: white;
|
background: white;
|
||||||
color: #494e6b;
|
color: #494e6b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* background: #011d33 url("../images/ui/fond1.webp") repeat left top;*/
|
/* background: #011d33 url("../images/ui/fond1.webp") repeat left top;*/
|
||||||
/*color: rgba(168, 139, 139, 0.5);*/
|
/*color: rgba(168, 139, 139, 0.5);*/
|
||||||
.window-app.sheet .window-content .sheet-header select[type="text"], .window-app.sheet .window-content .sheet-header input[type="text"], .window-app.sheet .window-content .sheet-header input[type="number"], .window-app.sheet .window-content .sheet-body input[type="text"], .window-app.sheet .window-content .sheet-body input[type="number"], .window-app.sheet .window-content .sheet-body select[type="text"] {
|
.window-app.sheet .window-content .sheet-header select[type="text"],
|
||||||
|
.window-app.sheet .window-content .sheet-header input[type="text"],
|
||||||
|
.window-app.sheet .window-content .sheet-header input[type="number"],
|
||||||
|
.window-app.sheet .window-content .sheet-body input[type="text"],
|
||||||
|
.window-app.sheet .window-content .sheet-body input[type="number"],
|
||||||
|
.window-app.sheet .window-content .sheet-body select[type="text"] {
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
/*color: #494e6b;*/
|
/*color: #494e6b;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-app.sheet .window-content .sheet-header input[type="password"], .window-app.sheet .window-content .sheet-header input[type="date"], .window-app.sheet .window-content .sheet-header input[type="time"] {
|
.window-app.sheet .window-content .sheet-header input[type="password"],
|
||||||
|
.window-app.sheet .window-content .sheet-header input[type="date"],
|
||||||
|
.window-app.sheet .window-content .sheet-header input[type="time"] {
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
background: url("../images/ui/fond_carnet_01.webp");
|
background: url("../images/ui/fond_carnet_01.webp");
|
||||||
border: 1 none;
|
border: 1 none;
|
||||||
@@ -431,7 +466,9 @@ select {
|
|||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-app.sheet .window-content .sheet-body input[type="password"], .window-app.sheet .window-content .sheet-body input[type="date"], .window-app.sheet .window-content .sheet-body input[type="time"] {
|
.window-app.sheet .window-content .sheet-body input[type="password"],
|
||||||
|
.window-app.sheet .window-content .sheet-body input[type="date"],
|
||||||
|
.window-app.sheet .window-content .sheet-body input[type="time"] {
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
background: url("../images/ui/fond_carnet_01.webp");
|
background: url("../images/ui/fond_carnet_01.webp");
|
||||||
border: 1 none;
|
border: 1 none;
|
||||||
@@ -439,7 +476,8 @@ select {
|
|||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-app.sheet .window-content .sheet-body select, .window-app.sheet .window-content .sheet-header select {
|
.window-app.sheet .window-content .sheet-body select,
|
||||||
|
.window-app.sheet .window-content .sheet-header select {
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1 none;
|
border: 1 none;
|
||||||
@@ -447,7 +485,8 @@ select {
|
|||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-app .window-content, .window-app.sheet .window-content .sheet-body{
|
.window-app .window-content,
|
||||||
|
.window-app.sheet .window-content .sheet-body {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
/*background: url("../images/ui/pc_sheet_bg.webp") repeat left top;*/
|
/*background: url("../images/ui/pc_sheet_bg.webp") repeat left top;*/
|
||||||
background: url("../images/ui/fond_carnet_01.webp");
|
background: url("../images/ui/fond_carnet_01.webp");
|
||||||
@@ -456,7 +495,9 @@ select {
|
|||||||
|
|
||||||
/* background: rgba(245,245,240,0.6) url("../images/ui/sheet_background.webp") left top;*/
|
/* background: rgba(245,245,240,0.6) url("../images/ui/sheet_background.webp") left top;*/
|
||||||
|
|
||||||
section.sheet-body{padding: 0.25rem 0.5rem;}
|
section.sheet-body {
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.sheet header.sheet-header .profile-img {
|
.sheet header.sheet-header .profile-img {
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
@@ -508,8 +549,13 @@ section.sheet-body:after {
|
|||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sheet header.sheet-header .flex-compteurs {text-align: right;}
|
.sheet header.sheet-header .flex-compteurs {
|
||||||
.sheet header.sheet-header .resource-content {width: 2rem;}
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet header.sheet-header .resource-content {
|
||||||
|
width: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.select-diff {
|
.select-diff {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -524,7 +570,8 @@ section.sheet-body:after {
|
|||||||
padding: 0.25rem;
|
padding: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-app.sheet .window-content .carac-value, .window-app.sheet .window-content .competence-xp {
|
.window-app.sheet .window-content .carac-value,
|
||||||
|
.window-app.sheet .window-content .competence-xp {
|
||||||
margin: 0.05rem;
|
margin: 0.05rem;
|
||||||
flex-basis: 3rem;
|
flex-basis: 3rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -535,15 +582,21 @@ section.sheet-body:after {
|
|||||||
|
|
||||||
/* ======================================== */
|
/* ======================================== */
|
||||||
|
|
||||||
h1, h2, h3, h4 {
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4 {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul, ol {
|
ul,
|
||||||
|
ol {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
ul, li {
|
|
||||||
|
ul,
|
||||||
|
li {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,6 +604,7 @@ ul, li {
|
|||||||
margin: 0.010rem;
|
margin: 0.010rem;
|
||||||
padding: 0.25rem;
|
padding: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-fields li {
|
.header-fields li {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -559,9 +613,11 @@ ul, li {
|
|||||||
.alterne-list>.list-item:hover {
|
.alterne-list>.list-item:hover {
|
||||||
background: rgba(100, 100, 50, 0.25);
|
background: rgba(100, 100, 50, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.alterne-list>.list-item:nth-child(even) {
|
.alterne-list>.list-item:nth-child(even) {
|
||||||
background: rgba(80, 60, 0, 0.10);
|
background: rgba(80, 60, 0, 0.10);
|
||||||
}
|
}
|
||||||
|
|
||||||
.alterne-list>.list-item:nth-child(odd) {
|
.alterne-list>.list-item:nth-child(odd) {
|
||||||
background: rgb(160, 130, 100, 0.05);
|
background: rgb(160, 130, 100, 0.05);
|
||||||
}
|
}
|
||||||
@@ -584,36 +640,45 @@ ul, li {
|
|||||||
display: flex !important;
|
display: flex !important;
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item-shadow {
|
.list-item-shadow {
|
||||||
background: rgba(87, 60, 32, 0.35);
|
background: rgba(87, 60, 32, 0.35);
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item-shadow2 {
|
.list-item-shadow2 {
|
||||||
background: rgba(87, 60, 32, 0.25);
|
background: rgba(87, 60, 32, 0.25);
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-display-show {
|
.item-display-show {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-display-hide {
|
.item-display-hide {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-quantite {
|
.item-quantite {
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item-margin1 {
|
.list-item-margin1 {
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item-margin2 {
|
.list-item-margin2 {
|
||||||
margin-left: 2rem;
|
margin-left: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item-margin3 {
|
.list-item-margin3 {
|
||||||
margin-left: 3rem;
|
margin-left: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item-margin4 {
|
.list-item-margin4 {
|
||||||
margin-left: 4rem;
|
margin-left: 4rem;
|
||||||
}
|
}
|
||||||
@@ -626,6 +691,7 @@ ul, li {
|
|||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
margin-right: 0.25rem;
|
margin-right: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.competence-column {
|
.competence-column {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
@@ -633,6 +699,7 @@ ul, li {
|
|||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
flex-basis: 1;
|
flex-basis: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.competence-header {
|
.competence-header {
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
@@ -644,16 +711,20 @@ ul, li {
|
|||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-header-label {
|
.status-header-label {
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.roll-dialog-label {
|
.roll-dialog-label {
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
min-width: 96px;
|
min-width: 96px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.short-label {
|
.short-label {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.keyword-label {
|
.keyword-label {
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
@@ -678,6 +749,7 @@ ul, li {
|
|||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sante-value,
|
.sante-value,
|
||||||
.competence-value {
|
.competence-value {
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
@@ -685,26 +757,32 @@ ul, li {
|
|||||||
margin-right: 0.25rem;
|
margin-right: 0.25rem;
|
||||||
margin-left: 0.25rem;
|
margin-left: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.description-value {
|
.description-value {
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
flex-basis: 4rem;
|
flex-basis: 4rem;
|
||||||
margin-right: 0.25rem;
|
margin-right: 0.25rem;
|
||||||
margin-left: 0.25rem;
|
margin-left: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.small-label {
|
.small-label {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.padd-right {
|
.padd-right {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.padd-left {
|
.padd-left {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stack-left {
|
.stack-left {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.packed-left {
|
.packed-left {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
@@ -730,6 +808,7 @@ ul, li {
|
|||||||
flex: 0 !important;
|
flex: 0 !important;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tokenhudext.left {
|
.tokenhudext.left {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -737,6 +816,7 @@ ul, li {
|
|||||||
top: 2.75rem;
|
top: 2.75rem;
|
||||||
right: 4rem;
|
right: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tokenhudext.right {
|
.tokenhudext.right {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -744,6 +824,7 @@ ul, li {
|
|||||||
top: 2.75rem;
|
top: 2.75rem;
|
||||||
left: 4rem;
|
left: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-icon.tokenhudicon {
|
.control-icon.tokenhudicon {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
@@ -753,12 +834,15 @@ ul, li {
|
|||||||
line-height: 1rem;
|
line-height: 1rem;
|
||||||
margin: 0.25rem;
|
margin: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-icon.tokenhudicon.right {
|
.control-icon.tokenhudicon.right {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#token-hud .status-effects.active {
|
#token-hud .status-effects.active {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.token-sheet .window-content .flexcol .sheet-tabs {
|
.token-sheet .window-content .flexcol .sheet-tabs {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
}
|
}
|
||||||
@@ -782,6 +866,7 @@ ul, li {
|
|||||||
.skill-label {
|
.skill-label {
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.skill-good-checkbox {
|
.skill-good-checkbox {
|
||||||
max-height: 10px;
|
max-height: 10px;
|
||||||
max-width: 10px;
|
max-width: 10px;
|
||||||
@@ -809,7 +894,8 @@ ul, li {
|
|||||||
height: 470px !important;
|
height: 470px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar-tabs > .collapsed, #chat-controls .chat-control-icon {
|
#sidebar-tabs>.collapsed,
|
||||||
|
#chat-controls .chat-control-icon {
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.75);
|
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.75);
|
||||||
}
|
}
|
||||||
@@ -824,6 +910,7 @@ ul, li {
|
|||||||
background: rgba(0, 0, 0, 0.05);
|
background: rgba(0, 0, 0, 0.05);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-message-header {
|
.chat-message-header {
|
||||||
background: rgba(220, 220, 210, 0.5);
|
background: rgba(220, 220, 210, 0.5);
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
@@ -834,9 +921,15 @@ ul, li {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-message .message-header .flavor-text, .chat-message .message-header .whisper-to {
|
.message-chat-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message .message-header .flavor-text,
|
||||||
|
.chat-message .message-header .whisper-to {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-result-text,
|
.chat-result-text,
|
||||||
.chat-actor-name {
|
.chat-actor-name {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -844,12 +937,15 @@ ul, li {
|
|||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-result-success {
|
.chat-result-success {
|
||||||
color: darkgreen;
|
color: darkgreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-result-failure {
|
.chat-result-failure {
|
||||||
color: darkred;
|
color: darkred;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-img {
|
.chat-img {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
@@ -927,6 +1023,7 @@ ul, li {
|
|||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.small-ability-icon {
|
.small-ability-icon {
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 2px 2px 2px 2px;
|
padding: 2px 2px 2px 2px;
|
||||||
@@ -935,6 +1032,7 @@ ul, li {
|
|||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combat-icon {
|
.combat-icon {
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 2px 2px 2px 2px;
|
padding: 2px 2px 2px 2px;
|
||||||
@@ -969,7 +1067,8 @@ ul, li {
|
|||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
/* Control, Tool, hotbar & navigation */
|
/* Control, Tool, hotbar & navigation */
|
||||||
|
|
||||||
#controls .scene-control, #controls .control-tool {
|
#controls .scene-control,
|
||||||
|
#controls .control-tool {
|
||||||
box-shadow: 0 0 3px #000;
|
box-shadow: 0 0 3px #000;
|
||||||
margin: 0 0 8px;
|
margin: 0 0 8px;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
@@ -980,7 +1079,10 @@ ul, li {
|
|||||||
border-image-outset: 0px;
|
border-image-outset: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#controls .scene-control.active, #controls .control-tool.active, #controls .scene-control:hover, #controls .control-tool:hover {
|
#controls .scene-control.active,
|
||||||
|
#controls .control-tool.active,
|
||||||
|
#controls .scene-control:hover,
|
||||||
|
#controls .control-tool:hover {
|
||||||
background: rgba(72, 46, 28, 1);
|
background: rgba(72, 46, 28, 1);
|
||||||
background-origin: padding-box;
|
background-origin: padding-box;
|
||||||
border-image: url(img/ui/footer-button.png) 10 repeat;
|
border-image: url(img/ui/footer-button.png) 10 repeat;
|
||||||
@@ -1026,7 +1128,8 @@ ul, li {
|
|||||||
border-image-outset: 0px;
|
border-image-outset: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#navigation #scene-list .scene.view, #navigation #scene-list .scene.context {
|
#navigation #scene-list .scene.view,
|
||||||
|
#navigation #scene-list .scene.context {
|
||||||
background: rgba(72, 46, 28, 1);
|
background: rgba(72, 46, 28, 1);
|
||||||
background-origin: padding-box;
|
background-origin: padding-box;
|
||||||
border-image: url(img/ui/footer-button.png) 10 repeat;
|
border-image: url(img/ui/footer-button.png) 10 repeat;
|
||||||
@@ -1071,7 +1174,8 @@ ul, li {
|
|||||||
|
|
||||||
|
|
||||||
.tooltip-nobottom {
|
.tooltip-nobottom {
|
||||||
border-bottom: unset; /* If you want dots under the hoverable text */
|
border-bottom: unset;
|
||||||
|
/* If you want dots under the hoverable text */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show the tooltip text when you mouse over the tooltip container */
|
/* Show the tooltip text when you mouse over the tooltip container */
|
||||||
@@ -1101,6 +1205,7 @@ ul, li {
|
|||||||
background: linear-gradient(to bottom, #800000 5%, #3e0101 100%);
|
background: linear-gradient(to bottom, #800000 5%, #3e0101 100%);
|
||||||
background-color: red;
|
background-color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-card-button:active {
|
.chat-card-button:active {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
@@ -1146,14 +1251,14 @@ ul, li {
|
|||||||
|
|
||||||
|
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
#pause
|
#pause {
|
||||||
{
|
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
#pause > h3
|
|
||||||
{
|
#pause>h3 {
|
||||||
color: #CCC
|
color: #CCC
|
||||||
}
|
}
|
||||||
|
|
||||||
#pause>img {
|
#pause>img {
|
||||||
content: url(../images/ui/ecryme_logo_small_01.webp);
|
content: url(../images/ui/ecryme_logo_small_01.webp);
|
||||||
height: 200px;
|
height: 200px;
|
||||||
@@ -1184,23 +1289,28 @@ ul, li {
|
|||||||
.status-small-label {
|
.status-small-label {
|
||||||
font-size: 0.65rem;
|
font-size: 0.65rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-grow {
|
.no-grow {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 32px;
|
max-width: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-col-name {
|
.status-col-name {
|
||||||
max-width: 72px;
|
max-width: 72px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img-no-border {
|
.img-no-border {
|
||||||
max-width: 48px;
|
max-width: 48px;
|
||||||
max-height: 48px;
|
max-height: 48px;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.items-title-bg {
|
.items-title-bg {
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.impact-box {
|
.impact-box {
|
||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
border-color: #000000;
|
border-color: #000000;
|
||||||
@@ -1209,6 +1319,7 @@ ul, li {
|
|||||||
margin: 4px;
|
margin: 4px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.impact-title {
|
.impact-title {
|
||||||
font-size: bold;
|
font-size: bold;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1224,140 +1335,169 @@ ul, li {
|
|||||||
font-family: MailartRubberstamp;
|
font-family: MailartRubberstamp;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lock-icon {
|
.lock-icon {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-sheet-img {
|
.item-sheet-img {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: auto;
|
height: auto;
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-img {
|
.item-name-img {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 2rem;
|
max-width: 2rem;
|
||||||
min-width: 2rem;
|
min-width: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-header {
|
.item-name-label-header {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 12rem;
|
max-width: 12rem;
|
||||||
min-width: 12rem;
|
min-width: 12rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-header-long {
|
.item-name-label-header-long {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 14rem;
|
max-width: 14rem;
|
||||||
min-width: 14rem;
|
min-width: 14rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-header-long2 {
|
.item-name-label-header-long2 {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 24rem;
|
max-width: 24rem;
|
||||||
min-width: 24rem;
|
min-width: 24rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label {
|
.item-name-label {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 10rem;
|
max-width: 10rem;
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-long {
|
.item-name-label-long {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 12rem;
|
max-width: 12rem;
|
||||||
min-width: 12rem;
|
min-width: 12rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-short {
|
.item-name-label-short {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 4rem;
|
max-width: 4rem;
|
||||||
min-width: 4rem;
|
min-width: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-medium {
|
.item-name-label-medium {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 6rem;
|
max-width: 6rem;
|
||||||
min-width: 6rem;
|
min-width: 6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-medium2 {
|
.item-name-label-medium2 {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
max-width: 10rem;
|
max-width: 10rem;
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-free {
|
.item-name-label-free {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-long2 {
|
.item-name-label-long2 {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 22rem;
|
max-width: 22rem;
|
||||||
min-width: 22rem;
|
min-width: 22rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-level2 {
|
.item-name-label-level2 {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 9rem;
|
max-width: 9rem;
|
||||||
min-width: 9rem;
|
min-width: 9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-field-label-short {
|
.item-field-label-short {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 4rem;
|
max-width: 4rem;
|
||||||
min-width: 4rem;
|
min-width: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-field-label-short-header {
|
.item-field-label-short-header {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 2.2rem;
|
max-width: 2.2rem;
|
||||||
min-width: 2.2rem;
|
min-width: 2.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-field-label-medium {
|
.item-field-label-medium {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 6rem;
|
max-width: 6rem;
|
||||||
min-width: 6rem;
|
min-width: 6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-field-skill {
|
.item-field-skill {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 6.8rem;
|
max-width: 6.8rem;
|
||||||
min-width: 6.8rem;
|
min-width: 6.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-field-label-long {
|
.item-field-label-long {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 10rem;
|
max-width: 10rem;
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-control-end {
|
.item-control-end {
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alternate-list {
|
.alternate-list {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-filler {
|
.item-filler {
|
||||||
flex-grow: 6;
|
flex-grow: 6;
|
||||||
flex-shrink: 7;
|
flex-shrink: 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-controls-fixed {
|
.item-controls-fixed {
|
||||||
min-width: 2rem;
|
min-width: 2rem;
|
||||||
max-width: 2rem;
|
max-width: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-controls-fixed-full {
|
.item-controls-fixed-full {
|
||||||
min-width: 3rem;
|
min-width: 3rem;
|
||||||
max-width: 3rem;
|
max-width: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attribute-label {
|
.attribute-label {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flexrow-no-expand {
|
.flexrow-no-expand {
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flexrow-start {
|
.flexrow-start {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-input-small {
|
.item-input-small {
|
||||||
max-width: 16px;
|
max-width: 16px;
|
||||||
max-height: 12px;
|
max-height: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.character-summary-rollable {
|
.character-summary-rollable {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
@@ -1365,6 +1505,7 @@ ul, li {
|
|||||||
.ecryme-roll-dialog .window-header {
|
.ecryme-roll-dialog .window-header {
|
||||||
border-radius: 10px 10px 0% 0%;
|
border-radius: 10px 10px 0% 0%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ecryme-roll-dialog .window-content {
|
.ecryme-roll-dialog .window-content {
|
||||||
border-radius: 0% 0% 10px 10px;
|
border-radius: 0% 0% 10px 10px;
|
||||||
}
|
}
|
||||||
@@ -1381,16 +1522,19 @@ ul, li {
|
|||||||
.bonus-spec {
|
.bonus-spec {
|
||||||
max-width: 48px;
|
max-width: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confront-bonus-container {
|
.confront-bonus-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pool-list {
|
.pool-list {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confront-bonus-centered {
|
.confront-bonus-centered {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@@ -1404,12 +1548,14 @@ ul, li {
|
|||||||
.dice-spec {
|
.dice-spec {
|
||||||
max-width: 64px;
|
max-width: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confront-dice-container {
|
.confront-dice-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confront-dice-centered {
|
.confront-dice-centered {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@@ -1419,6 +1565,7 @@ ul, li {
|
|||||||
font-family: MailartRubberstamp;
|
font-family: MailartRubberstamp;
|
||||||
transform: translate(-50%, -55%);
|
transform: translate(-50%, -55%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.confront-area {
|
.confront-area {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// ============================================================
|
||||||
|
// Ecryme LESS Variables
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
// Background & images
|
||||||
|
@background-image: url("../images/ui/fond_carnet_01.webp");
|
||||||
|
@logo-image: url("../images/ui/ecryme_logo_small_01.webp");
|
||||||
|
|
||||||
|
// Text colors
|
||||||
|
@color-text-dark: rgba(19, 18, 18, 0.95);
|
||||||
|
@color-text-disabled: #1c2058;
|
||||||
|
|
||||||
|
// Input / select
|
||||||
|
@color-input-bg: white;
|
||||||
|
@color-input-text: #494e6b;
|
||||||
|
|
||||||
|
// Navigation
|
||||||
|
@color-nav-bg: #252525;
|
||||||
|
@color-nav-text: beige;
|
||||||
|
|
||||||
|
// Accent & interaction
|
||||||
|
@color-accent: #ff6600;
|
||||||
|
|
||||||
|
// Dark UI controls
|
||||||
|
@color-control-dark: rgba(30, 25, 20, 1);
|
||||||
|
@color-control-warm: rgba(72, 46, 28, 1);
|
||||||
|
|
||||||
|
// Typography
|
||||||
|
@font-primary: "MailartRubberstamp";
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Steampunk palette — Ecryme (industrial acid world)
|
||||||
|
// ============================================================
|
||||||
|
@steam-dark: #1A1510; // charbon / fer sombre
|
||||||
|
@steam-metal: #252018; // métal industriel
|
||||||
|
@steam-metal-mid: #352E22; // métal moyen
|
||||||
|
@steam-brass: #B87333; // laiton
|
||||||
|
@steam-brass-light: #D4963A; // laiton clair / reflet
|
||||||
|
@steam-brass-dark: #7A4E1E; // laiton sombre
|
||||||
|
@steam-copper: #C07038; // cuivre
|
||||||
|
@steam-gold: #D4AF37; // or vieilli
|
||||||
|
@steam-rust: #5C2A0A; // rouille
|
||||||
|
@steam-parchment: #EAD9A8; // parchemin / papier vieilli
|
||||||
|
@steam-parchment-dk:#D4BF84; // parchemin sombre
|
||||||
|
@steam-cream: #F2EAD0; // crème
|
||||||
|
@steam-acid: #6B9420; // vert acide industriel (muted)
|
||||||
|
@steam-acid-bright: #9ACD32; // vert acide vif
|
||||||
|
@steam-acid-dark: #3B5412; // vert acide profond
|
||||||
|
@steam-success: #4A7A18; // vert succès
|
||||||
|
@steam-failure: #7B1E1E; // rouge rouille échec
|
||||||
|
@steam-rivet: #8A7055; // couleur rivet
|
||||||
@@ -0,0 +1,430 @@
|
|||||||
|
// ============================================================
|
||||||
|
// Actor sheets — Steampunk theme
|
||||||
|
// Scoped to .fvtt-ecryme.sheet.actor and .fvtt-ecryme.sheet.annency
|
||||||
|
// Applies visual theming without touching layout or tab structure.
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
.fvtt-ecryme.sheet.actor,
|
||||||
|
.fvtt-ecryme.sheet.annency {
|
||||||
|
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
// AppV2 window title bar — brass plate
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
.window-header {
|
||||||
|
.brass-gradient();
|
||||||
|
border-bottom: 2px solid @steam-brass-dark;
|
||||||
|
color: @steam-dark;
|
||||||
|
|
||||||
|
.window-title {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: @steam-dark;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-button,
|
||||||
|
button[data-action="close"] {
|
||||||
|
color: @steam-dark;
|
||||||
|
opacity: 0.75;
|
||||||
|
&:hover { opacity: 1; color: @steam-rust; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Window outer frame — rivets
|
||||||
|
border: 2px solid @steam-brass-dark;
|
||||||
|
box-shadow:
|
||||||
|
inset 4px 4px 0 1px @steam-rivet,
|
||||||
|
inset -4px 4px 0 1px @steam-rivet,
|
||||||
|
inset 4px -4px 0 1px @steam-rivet,
|
||||||
|
inset -4px -4px 0 1px @steam-rivet,
|
||||||
|
0 4px 16px rgba(0, 0, 0, 0.55);
|
||||||
|
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
// Sheet header — profile image + name area
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
.sheet-header {
|
||||||
|
background: linear-gradient(180deg, @steam-parchment-dk 0%, @steam-parchment 100%);
|
||||||
|
border-bottom: 2px solid @steam-brass-dark;
|
||||||
|
padding: 8px 10px;
|
||||||
|
align-items: stretch;
|
||||||
|
|
||||||
|
// Profile image — fills full header height, square ratio
|
||||||
|
.profile-img {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
align-self: stretch;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
border: 3px solid @steam-brass-dark;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 0 8px rgba(0, 0, 0, 0.45);
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
object-fit: cover;
|
||||||
|
object-position: center top;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Character name — large, dark ink
|
||||||
|
h1.charname input {
|
||||||
|
font-family: @font-primary;
|
||||||
|
color: @steam-dark;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 2px solid rgba(@steam-brass-dark, 0.4);
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
|
||||||
|
padding-bottom: 2px;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
border-bottom-color: @steam-brass;
|
||||||
|
background: rgba(@steam-cream, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header traits area (spleen/ideal/traits)
|
||||||
|
.actor-header-traits {
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
color: @steam-rust;
|
||||||
|
padding: 1px 0;
|
||||||
|
border-bottom: 1px solid rgba(@steam-brass-dark, 0.15);
|
||||||
|
&:last-child { border-bottom: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
label { color: @steam-rust; }
|
||||||
|
|
||||||
|
// Trait name as link
|
||||||
|
a[data-action="itemEdit"] {
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
font-weight: bold;
|
||||||
|
&:hover { color: @steam-brass; text-decoration: underline; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annency description textarea
|
||||||
|
textarea {
|
||||||
|
background: @steam-cream;
|
||||||
|
color: @steam-dark;
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 3px 5px;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
// Tab navigation — industrial metal bar
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
nav.sheet-tabs {
|
||||||
|
background: linear-gradient(180deg, @steam-metal 0%, @steam-metal-mid 100%);
|
||||||
|
border-top: 1px solid @steam-brass-dark;
|
||||||
|
border-bottom: 2px solid @steam-brass-dark;
|
||||||
|
padding: 0 8px;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
a.item {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: @steam-parchment-dk;
|
||||||
|
padding: 4px 10px;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
border-bottom: 3px solid transparent;
|
||||||
|
transition: color 0.15s, border-color 0.15s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @steam-brass-light;
|
||||||
|
border-bottom-color: rgba(@steam-brass, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: @steam-brass-light;
|
||||||
|
border-bottom-color: @steam-brass;
|
||||||
|
text-shadow: 0 0 6px rgba(@steam-brass-light, 0.5);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
// Window content area — parchment background
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
.window-content {
|
||||||
|
background: @steam-parchment;
|
||||||
|
color: @steam-rust;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
// Sheet body (tab content)
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
.sheet-body {
|
||||||
|
background: transparent;
|
||||||
|
color: @steam-rust;
|
||||||
|
padding: 0 8px;
|
||||||
|
|
||||||
|
// ---- Section title rows ----
|
||||||
|
.items-title-bg {
|
||||||
|
.brass-gradient();
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 3px 6px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
|
||||||
|
h3, label, .items-title-text {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 0.92rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: @steam-dark;
|
||||||
|
text-shadow: 0 1px 1px rgba(255, 220, 60, 0.4);
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roll icons in title (NPC category roll)
|
||||||
|
a {
|
||||||
|
color: @steam-dark;
|
||||||
|
opacity: 0.8;
|
||||||
|
&:hover { opacity: 1; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Alternating item list ----
|
||||||
|
ul.item-list,
|
||||||
|
ul.stat-list,
|
||||||
|
ul.alternate-list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 2px 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.list-item {
|
||||||
|
background: @steam-parchment;
|
||||||
|
border-bottom: 1px solid rgba(@steam-brass-dark, 0.18);
|
||||||
|
padding: 3px 4px;
|
||||||
|
color: @steam-rust;
|
||||||
|
font-size: 0.83rem;
|
||||||
|
|
||||||
|
&:nth-child(even) { background: @steam-parchment-dk; }
|
||||||
|
&:last-child { border-bottom: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Items with hover effect
|
||||||
|
li.list-item-shadow {
|
||||||
|
transition: background 0.1s;
|
||||||
|
&:hover { background: mix(@steam-parchment, @steam-brass, 88%); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Labels ----
|
||||||
|
label,
|
||||||
|
.item-name-label-short,
|
||||||
|
.item-name-label-medium,
|
||||||
|
.item-name-label-long,
|
||||||
|
.item-name-label-long2,
|
||||||
|
.item-name-label-free,
|
||||||
|
.item-field-label-short,
|
||||||
|
.item-field-label-medium {
|
||||||
|
color: @steam-rust;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Roll action links (dice icons) ----
|
||||||
|
a[data-action^="roll"],
|
||||||
|
a.roll-skill,
|
||||||
|
a.roll-spec,
|
||||||
|
a.roll-cephaly {
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
&:hover { color: @steam-brass; }
|
||||||
|
i { font-size: 0.85rem; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Item edit links ----
|
||||||
|
a[data-action="itemEdit"],
|
||||||
|
a.item-edit {
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
&:hover { color: @steam-brass; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Item control buttons (edit/delete/add) ----
|
||||||
|
.item-controls {
|
||||||
|
a.item-control {
|
||||||
|
color: @steam-rust;
|
||||||
|
opacity: 0.7;
|
||||||
|
padding: 0 3px;
|
||||||
|
&:hover { color: @steam-brass-dark; opacity: 1; }
|
||||||
|
|
||||||
|
&.item-delete:hover { color: @steam-failure; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Selects & inputs inside body ----
|
||||||
|
select,
|
||||||
|
input[type="text"],
|
||||||
|
input[type="number"] {
|
||||||
|
background: @steam-cream;
|
||||||
|
color: @steam-dark;
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 1px 4px;
|
||||||
|
font-size: 0.83rem;
|
||||||
|
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: @steam-brass;
|
||||||
|
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1),
|
||||||
|
0 0 4px rgba(@steam-brass, 0.45);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skill level select in header (NPC)
|
||||||
|
.item-field-label-short-header select {
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
color: @steam-dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- HR separator — brass wire + gear ----
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
height: 2px;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
transparent 0%,
|
||||||
|
@steam-brass-dark 10%,
|
||||||
|
@steam-brass 50%,
|
||||||
|
@steam-brass-dark 90%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
margin: 10px 4px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "⚙";
|
||||||
|
position: absolute;
|
||||||
|
top: -0.6em;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
background: @steam-parchment;
|
||||||
|
padding: 0 4px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Impact boxes (combat tab) ----
|
||||||
|
.impact-box {
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 6px 8px;
|
||||||
|
margin: 4px;
|
||||||
|
|
||||||
|
.impact-title {
|
||||||
|
.brass-gradient();
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 3px 6px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
|
||||||
|
label, .items-title-text {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: @steam-dark;
|
||||||
|
text-shadow: 0 1px 1px rgba(255, 220, 60, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 2px 0;
|
||||||
|
border-bottom: 1px solid rgba(@steam-brass-dark, 0.18);
|
||||||
|
color: @steam-rust;
|
||||||
|
font-size: 0.83rem;
|
||||||
|
&:last-child { border-bottom: none; }
|
||||||
|
|
||||||
|
// +/- impact buttons
|
||||||
|
a[data-action="impactModify"] {
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
font-size: 1rem;
|
||||||
|
&:hover { color: @steam-brass; }
|
||||||
|
}
|
||||||
|
|
||||||
|
span { font-weight: bold; color: @steam-dark; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Sub-list (specializations) ----
|
||||||
|
ul.ul-level1 {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 0 16px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
background: transparent;
|
||||||
|
border-bottom: 1px solid rgba(@steam-brass-dark, 0.1);
|
||||||
|
padding: 2px 4px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: @steam-rust;
|
||||||
|
|
||||||
|
a { color: @steam-brass-dark; &:hover { color: @steam-brass; } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Item icon (sheet-competence-img) ----
|
||||||
|
img.sheet-competence-img {
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
padding: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group.small-editor,
|
||||||
|
.form-group.editor {
|
||||||
|
background: @steam-cream;
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 4px;
|
||||||
|
color: @steam-dark;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group.small-editor textarea,
|
||||||
|
.form-group.editor textarea {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
min-height: 92px;
|
||||||
|
resize: none;
|
||||||
|
overflow-y: auto;
|
||||||
|
background: @steam-cream;
|
||||||
|
color: @steam-dark;
|
||||||
|
border: none;
|
||||||
|
padding: 4px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Grid headings (h3/h4 outside of items-title-bg) ----
|
||||||
|
h3, h4 {
|
||||||
|
font-family: @font-primary;
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
margin: 6px 0 3px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
// ============================================================
|
||||||
|
// Actor sheet AppV2 styles (.fvtt-ecryme.sheet.actor)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
.fvtt-ecryme.sheet.actor {
|
||||||
|
// Header: compact with profile image
|
||||||
|
.sheet-header {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-height: 90px;
|
||||||
|
padding: 4px 6px;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.profile-img {
|
||||||
|
flex: 0 0 80px;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
object-fit: cover;
|
||||||
|
object-position: 50% 0;
|
||||||
|
border: 1px solid #7a7971;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-fields {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
h1.charname {
|
||||||
|
height: auto;
|
||||||
|
margin: 0 0 4px;
|
||||||
|
border-bottom: 0;
|
||||||
|
|
||||||
|
input {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 2rem;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actor-header-traits {
|
||||||
|
margin-top: 2px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tab bar
|
||||||
|
nav.sheet-tabs {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
|
||||||
|
a.active {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sheet body
|
||||||
|
.sheet-body {
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.active) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
// ============================================================
|
||||||
|
// Actor sheet scoped styles (.fvtt-ecryme)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
.fvtt-ecryme {
|
||||||
|
.sheet-header {
|
||||||
|
flex: 0 0 210px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.profile-img {
|
||||||
|
flex: 0 0 128px;
|
||||||
|
width: 128px;
|
||||||
|
height: auto;
|
||||||
|
max-height: 128px;
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-right: 10px;
|
||||||
|
object-fit: cover;
|
||||||
|
object-position: 50% 0;
|
||||||
|
border-width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-fields {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.charname {
|
||||||
|
height: 50px;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 5px 0;
|
||||||
|
border-bottom: 0;
|
||||||
|
|
||||||
|
input {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 3rem;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet-tabs {
|
||||||
|
flex: 0;
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 2.2rem;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
line-height: 40px;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
text-decoration: underline;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
height: 40px;
|
||||||
|
border-top: 1px solid #AAA;
|
||||||
|
border-bottom: 1px solid #AAA;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet-body,
|
||||||
|
.sheet-body .tab,
|
||||||
|
.sheet-body .tab .editor {
|
||||||
|
height: 100%;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tox {
|
||||||
|
.tox-editor-container {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.tox-edit-area {
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.resource-label {
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 1px 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.item-header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
height: 30px;
|
||||||
|
line-height: 24px;
|
||||||
|
padding: 1px 0;
|
||||||
|
border-bottom: 1px solid #BBB;
|
||||||
|
|
||||||
|
.item-image {
|
||||||
|
flex: 0 0 24px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-name {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-controls {
|
||||||
|
flex: 0 0 86px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-img-container {
|
||||||
|
margin-right: 0.2rem;
|
||||||
|
max-width: 140px;
|
||||||
|
width: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.folder > .folder-header h3 {
|
||||||
|
color: @color-text-dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor {
|
||||||
|
border: 2;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.medium-editor {
|
||||||
|
border: 2;
|
||||||
|
height: 240px;
|
||||||
|
padding: 0 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-editor {
|
||||||
|
border: 2;
|
||||||
|
height: 120px;
|
||||||
|
padding: 0 3px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,689 @@
|
|||||||
|
// ============================================================
|
||||||
|
// Chat — Steampunk theme for Ecryme
|
||||||
|
// Uses .ecryme-chat-body (custom class) so Foundry CSS never interferes.
|
||||||
|
// Header = brass plate. Body = aged parchment + dark ink.
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
// ---- Mixin: rivet ornament (corner box-shadow bolts) ----
|
||||||
|
.riveted-border() {
|
||||||
|
box-shadow:
|
||||||
|
inset 4px 4px 0 1px @steam-rivet,
|
||||||
|
inset -4px 4px 0 1px @steam-rivet,
|
||||||
|
inset 4px -4px 0 1px @steam-rivet,
|
||||||
|
inset -4px -4px 0 1px @steam-rivet,
|
||||||
|
0 3px 10px rgba(0, 0, 0, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Mixin: brass gradient ----
|
||||||
|
.brass-gradient() {
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
@steam-brass-dark 0%,
|
||||||
|
@steam-brass 30%,
|
||||||
|
@steam-brass-light 50%,
|
||||||
|
@steam-brass 70%,
|
||||||
|
@steam-brass-dark 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Chat message outer frame — brass border + rivets
|
||||||
|
// ============================================================
|
||||||
|
#chat-log .chat-message,
|
||||||
|
.chat-popout .chat-message {
|
||||||
|
border: 2px solid @steam-brass-dark;
|
||||||
|
border-radius: 3px;
|
||||||
|
.riveted-border();
|
||||||
|
margin-bottom: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
// Whisper: acid-tinted border
|
||||||
|
&.whisper {
|
||||||
|
border-color: @steam-acid-dark;
|
||||||
|
box-shadow:
|
||||||
|
inset 4px 4px 0 1px @steam-acid-dark,
|
||||||
|
inset -4px 4px 0 1px @steam-acid-dark,
|
||||||
|
inset 4px -4px 0 1px @steam-acid-dark,
|
||||||
|
inset -4px -4px 0 1px @steam-acid-dark,
|
||||||
|
0 3px 10px rgba(0, 0, 0, 0.4);
|
||||||
|
|
||||||
|
.ecryme-chat-body {
|
||||||
|
background: mix(@steam-parchment, @steam-acid, 82%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Message header — brass plate
|
||||||
|
// ============================================================
|
||||||
|
.chat-message-header {
|
||||||
|
.brass-gradient();
|
||||||
|
border-bottom: 2px solid @steam-brass-dark;
|
||||||
|
font-size: 1rem;
|
||||||
|
height: 48px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 8px;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
img.actor-icon,
|
||||||
|
.actor-icon {
|
||||||
|
border: 2px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: 0 0 4px rgba(0, 0, 0, 0.4);
|
||||||
|
width: 38px;
|
||||||
|
height: 38px;
|
||||||
|
padding: 1px;
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-actor-name {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: @steam-dark;
|
||||||
|
text-shadow: 0 1px 1px rgba(255, 210, 60, 0.5);
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-actor-subtitle {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-weight: normal;
|
||||||
|
color: @steam-dark;
|
||||||
|
opacity: 0.75;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Body — aged parchment panel (our class = Foundry never overrides)
|
||||||
|
// ============================================================
|
||||||
|
.ecryme-chat-body {
|
||||||
|
background: @steam-parchment;
|
||||||
|
color: @steam-dark;
|
||||||
|
padding: 6px 8px 8px;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
|
||||||
|
// Skill / ability icon
|
||||||
|
.ecryme-chat-icon-row {
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
|
||||||
|
img.chat-icon {
|
||||||
|
border: 2px solid @steam-brass-dark;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
width: 52px;
|
||||||
|
height: 52px;
|
||||||
|
padding: 2px;
|
||||||
|
float: left;
|
||||||
|
margin: 0 8px 4px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Brass wire separator
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
height: 2px;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
transparent 0%,
|
||||||
|
@steam-brass-dark 10%,
|
||||||
|
@steam-brass 50%,
|
||||||
|
@steam-brass-dark 90%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
margin: 6px 4px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "⚙";
|
||||||
|
position: absolute;
|
||||||
|
top: -0.6em;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
background: @steam-parchment;
|
||||||
|
padding: 0 4px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detail list — dark sepia ink on parchment
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
color: @steam-rust;
|
||||||
|
font-size: 0.87rem;
|
||||||
|
padding: 3px 2px 3px 20px;
|
||||||
|
border-bottom: 1px solid rgba(@steam-brass-dark, 0.2);
|
||||||
|
position: relative;
|
||||||
|
line-height: 1.4;
|
||||||
|
|
||||||
|
&:last-child { border-bottom: none; }
|
||||||
|
|
||||||
|
// Brass arrow bullet
|
||||||
|
&::before {
|
||||||
|
content: "▸";
|
||||||
|
position: absolute;
|
||||||
|
left: 4px;
|
||||||
|
top: 4px;
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result line (success/failure) — no bullet, centered
|
||||||
|
li.ecryme-result-line {
|
||||||
|
padding-left: 4px;
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: none;
|
||||||
|
margin-top: 2px;
|
||||||
|
|
||||||
|
&::before { content: none; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GM row with difficulty select
|
||||||
|
.ecryme-chat-gm-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin: 6px 0 4px;
|
||||||
|
color: @steam-dark;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
|
||||||
|
select {
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
color: @steam-dark;
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 2px 4px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Sent to GM" italic note
|
||||||
|
p.ecryme-chat-sent-gm {
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 0.82rem;
|
||||||
|
margin: 4px 0 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Success / Failure labels
|
||||||
|
// ============================================================
|
||||||
|
.chat-result-success {
|
||||||
|
color: @steam-success;
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-result-failure {
|
||||||
|
color: @steam-failure;
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-result-text {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1.15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Action buttons — brass mechanical style
|
||||||
|
// ============================================================
|
||||||
|
.chat-card-button,
|
||||||
|
.button-apply-impact,
|
||||||
|
.button-apply-bonus,
|
||||||
|
.button-select-confront,
|
||||||
|
.button-apply-cephaly-difficulty {
|
||||||
|
display: block;
|
||||||
|
width: calc(100% - 8px);
|
||||||
|
margin: 4px 4px 2px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-family: @font-primary;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
color: @steam-parchment;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
|
||||||
|
position: relative;
|
||||||
|
background: linear-gradient(180deg,
|
||||||
|
mix(@steam-brass, @steam-dark, 50%) 0%,
|
||||||
|
mix(@steam-brass-dark, @steam-dark, 65%) 100%
|
||||||
|
);
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 215, 80, 0.2),
|
||||||
|
0 2px 4px rgba(0, 0, 0, 0.35);
|
||||||
|
transition: background 0.15s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(180deg,
|
||||||
|
mix(@steam-brass-light, @steam-dark, 60%) 0%,
|
||||||
|
mix(@steam-brass, @steam-dark, 50%) 100%
|
||||||
|
);
|
||||||
|
color: @steam-cream;
|
||||||
|
}
|
||||||
|
&:active { top: 1px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.plus-minus-button {
|
||||||
|
background: linear-gradient(180deg,
|
||||||
|
mix(@steam-brass, @steam-dark, 40%) 0%,
|
||||||
|
mix(@steam-brass-dark, @steam-dark, 55%) 100%
|
||||||
|
);
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
color: @steam-parchment;
|
||||||
|
padding: 2px 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
&:hover { color: @steam-cream; }
|
||||||
|
&:active { position: relative; top: 1px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Dice images
|
||||||
|
// ============================================================
|
||||||
|
.dice-image {
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: 0 0 3px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dice-image-reroll {
|
||||||
|
border: 2px solid @steam-acid;
|
||||||
|
border-radius: 2px;
|
||||||
|
background-color: rgba(@steam-acid-dark, 0.15);
|
||||||
|
box-shadow: 0 0 5px rgba(@steam-acid, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---- Mixin: rivet ornament (corner box-shadow bolts) ----
|
||||||
|
.riveted-border() {
|
||||||
|
box-shadow:
|
||||||
|
inset 4px 4px 0 1px @steam-rivet,
|
||||||
|
inset -4px 4px 0 1px @steam-rivet,
|
||||||
|
inset 4px -4px 0 1px @steam-rivet,
|
||||||
|
inset -4px -4px 0 1px @steam-rivet,
|
||||||
|
0 3px 10px rgba(0, 0, 0, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Mixin: brass gradient ----
|
||||||
|
.brass-gradient() {
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
@steam-brass-dark 0%,
|
||||||
|
@steam-brass 30%,
|
||||||
|
@steam-brass-light 50%,
|
||||||
|
@steam-brass 70%,
|
||||||
|
@steam-brass-dark 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Chat message container — parchment panel + brass frame
|
||||||
|
// ============================================================
|
||||||
|
#chat-log .chat-message,
|
||||||
|
.chat-popout .chat-message {
|
||||||
|
border: 2px solid @steam-brass-dark;
|
||||||
|
border-radius: 3px;
|
||||||
|
.riveted-border();
|
||||||
|
// Parchment background applied at all levels
|
||||||
|
background: @steam-parchment !important;
|
||||||
|
background-color: @steam-parchment !important;
|
||||||
|
color: @steam-dark;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
|
||||||
|
// Cover Foundry's inner wrappers
|
||||||
|
.message-content {
|
||||||
|
background: @steam-parchment !important;
|
||||||
|
background-color: @steam-parchment !important;
|
||||||
|
color: @steam-dark;
|
||||||
|
padding: 4px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All text descendants default to dark ink
|
||||||
|
p, span, div, label, li, ul, h1, h2, h3, h4, h5 {
|
||||||
|
color: @steam-dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whisper: acid-tinted parchment
|
||||||
|
&.whisper {
|
||||||
|
border-color: @steam-acid-dark;
|
||||||
|
background: mix(@steam-parchment, @steam-acid, 85%) !important;
|
||||||
|
background-color: mix(@steam-parchment, @steam-acid, 85%) !important;
|
||||||
|
box-shadow:
|
||||||
|
inset 4px 4px 0 1px @steam-acid-dark,
|
||||||
|
inset -4px 4px 0 1px @steam-acid-dark,
|
||||||
|
inset 4px -4px 0 1px @steam-acid-dark,
|
||||||
|
inset -4px -4px 0 1px @steam-acid-dark,
|
||||||
|
0 3px 10px rgba(0, 0, 0, 0.4);
|
||||||
|
|
||||||
|
.message-content {
|
||||||
|
background: mix(@steam-parchment, @steam-acid, 85%) !important;
|
||||||
|
background-color: mix(@steam-parchment, @steam-acid, 85%) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Message header — brass plate with dark name
|
||||||
|
// ============================================================
|
||||||
|
.chat-message-header {
|
||||||
|
.brass-gradient();
|
||||||
|
border-bottom: 2px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px 2px 0 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
height: 48px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 6px;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
// Force brass bg even inside message-content parchment
|
||||||
|
background: linear-gradient(135deg, @steam-brass-dark 0%, @steam-brass 30%, @steam-brass-light 50%, @steam-brass 70%, @steam-brass-dark 100%) !important;
|
||||||
|
background-color: @steam-brass !important;
|
||||||
|
|
||||||
|
img.actor-icon,
|
||||||
|
.actor-icon {
|
||||||
|
border: 2px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: 0 0 4px rgba(0,0,0,0.4);
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
padding: 1px;
|
||||||
|
background: @steam-parchment;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-actor-name {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: @steam-dark !important;
|
||||||
|
text-shadow: 0 1px 1px rgba(255, 220, 80, 0.4);
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Separator — brass wire with central gear
|
||||||
|
// ============================================================
|
||||||
|
#chat-log .chat-message hr,
|
||||||
|
.chat-popout .chat-message hr {
|
||||||
|
border: none;
|
||||||
|
height: 2px;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
transparent 0%,
|
||||||
|
@steam-brass-dark 10%,
|
||||||
|
@steam-brass 50%,
|
||||||
|
@steam-brass-dark 90%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
margin: 5px 4px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "⚙";
|
||||||
|
position: absolute;
|
||||||
|
top: -0.6em;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
color: @steam-brass;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
background: @steam-parchment;
|
||||||
|
padding: 0 4px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Detail list — dark ink on parchment
|
||||||
|
// ============================================================
|
||||||
|
#chat-log .chat-message ul,
|
||||||
|
.chat-popout .chat-message ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 4px 0;
|
||||||
|
padding: 0 4px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
color: @steam-rust !important; // dark sepia/brown ink — readable on parchment
|
||||||
|
font-size: 0.88rem;
|
||||||
|
padding: 2px 0 2px 18px;
|
||||||
|
border-bottom: 1px solid rgba(@steam-brass-dark, 0.2);
|
||||||
|
position: relative;
|
||||||
|
line-height: 1.4;
|
||||||
|
|
||||||
|
&:last-child { border-bottom: none; }
|
||||||
|
|
||||||
|
// Arrow bullet in brass
|
||||||
|
&::before {
|
||||||
|
content: "▸";
|
||||||
|
position: absolute;
|
||||||
|
left: 2px;
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong { color: @steam-brass-dark !important; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Skill / ability icon
|
||||||
|
// ============================================================
|
||||||
|
.chat-icon {
|
||||||
|
border: 2px solid @steam-brass-dark;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 0 5px rgba(0,0,0,0.3);
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
width: 52px;
|
||||||
|
height: 52px;
|
||||||
|
padding: 2px;
|
||||||
|
margin: 4px 6px 4px 4px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Result labels (success / failure)
|
||||||
|
// ============================================================
|
||||||
|
.chat-result-success {
|
||||||
|
color: @steam-success !important;
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-result-failure {
|
||||||
|
color: @steam-failure !important;
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-result-text {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: @steam-dark !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Action buttons — brass mechanical style
|
||||||
|
// ============================================================
|
||||||
|
.chat-card-button,
|
||||||
|
.button-apply-impact,
|
||||||
|
.button-apply-bonus,
|
||||||
|
.button-select-confront,
|
||||||
|
.button-apply-cephaly-difficulty {
|
||||||
|
display: block;
|
||||||
|
width: calc(100% - 8px);
|
||||||
|
margin: 4px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-family: @font-primary;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
color: @steam-parchment !important;
|
||||||
|
text-shadow: 0 1px 2px rgba(0,0,0,0.8);
|
||||||
|
position: relative;
|
||||||
|
background: linear-gradient(180deg,
|
||||||
|
mix(@steam-brass, @steam-dark, 50%) 0%,
|
||||||
|
mix(@steam-brass-dark, @steam-dark, 65%) 100%
|
||||||
|
);
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 215, 80, 0.2),
|
||||||
|
0 2px 4px rgba(0,0,0,0.4);
|
||||||
|
transition: background 0.15s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(180deg,
|
||||||
|
mix(@steam-brass-light, @steam-dark, 60%) 0%,
|
||||||
|
mix(@steam-brass, @steam-dark, 50%) 100%
|
||||||
|
);
|
||||||
|
color: @steam-cream !important;
|
||||||
|
}
|
||||||
|
&:active { top: 1px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.plus-minus-button {
|
||||||
|
background: linear-gradient(180deg,
|
||||||
|
mix(@steam-brass, @steam-dark, 40%) 0%,
|
||||||
|
mix(@steam-brass-dark, @steam-dark, 55%) 100%
|
||||||
|
);
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
color: @steam-parchment !important;
|
||||||
|
padding: 2px 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
&:hover { color: @steam-cream !important; }
|
||||||
|
&:active { position: relative; top: 1px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Dice images — brass frame
|
||||||
|
// ============================================================
|
||||||
|
.dice-image {
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: 0 0 3px rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dice-image-reroll {
|
||||||
|
border: 2px solid @steam-acid;
|
||||||
|
border-radius: 2px;
|
||||||
|
background-color: rgba(@steam-acid-dark, 0.15);
|
||||||
|
box-shadow: 0 0 5px rgba(@steam-acid, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// GM difficulty select
|
||||||
|
// ============================================================
|
||||||
|
#chat-log .chat-message,
|
||||||
|
.chat-popout .chat-message {
|
||||||
|
select[name="cephaly-difficulty"] {
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
color: @steam-dark;
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 2px 4px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Welcome message — sections & footer
|
||||||
|
// ============================================================
|
||||||
|
.ecryme-chat-body {
|
||||||
|
|
||||||
|
// Title
|
||||||
|
.welcome-message-h3 {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
margin: 0 0 8px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
border-bottom: 1px solid rgba(@steam-brass-dark, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Content sections
|
||||||
|
.welcome-section {
|
||||||
|
color: @steam-dark;
|
||||||
|
font-size: 0.86rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 5px 6px;
|
||||||
|
background: rgba(@steam-parchment-dk, 0.55);
|
||||||
|
border-left: 3px solid @steam-brass;
|
||||||
|
border-radius: 0 2px 2px 0;
|
||||||
|
|
||||||
|
strong { color: @steam-rust; }
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: underline;
|
||||||
|
&:hover { color: @steam-brass; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer signature
|
||||||
|
.welcome-footer {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 0.82rem;
|
||||||
|
color: @steam-rust;
|
||||||
|
text-align: center;
|
||||||
|
font-style: italic;
|
||||||
|
margin-top: 8px;
|
||||||
|
padding-top: 6px;
|
||||||
|
border-top: 1px solid rgba(@steam-brass-dark, 0.3);
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,251 @@
|
|||||||
|
// ============================================================
|
||||||
|
// Chat, dice, roll dialogs, buttons
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
.chat-message-header {
|
||||||
|
background: rgba(220, 220, 210, 0.5);
|
||||||
|
font-size: 1.1rem;
|
||||||
|
height: 48px;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-chat-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-message-h3 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
color: darkred;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message {
|
||||||
|
background: rgba(220, 220, 210, 0.5);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
|
||||||
|
&.whisper {
|
||||||
|
background: rgba(220, 220, 210, 0.75);
|
||||||
|
border: 2px solid #545469;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-header {
|
||||||
|
.flavor-text,
|
||||||
|
.whisper-to {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-icon {
|
||||||
|
border: 0;
|
||||||
|
padding: 2px 6px 2px 2px;
|
||||||
|
float: left;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-result-text,
|
||||||
|
.chat-actor-name {
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-result-success { color: darkgreen; }
|
||||||
|
.chat-result-failure { color: darkred; }
|
||||||
|
|
||||||
|
.chat-img {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roll dialog
|
||||||
|
.roll-dialog-header {
|
||||||
|
height: 52px;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roll-dialog-actor-title {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1.3;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ecryme-roll-dialog,
|
||||||
|
.ecryme-confront-start-dialog,
|
||||||
|
.ecryme-confrontation-dialog {
|
||||||
|
.window-header { border-radius: 10px 10px 0% 0%; }
|
||||||
|
.window-content { border-radius: 0% 0% 10px 10px; }
|
||||||
|
|
||||||
|
.sheet-footer {
|
||||||
|
margin-top: 8px;
|
||||||
|
padding: 4px 0;
|
||||||
|
border-top: 1px solid var(--color-border-light-tertiary, #999);
|
||||||
|
gap: 6px;
|
||||||
|
button {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ecryme-confront-start-dialog {
|
||||||
|
.sheet-footer {
|
||||||
|
gap: 4px;
|
||||||
|
button { font-size: 0.85rem; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.skill-roll-dialog div {
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actor icon in chat
|
||||||
|
.actor-icon {
|
||||||
|
float: left;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
padding: 2px 6px 2px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dice
|
||||||
|
.padding-dice {
|
||||||
|
padding-top: .2rem;
|
||||||
|
padding-bottom: .2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dice-image {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dice-image-reroll {
|
||||||
|
background-color: rgba(115, 224, 115, 0.25);
|
||||||
|
border-color: #011d33;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px;
|
||||||
|
border-radius: 0%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-dice {
|
||||||
|
width: 15%;
|
||||||
|
height: 15%;
|
||||||
|
font-size: 15px;
|
||||||
|
padding: 10px;
|
||||||
|
padding-top: .2rem;
|
||||||
|
padding-bottom: .2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.div-center { align-self: center; }
|
||||||
|
|
||||||
|
.ability-icon {
|
||||||
|
border: 0;
|
||||||
|
padding: 2px;
|
||||||
|
max-width: 32px;
|
||||||
|
max-height: 32px;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-ability-icon {
|
||||||
|
border: 0;
|
||||||
|
padding: 2px;
|
||||||
|
max-width: 16px;
|
||||||
|
max-height: 16px;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.combat-icon {
|
||||||
|
border: 0;
|
||||||
|
padding: 2px;
|
||||||
|
max-width: 24px;
|
||||||
|
max-height: 24px;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dice cell / formula / total
|
||||||
|
.dice-cell {
|
||||||
|
padding-left: 12px;
|
||||||
|
padding-right: 12px;
|
||||||
|
width: 60px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dice-formula,
|
||||||
|
.dice-total {
|
||||||
|
height: 54px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
.chat-card-button {
|
||||||
|
box-shadow: inset 0px 1px 0px 0px #a6827e;
|
||||||
|
background: linear-gradient(to bottom, rgba(33, 55, 74, 0.98824) 5%, rgba(21, 40, 51, 0.67059) 100%);
|
||||||
|
background-color: rgba(125, 93, 59, 0);
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 2px ridge #846109;
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 4px 12px 0px 12px;
|
||||||
|
text-decoration: none;
|
||||||
|
text-shadow: 0px 1px 0px #4d3534;
|
||||||
|
position: relative;
|
||||||
|
margin: 2px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(to bottom, #800000 5%, #3e0101 100%);
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.plus-minus-button {
|
||||||
|
box-shadow: inset 0px 1px 0px 0px #a6827e;
|
||||||
|
background: linear-gradient(to bottom, rgba(33, 55, 74, 0.98824) 5%, rgba(21, 40, 51, 0.67059) 100%);
|
||||||
|
background-color: rgba(125, 93, 59, 0);
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px ridge #846109;
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 2px;
|
||||||
|
text-decoration: none;
|
||||||
|
text-shadow: 0px 1px 0px #4d3534;
|
||||||
|
position: relative;
|
||||||
|
margin: 0px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(to bottom, #800000 5%, #3e0101 100%);
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.plus-minus {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
// ============================================================
|
||||||
|
// Roll & Confrontation dialogs — Steampunk theme
|
||||||
|
// Targets .ecryme-roll-dialog, .ecryme-confront-start-dialog,
|
||||||
|
// .ecryme-confrontation-dialog (AppV2 root classes)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
// Common container mixin
|
||||||
|
.steam-dialog-window() {
|
||||||
|
// Title bar — brass plate
|
||||||
|
.window-header {
|
||||||
|
.brass-gradient();
|
||||||
|
border-bottom: 2px solid @steam-brass-dark;
|
||||||
|
color: @steam-dark;
|
||||||
|
text-shadow: 0 1px 1px rgba(255, 220, 80, 0.4);
|
||||||
|
|
||||||
|
.window-title {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: @steam-dark;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close button — rivet look
|
||||||
|
.header-button,
|
||||||
|
button[data-action="close"] {
|
||||||
|
color: @steam-dark;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 1rem;
|
||||||
|
opacity: 0.7;
|
||||||
|
&:hover { opacity: 1; color: @steam-rust; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Content area — aged parchment
|
||||||
|
.window-content {
|
||||||
|
background: @steam-parchment;
|
||||||
|
color: @steam-rust;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Apply to all three dialog app containers
|
||||||
|
// ============================================================
|
||||||
|
.ecryme-roll-dialog,
|
||||||
|
.ecryme-confront-start-dialog,
|
||||||
|
.ecryme-confrontation-dialog {
|
||||||
|
.steam-dialog-window();
|
||||||
|
|
||||||
|
// Outer window frame
|
||||||
|
border: 2px solid @steam-brass-dark;
|
||||||
|
box-shadow:
|
||||||
|
inset 4px 4px 0 1px @steam-rivet,
|
||||||
|
inset -4px 4px 0 1px @steam-rivet,
|
||||||
|
inset 4px -4px 0 1px @steam-rivet,
|
||||||
|
inset -4px -4px 0 1px @steam-rivet,
|
||||||
|
0 4px 14px rgba(0, 0, 0, 0.6);
|
||||||
|
|
||||||
|
// ---- Actor header row ----
|
||||||
|
.roll-dialog-header {
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
@steam-parchment-dk 0%,
|
||||||
|
@steam-parchment 60%
|
||||||
|
);
|
||||||
|
border-bottom: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 6px 8px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.actor-icon {
|
||||||
|
border: 2px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: 0 0 4px rgba(0, 0, 0, 0.35);
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
padding: 1px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roll-dialog-actor-title {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: @steam-dark;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Form labels ----
|
||||||
|
.roll-dialog-label {
|
||||||
|
color: @steam-rust;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Row separator ----
|
||||||
|
.flexrow {
|
||||||
|
border-bottom: 1px solid rgba(@steam-brass-dark, 0.15);
|
||||||
|
padding: 3px 0;
|
||||||
|
&:last-child { border-bottom: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Selects & inputs ----
|
||||||
|
select,
|
||||||
|
input[type="text"],
|
||||||
|
input[type="number"] {
|
||||||
|
background: @steam-cream;
|
||||||
|
color: @steam-dark;
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 2px 5px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.12);
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: @steam-brass;
|
||||||
|
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.12),
|
||||||
|
0 0 4px rgba(@steam-brass, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select[multiple] {
|
||||||
|
min-height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Headings inside content ----
|
||||||
|
h3, h4 {
|
||||||
|
font-family: @font-primary;
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin: 6px 0 3px;
|
||||||
|
border-bottom: 1px solid rgba(@steam-brass-dark, 0.3);
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Footer ----
|
||||||
|
.sheet-footer {
|
||||||
|
border-top: 2px solid @steam-brass-dark;
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
padding: 6px 4px;
|
||||||
|
margin-top: 6px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: linear-gradient(180deg,
|
||||||
|
mix(@steam-brass, @steam-dark, 50%) 0%,
|
||||||
|
mix(@steam-brass-dark, @steam-dark, 65%) 100%
|
||||||
|
);
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
color: @steam-parchment;
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
padding: 5px 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 215, 80, 0.2),
|
||||||
|
0 2px 4px rgba(0, 0, 0, 0.35);
|
||||||
|
transition: background 0.15s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(180deg,
|
||||||
|
mix(@steam-brass-light, @steam-dark, 60%) 0%,
|
||||||
|
mix(@steam-brass, @steam-dark, 50%) 100%
|
||||||
|
);
|
||||||
|
color: @steam-cream;
|
||||||
|
}
|
||||||
|
&:active { position: relative; top: 1px; }
|
||||||
|
|
||||||
|
&[disabled] {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: default;
|
||||||
|
box-shadow: none;
|
||||||
|
&:hover { background: none; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Confrontation dialog — dice / bonus pool areas
|
||||||
|
// ============================================================
|
||||||
|
.ecryme-confrontation-dialog {
|
||||||
|
|
||||||
|
// Area containers (execution, preservation, pool)
|
||||||
|
.confront-area {
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 3px;
|
||||||
|
min-height: 60px;
|
||||||
|
padding: 4px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 4px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execution area — slight warm tint
|
||||||
|
.confront-execution-area {
|
||||||
|
border-left: 3px solid @steam-brass;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preservation area — slight cool tint
|
||||||
|
.confront-preservation-area {
|
||||||
|
border-left: 3px solid @steam-copper;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pool list area
|
||||||
|
.pool-list {
|
||||||
|
border-left: 3px solid @steam-metal-mid;
|
||||||
|
min-height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Individual dice container
|
||||||
|
.confront-dice-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
|
cursor: grab;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 2px;
|
||||||
|
transition: background 0.1s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(@steam-brass, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dice image
|
||||||
|
.confront-dice {
|
||||||
|
border: 1px solid @steam-brass-dark;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
|
||||||
|
background: @steam-parchment-dk;
|
||||||
|
width: 38px;
|
||||||
|
height: 38px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dice value label
|
||||||
|
.confront-dice-centered,
|
||||||
|
.confront-bonus-centered {
|
||||||
|
font-family: @font-primary;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: @steam-brass-dark;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bonus spec — acid tint
|
||||||
|
.bonus-spec .confront-dice {
|
||||||
|
border-color: @steam-acid;
|
||||||
|
background-color: mix(@steam-parchment, @steam-acid, 88%);
|
||||||
|
box-shadow: 0 0 4px rgba(@steam-acid, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
+266
-33
@@ -46,13 +46,30 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fonts */
|
/* Fonts */
|
||||||
.sheet header.sheet-header h1 input, .window-app .window-header, #actors .directory-list, #navigation #scene-list .scene.nav-item {
|
.sheet header.sheet-header h1 input,
|
||||||
|
.window-app .window-header,
|
||||||
|
#actors .directory-list,
|
||||||
|
#navigation #scene-list .scene.nav-item {
|
||||||
font-size: 1.0rem;
|
font-size: 1.0rem;
|
||||||
} /* For title, sidebar character and scene */
|
}
|
||||||
|
|
||||||
|
/* For title, sidebar character and scene */
|
||||||
.sheet nav.sheet-tabs {
|
.sheet nav.sheet-tabs {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
} /* For nav and title */
|
}
|
||||||
.window-app input, .fvtt-ecryme .item-form, .sheet header.sheet-header .flex-group-center.flex-compteurs, .sheet header.sheet-header .flex-group-center.flex-fatigue, select, button, .item-checkbox, #sidebar, #players, #navigation #nav-toggle {
|
|
||||||
|
/* For nav and title */
|
||||||
|
.window-app input,
|
||||||
|
.application input,
|
||||||
|
.fvtt-ecryme .item-form,
|
||||||
|
.sheet header.sheet-header .flex-group-center.flex-compteurs,
|
||||||
|
.sheet header.sheet-header .flex-group-center.flex-fatigue,
|
||||||
|
select,
|
||||||
|
button,
|
||||||
|
.item-checkbox,
|
||||||
|
#sidebar,
|
||||||
|
#players,
|
||||||
|
#navigation #nav-toggle {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,19 +77,25 @@
|
|||||||
background: rgba(0, 0, 0, 0.75);
|
background: rgba(0, 0, 0, 0.75);
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-app.sheet .window-content {
|
.window-app.sheet .window-content,
|
||||||
|
.application.sheet .window-content {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
overflow: hidden auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.strong-text {
|
.strong-text {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs .item.active, .blessures-list li ul li:first-child:hover, a:hover {
|
.tabs .item.active,
|
||||||
|
.blessures-list li ul li:first-child:hover,
|
||||||
|
a:hover {
|
||||||
text-shadow: 1px 0px 0px #ff6600;
|
text-shadow: 1px 0px 0px #ff6600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rollable:hover, .rollable:focus {
|
.rollable:hover,
|
||||||
|
.rollable:focus {
|
||||||
color: #000;
|
color: #000;
|
||||||
text-shadow: 0 0 10px red;
|
text-shadow: 0 0 10px red;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -86,12 +109,17 @@ input:hover {
|
|||||||
input:disabled {
|
input:disabled {
|
||||||
color: #1c2058;
|
color: #1c2058;
|
||||||
}
|
}
|
||||||
|
|
||||||
select:disabled {
|
select:disabled {
|
||||||
color: #1c2058;
|
color: #1c2058;
|
||||||
}
|
}
|
||||||
table {border: 1px solid #7a7971;}
|
|
||||||
|
|
||||||
.grid, .grid-2col {
|
table {
|
||||||
|
border: 1px solid #7a7971;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid,
|
||||||
|
.grid-2col {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-column: span 2 / span 2;
|
grid-column: span 2 / span 2;
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
@@ -212,6 +240,7 @@ table {border: 1px solid #7a7971;}
|
|||||||
object-position: 50% 0;
|
object-position: 50% 0;
|
||||||
border-width: 0px;
|
border-width: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-img-container {
|
.profile-img-container {
|
||||||
margin-right: 0.2rem;
|
margin-right: 0.2rem;
|
||||||
max-width: 140px;
|
max-width: 140px;
|
||||||
@@ -370,13 +399,16 @@ li.folder > .folder-header h3 {
|
|||||||
|
|
||||||
/* ======================================== */
|
/* ======================================== */
|
||||||
/* Sheet */
|
/* Sheet */
|
||||||
.window-app.sheet .window-content .sheet-header{
|
.window-app.sheet .window-content .sheet-header,
|
||||||
|
.application.sheet .window-content .sheet-header {
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
background: url("../images/ui/fond_carnet_01.webp");
|
background: url("../images/ui/fond_carnet_01.webp");
|
||||||
/*background: #494e6b;*/
|
/*background: #494e6b;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"], select[type="text"] {
|
input[type="text"],
|
||||||
|
input[type="number"],
|
||||||
|
select[type="text"] {
|
||||||
background: white;
|
background: white;
|
||||||
color: #494e6b;
|
color: #494e6b;
|
||||||
}
|
}
|
||||||
@@ -385,14 +417,31 @@ select {
|
|||||||
background: white;
|
background: white;
|
||||||
color: #494e6b;
|
color: #494e6b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* background: #011d33 url("../images/ui/fond1.webp") repeat left top;*/
|
/* background: #011d33 url("../images/ui/fond1.webp") repeat left top;*/
|
||||||
/*color: rgba(168, 139, 139, 0.5);*/
|
/*color: rgba(168, 139, 139, 0.5);*/
|
||||||
.window-app.sheet .window-content .sheet-header select[type="text"], .window-app.sheet .window-content .sheet-header input[type="text"], .window-app.sheet .window-content .sheet-header input[type="number"], .window-app.sheet .window-content .sheet-body input[type="text"], .window-app.sheet .window-content .sheet-body input[type="number"], .window-app.sheet .window-content .sheet-body select[type="text"] {
|
.window-app.sheet .window-content .sheet-header select[type="text"],
|
||||||
|
.window-app.sheet .window-content .sheet-header input[type="text"],
|
||||||
|
.window-app.sheet .window-content .sheet-header input[type="number"],
|
||||||
|
.window-app.sheet .window-content .sheet-body input[type="text"],
|
||||||
|
.window-app.sheet .window-content .sheet-body input[type="number"],
|
||||||
|
.window-app.sheet .window-content .sheet-body select[type="text"],
|
||||||
|
.application.sheet .window-content .sheet-header select[type="text"],
|
||||||
|
.application.sheet .window-content .sheet-header input[type="text"],
|
||||||
|
.application.sheet .window-content .sheet-header input[type="number"],
|
||||||
|
.application.sheet .window-content .sheet-body input[type="text"],
|
||||||
|
.application.sheet .window-content .sheet-body input[type="number"],
|
||||||
|
.application.sheet .window-content .sheet-body select[type="text"] {
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
/*color: #494e6b;*/
|
/*color: #494e6b;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-app.sheet .window-content .sheet-header input[type="password"], .window-app.sheet .window-content .sheet-header input[type="date"], .window-app.sheet .window-content .sheet-header input[type="time"] {
|
.window-app.sheet .window-content .sheet-header input[type="password"],
|
||||||
|
.window-app.sheet .window-content .sheet-header input[type="date"],
|
||||||
|
.window-app.sheet .window-content .sheet-header input[type="time"],
|
||||||
|
.application.sheet .window-content .sheet-header input[type="password"],
|
||||||
|
.application.sheet .window-content .sheet-header input[type="date"],
|
||||||
|
.application.sheet .window-content .sheet-header input[type="time"] {
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
background: url("../images/ui/fond_carnet_01.webp");
|
background: url("../images/ui/fond_carnet_01.webp");
|
||||||
border: 1 none;
|
border: 1 none;
|
||||||
@@ -400,7 +449,12 @@ select {
|
|||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-app.sheet .window-content .sheet-body input[type="password"], .window-app.sheet .window-content .sheet-body input[type="date"], .window-app.sheet .window-content .sheet-body input[type="time"] {
|
.window-app.sheet .window-content .sheet-body input[type="password"],
|
||||||
|
.window-app.sheet .window-content .sheet-body input[type="date"],
|
||||||
|
.window-app.sheet .window-content .sheet-body input[type="time"],
|
||||||
|
.application.sheet .window-content .sheet-body input[type="password"],
|
||||||
|
.application.sheet .window-content .sheet-body input[type="date"],
|
||||||
|
.application.sheet .window-content .sheet-body input[type="time"] {
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
background: url("../images/ui/fond_carnet_01.webp");
|
background: url("../images/ui/fond_carnet_01.webp");
|
||||||
border: 1 none;
|
border: 1 none;
|
||||||
@@ -408,7 +462,10 @@ select {
|
|||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-app.sheet .window-content .sheet-body select, .window-app.sheet .window-content .sheet-header select {
|
.window-app.sheet .window-content .sheet-body select,
|
||||||
|
.window-app.sheet .window-content .sheet-header select,
|
||||||
|
.application.sheet .window-content .sheet-body select,
|
||||||
|
.application.sheet .window-content .sheet-header select {
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1 none;
|
border: 1 none;
|
||||||
@@ -416,7 +473,10 @@ select {
|
|||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-app .window-content, .window-app.sheet .window-content .sheet-body{
|
.window-app .window-content,
|
||||||
|
.window-app.sheet .window-content .sheet-body,
|
||||||
|
.application .window-content,
|
||||||
|
.application.sheet .window-content .sheet-body {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
/*background: url("../images/ui/pc_sheet_bg.webp") repeat left top;*/
|
/*background: url("../images/ui/pc_sheet_bg.webp") repeat left top;*/
|
||||||
background: url("../images/ui/fond_carnet_01.webp");
|
background: url("../images/ui/fond_carnet_01.webp");
|
||||||
@@ -425,7 +485,9 @@ select {
|
|||||||
|
|
||||||
/* background: rgba(245,245,240,0.6) url("../images/ui/sheet_background.webp") left top;*/
|
/* background: rgba(245,245,240,0.6) url("../images/ui/sheet_background.webp") left top;*/
|
||||||
|
|
||||||
section.sheet-body{padding: 0.25rem 0.5rem;}
|
section.sheet-body {
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.sheet header.sheet-header .profile-img {
|
.sheet header.sheet-header .profile-img {
|
||||||
-o-object-fit: cover;
|
-o-object-fit: cover;
|
||||||
@@ -481,8 +543,13 @@ section.sheet-body:after {
|
|||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sheet header.sheet-header .flex-compteurs {text-align: right;}
|
.sheet header.sheet-header .flex-compteurs {
|
||||||
.sheet header.sheet-header .resource-content {width: 2rem;}
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet header.sheet-header .resource-content {
|
||||||
|
width: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.select-diff {
|
.select-diff {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -497,7 +564,8 @@ section.sheet-body:after {
|
|||||||
padding: 0.25rem;
|
padding: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-app.sheet .window-content .carac-value, .window-app.sheet .window-content .competence-xp {
|
.window-app.sheet .window-content .carac-value,
|
||||||
|
.window-app.sheet .window-content .competence-xp {
|
||||||
margin: 0.05rem;
|
margin: 0.05rem;
|
||||||
flex-basis: 3rem;
|
flex-basis: 3rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -508,15 +576,21 @@ section.sheet-body:after {
|
|||||||
|
|
||||||
/* ======================================== */
|
/* ======================================== */
|
||||||
|
|
||||||
h1, h2, h3, h4 {
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4 {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul, ol {
|
ul,
|
||||||
|
ol {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
ul, li {
|
|
||||||
|
ul,
|
||||||
|
li {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,6 +598,7 @@ ul, li {
|
|||||||
margin: 0.010rem;
|
margin: 0.010rem;
|
||||||
padding: 0.25rem;
|
padding: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-fields li {
|
.header-fields li {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -532,9 +607,11 @@ ul, li {
|
|||||||
.alterne-list>.list-item:hover {
|
.alterne-list>.list-item:hover {
|
||||||
background: rgba(100, 100, 50, 0.25);
|
background: rgba(100, 100, 50, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.alterne-list>.list-item:nth-child(even) {
|
.alterne-list>.list-item:nth-child(even) {
|
||||||
background: rgba(80, 60, 0, 0.10);
|
background: rgba(80, 60, 0, 0.10);
|
||||||
}
|
}
|
||||||
|
|
||||||
.alterne-list>.list-item:nth-child(odd) {
|
.alterne-list>.list-item:nth-child(odd) {
|
||||||
background: rgb(160, 130, 100, 0.05);
|
background: rgb(160, 130, 100, 0.05);
|
||||||
}
|
}
|
||||||
@@ -557,36 +634,45 @@ ul, li {
|
|||||||
display: flex !important;
|
display: flex !important;
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item-shadow {
|
.list-item-shadow {
|
||||||
background: rgba(87, 60, 32, 0.35);
|
background: rgba(87, 60, 32, 0.35);
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item-shadow2 {
|
.list-item-shadow2 {
|
||||||
background: rgba(87, 60, 32, 0.25);
|
background: rgba(87, 60, 32, 0.25);
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-display-show {
|
.item-display-show {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-display-hide {
|
.item-display-hide {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-quantite {
|
.item-quantite {
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item-margin1 {
|
.list-item-margin1 {
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item-margin2 {
|
.list-item-margin2 {
|
||||||
margin-left: 2rem;
|
margin-left: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item-margin3 {
|
.list-item-margin3 {
|
||||||
margin-left: 3rem;
|
margin-left: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item-margin4 {
|
.list-item-margin4 {
|
||||||
margin-left: 4rem;
|
margin-left: 4rem;
|
||||||
}
|
}
|
||||||
@@ -599,6 +685,7 @@ ul, li {
|
|||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
margin-right: 0.25rem;
|
margin-right: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.competence-column {
|
.competence-column {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
@@ -606,6 +693,7 @@ ul, li {
|
|||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
flex-basis: 1;
|
flex-basis: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.competence-header {
|
.competence-header {
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
@@ -617,16 +705,20 @@ ul, li {
|
|||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-header-label {
|
.status-header-label {
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.roll-dialog-label {
|
.roll-dialog-label {
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
min-width: 96px;
|
min-width: 96px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.short-label {
|
.short-label {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.keyword-label {
|
.keyword-label {
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
@@ -651,6 +743,7 @@ ul, li {
|
|||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sante-value,
|
.sante-value,
|
||||||
.competence-value {
|
.competence-value {
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
@@ -658,26 +751,32 @@ ul, li {
|
|||||||
margin-right: 0.25rem;
|
margin-right: 0.25rem;
|
||||||
margin-left: 0.25rem;
|
margin-left: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.description-value {
|
.description-value {
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
flex-basis: 4rem;
|
flex-basis: 4rem;
|
||||||
margin-right: 0.25rem;
|
margin-right: 0.25rem;
|
||||||
margin-left: 0.25rem;
|
margin-left: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.small-label {
|
.small-label {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.padd-right {
|
.padd-right {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.padd-left {
|
.padd-left {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stack-left {
|
.stack-left {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.packed-left {
|
.packed-left {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
@@ -703,6 +802,7 @@ ul, li {
|
|||||||
flex: 0 !important;
|
flex: 0 !important;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tokenhudext.left {
|
.tokenhudext.left {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -710,6 +810,7 @@ ul, li {
|
|||||||
top: 2.75rem;
|
top: 2.75rem;
|
||||||
right: 4rem;
|
right: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tokenhudext.right {
|
.tokenhudext.right {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -717,6 +818,7 @@ ul, li {
|
|||||||
top: 2.75rem;
|
top: 2.75rem;
|
||||||
left: 4rem;
|
left: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-icon.tokenhudicon {
|
.control-icon.tokenhudicon {
|
||||||
width: -moz-fit-content;
|
width: -moz-fit-content;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
@@ -728,12 +830,15 @@ ul, li {
|
|||||||
line-height: 1rem;
|
line-height: 1rem;
|
||||||
margin: 0.25rem;
|
margin: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-icon.tokenhudicon.right {
|
.control-icon.tokenhudicon.right {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#token-hud .status-effects.active {
|
#token-hud .status-effects.active {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.token-sheet .window-content .flexcol .sheet-tabs {
|
.token-sheet .window-content .flexcol .sheet-tabs {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
}
|
}
|
||||||
@@ -757,6 +862,7 @@ ul, li {
|
|||||||
.skill-label {
|
.skill-label {
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.skill-good-checkbox {
|
.skill-good-checkbox {
|
||||||
max-height: 10px;
|
max-height: 10px;
|
||||||
max-width: 10px;
|
max-width: 10px;
|
||||||
@@ -784,7 +890,8 @@ ul, li {
|
|||||||
height: 470px !important;
|
height: 470px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar-tabs > .collapsed, #chat-controls .chat-control-icon {
|
#sidebar-tabs>.collapsed,
|
||||||
|
#chat-controls .chat-control-icon {
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.75);
|
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.75);
|
||||||
}
|
}
|
||||||
@@ -799,6 +906,7 @@ ul, li {
|
|||||||
background: rgba(0, 0, 0, 0.05);
|
background: rgba(0, 0, 0, 0.05);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-message-header {
|
.chat-message-header {
|
||||||
background: rgba(220, 220, 210, 0.5);
|
background: rgba(220, 220, 210, 0.5);
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
@@ -809,9 +917,22 @@ ul, li {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-message .message-header .flavor-text, .chat-message .message-header .whisper-to {
|
.message-chat-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-message-h3 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
color: darkred;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message .message-header .flavor-text,
|
||||||
|
.chat-message .message-header .whisper-to {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-result-text,
|
.chat-result-text,
|
||||||
.chat-actor-name {
|
.chat-actor-name {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -819,12 +940,15 @@ ul, li {
|
|||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-result-success {
|
.chat-result-success {
|
||||||
color: darkgreen;
|
color: darkgreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-result-failure {
|
.chat-result-failure {
|
||||||
color: darkred;
|
color: darkred;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-img {
|
.chat-img {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
@@ -902,6 +1026,7 @@ ul, li {
|
|||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.small-ability-icon {
|
.small-ability-icon {
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 2px 2px 2px 2px;
|
padding: 2px 2px 2px 2px;
|
||||||
@@ -910,6 +1035,7 @@ ul, li {
|
|||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combat-icon {
|
.combat-icon {
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 2px 2px 2px 2px;
|
padding: 2px 2px 2px 2px;
|
||||||
@@ -944,7 +1070,8 @@ ul, li {
|
|||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
/* Control, Tool, hotbar & navigation */
|
/* Control, Tool, hotbar & navigation */
|
||||||
|
|
||||||
#controls .scene-control, #controls .control-tool {
|
#controls .scene-control,
|
||||||
|
#controls .control-tool {
|
||||||
box-shadow: 0 0 3px #000;
|
box-shadow: 0 0 3px #000;
|
||||||
margin: 0 0 8px;
|
margin: 0 0 8px;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
@@ -956,7 +1083,10 @@ ul, li {
|
|||||||
border-image-outset: 0px;
|
border-image-outset: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#controls .scene-control.active, #controls .control-tool.active, #controls .scene-control:hover, #controls .control-tool:hover {
|
#controls .scene-control.active,
|
||||||
|
#controls .control-tool.active,
|
||||||
|
#controls .scene-control:hover,
|
||||||
|
#controls .control-tool:hover {
|
||||||
background: rgba(72, 46, 28, 1);
|
background: rgba(72, 46, 28, 1);
|
||||||
background-origin: padding-box;
|
background-origin: padding-box;
|
||||||
-o-border-image: url(img/ui/footer-button.png) 10 repeat;
|
-o-border-image: url(img/ui/footer-button.png) 10 repeat;
|
||||||
@@ -1006,7 +1136,8 @@ ul, li {
|
|||||||
border-image-outset: 0px;
|
border-image-outset: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#navigation #scene-list .scene.view, #navigation #scene-list .scene.context {
|
#navigation #scene-list .scene.view,
|
||||||
|
#navigation #scene-list .scene.context {
|
||||||
background: rgba(72, 46, 28, 1);
|
background: rgba(72, 46, 28, 1);
|
||||||
background-origin: padding-box;
|
background-origin: padding-box;
|
||||||
-o-border-image: url(img/ui/footer-button.png) 10 repeat;
|
-o-border-image: url(img/ui/footer-button.png) 10 repeat;
|
||||||
@@ -1053,7 +1184,8 @@ ul, li {
|
|||||||
|
|
||||||
|
|
||||||
.tooltip-nobottom {
|
.tooltip-nobottom {
|
||||||
border-bottom: unset; /* If you want dots under the hoverable text */
|
border-bottom: unset;
|
||||||
|
/* If you want dots under the hoverable text */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show the tooltip text when you mouse over the tooltip container */
|
/* Show the tooltip text when you mouse over the tooltip container */
|
||||||
@@ -1083,6 +1215,7 @@ ul, li {
|
|||||||
background: linear-gradient(to bottom, #800000 5%, #3e0101 100%);
|
background: linear-gradient(to bottom, #800000 5%, #3e0101 100%);
|
||||||
background-color: red;
|
background-color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-card-button:active {
|
.chat-card-button:active {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
@@ -1128,14 +1261,14 @@ ul, li {
|
|||||||
|
|
||||||
|
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
#pause
|
#pause {
|
||||||
{
|
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
#pause > h3
|
|
||||||
{
|
#pause>h3 {
|
||||||
color: #CCC
|
color: #CCC
|
||||||
}
|
}
|
||||||
|
|
||||||
#pause>img {
|
#pause>img {
|
||||||
content: url(../images/ui/ecryme_logo_small_01.webp);
|
content: url(../images/ui/ecryme_logo_small_01.webp);
|
||||||
height: 200px;
|
height: 200px;
|
||||||
@@ -1166,23 +1299,28 @@ ul, li {
|
|||||||
.status-small-label {
|
.status-small-label {
|
||||||
font-size: 0.65rem;
|
font-size: 0.65rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-grow {
|
.no-grow {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 32px;
|
max-width: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-col-name {
|
.status-col-name {
|
||||||
max-width: 72px;
|
max-width: 72px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img-no-border {
|
.img-no-border {
|
||||||
max-width: 48px;
|
max-width: 48px;
|
||||||
max-height: 48px;
|
max-height: 48px;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.items-title-bg {
|
.items-title-bg {
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
color: rgba(19, 18, 18, 0.95);
|
color: rgba(19, 18, 18, 0.95);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.impact-box {
|
.impact-box {
|
||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
border-color: #000000;
|
border-color: #000000;
|
||||||
@@ -1191,6 +1329,7 @@ ul, li {
|
|||||||
margin: 4px;
|
margin: 4px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.impact-title {
|
.impact-title {
|
||||||
font-size: bold;
|
font-size: bold;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1206,140 +1345,169 @@ ul, li {
|
|||||||
font-family: MailartRubberstamp;
|
font-family: MailartRubberstamp;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lock-icon {
|
.lock-icon {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-sheet-img {
|
.item-sheet-img {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: auto;
|
height: auto;
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-img {
|
.item-name-img {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 2rem;
|
max-width: 2rem;
|
||||||
min-width: 2rem;
|
min-width: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-header {
|
.item-name-label-header {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 12rem;
|
max-width: 12rem;
|
||||||
min-width: 12rem;
|
min-width: 12rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-header-long {
|
.item-name-label-header-long {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 14rem;
|
max-width: 14rem;
|
||||||
min-width: 14rem;
|
min-width: 14rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-header-long2 {
|
.item-name-label-header-long2 {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 24rem;
|
max-width: 24rem;
|
||||||
min-width: 24rem;
|
min-width: 24rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label {
|
.item-name-label {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 10rem;
|
max-width: 10rem;
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-long {
|
.item-name-label-long {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 12rem;
|
max-width: 12rem;
|
||||||
min-width: 12rem;
|
min-width: 12rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-short {
|
.item-name-label-short {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 4rem;
|
max-width: 4rem;
|
||||||
min-width: 4rem;
|
min-width: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-medium {
|
.item-name-label-medium {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 6rem;
|
max-width: 6rem;
|
||||||
min-width: 6rem;
|
min-width: 6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-medium2 {
|
.item-name-label-medium2 {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
max-width: 10rem;
|
max-width: 10rem;
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-free {
|
.item-name-label-free {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-long2 {
|
.item-name-label-long2 {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 22rem;
|
max-width: 22rem;
|
||||||
min-width: 22rem;
|
min-width: 22rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name-label-level2 {
|
.item-name-label-level2 {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
max-width: 9rem;
|
max-width: 9rem;
|
||||||
min-width: 9rem;
|
min-width: 9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-field-label-short {
|
.item-field-label-short {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 4rem;
|
max-width: 4rem;
|
||||||
min-width: 4rem;
|
min-width: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-field-label-short-header {
|
.item-field-label-short-header {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 2.2rem;
|
max-width: 2.2rem;
|
||||||
min-width: 2.2rem;
|
min-width: 2.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-field-label-medium {
|
.item-field-label-medium {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 6rem;
|
max-width: 6rem;
|
||||||
min-width: 6rem;
|
min-width: 6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-field-skill {
|
.item-field-skill {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 6.8rem;
|
max-width: 6.8rem;
|
||||||
min-width: 6.8rem;
|
min-width: 6.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-field-label-long {
|
.item-field-label-long {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 10rem;
|
max-width: 10rem;
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-control-end {
|
.item-control-end {
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alternate-list {
|
.alternate-list {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-filler {
|
.item-filler {
|
||||||
flex-grow: 6;
|
flex-grow: 6;
|
||||||
flex-shrink: 7;
|
flex-shrink: 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-controls-fixed {
|
.item-controls-fixed {
|
||||||
min-width: 2rem;
|
min-width: 2rem;
|
||||||
max-width: 2rem;
|
max-width: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-controls-fixed-full {
|
.item-controls-fixed-full {
|
||||||
min-width: 3rem;
|
min-width: 3rem;
|
||||||
max-width: 3rem;
|
max-width: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attribute-label {
|
.attribute-label {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flexrow-no-expand {
|
.flexrow-no-expand {
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flexrow-start {
|
.flexrow-start {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-input-small {
|
.item-input-small {
|
||||||
max-width: 16px;
|
max-width: 16px;
|
||||||
max-height: 12px;
|
max-height: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.character-summary-rollable {
|
.character-summary-rollable {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
@@ -1347,6 +1515,7 @@ ul, li {
|
|||||||
.ecryme-roll-dialog .window-header {
|
.ecryme-roll-dialog .window-header {
|
||||||
border-radius: 10px 10px 0% 0%;
|
border-radius: 10px 10px 0% 0%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ecryme-roll-dialog .window-content {
|
.ecryme-roll-dialog .window-content {
|
||||||
border-radius: 0% 0% 10px 10px;
|
border-radius: 0% 0% 10px 10px;
|
||||||
}
|
}
|
||||||
@@ -1363,16 +1532,19 @@ ul, li {
|
|||||||
.bonus-spec {
|
.bonus-spec {
|
||||||
max-width: 48px;
|
max-width: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confront-bonus-container {
|
.confront-bonus-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pool-list {
|
.pool-list {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confront-bonus-centered {
|
.confront-bonus-centered {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@@ -1386,12 +1558,14 @@ ul, li {
|
|||||||
.dice-spec {
|
.dice-spec {
|
||||||
max-width: 64px;
|
max-width: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confront-dice-container {
|
.confront-dice-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confront-dice-centered {
|
.confront-dice-centered {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@@ -1401,6 +1575,7 @@ ul, li {
|
|||||||
font-family: MailartRubberstamp;
|
font-family: MailartRubberstamp;
|
||||||
transform: translate(-50%, -55%);
|
transform: translate(-50%, -55%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.confront-area {
|
.confront-area {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
@@ -1412,3 +1587,61 @@ ul, li {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==============================
|
||||||
|
Application V2 Item Sheets
|
||||||
|
============================== */
|
||||||
|
|
||||||
|
/* Compact header for item sheets (smaller than actor sheets) */
|
||||||
|
.fvtt-ecryme.item .sheet-header {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-height: 70px;
|
||||||
|
padding: 4px 6px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fvtt-ecryme.item .sheet-header .item-sheet-img {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
object-fit: contain;
|
||||||
|
border: 1px solid #7a7971;
|
||||||
|
cursor: pointer;
|
||||||
|
flex: 0 0 64px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fvtt-ecryme.item .sheet-header .header-fields {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fvtt-ecryme.item .sheet-header h1.charname {
|
||||||
|
height: auto;
|
||||||
|
margin: 0;
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fvtt-ecryme.item .sheet-header h1.charname input {
|
||||||
|
font-family: MailartRubberstamp;
|
||||||
|
font-size: 1.8rem;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Active tab styling for AppV2 (uses <a> without .item class) */
|
||||||
|
.fvtt-ecryme.item nav.sheet-tabs a.active {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Details tab content */
|
||||||
|
.fvtt-ecryme.item .sheet-body ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 4px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fvtt-ecryme.item .sheet-body ul li.flexrow {
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// ============================================================
|
||||||
|
// Ecryme — Main LESS entry point
|
||||||
|
// Compiled output: css/ecryme.css
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
@import "_variables.less";
|
||||||
|
@import "fonts.less";
|
||||||
|
@import "global.less";
|
||||||
|
@import "sheet.less";
|
||||||
|
@import "actor-sheet.less";
|
||||||
|
@import "actor-sheet-v2.less";
|
||||||
|
@import "item-sheet.less";
|
||||||
|
@import "ui.less";
|
||||||
|
@import "sidebar.less";
|
||||||
|
@import "chat.less";
|
||||||
|
@import "chat-steampunk.less";
|
||||||
|
@import "dialog-steampunk.less";
|
||||||
|
@import "actor-sheet-steampunk.less";
|
||||||
|
@import "item-sheet-steampunk.less";
|
||||||
|
@import "hud.less";
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// ============================================================
|
||||||
|
// Fonts
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "MailartRubberstamp";
|
||||||
|
src: url('../fonts/MailartRubberstamp-Regular.woff') format("woff");
|
||||||
|
}
|
||||||
@@ -0,0 +1,178 @@
|
|||||||
|
// ============================================================
|
||||||
|
// Global base styles
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
:root {
|
||||||
|
// Actor sheet font styles
|
||||||
|
--window-header-title-font-size: 1.3rem;
|
||||||
|
--window-header-title-font-weight: normal;
|
||||||
|
--window-header-title-color: #f5f5f5;
|
||||||
|
|
||||||
|
--major-button-font-size: 1.05rem;
|
||||||
|
--major-button-font-weight: normal;
|
||||||
|
--major-button-color: #dadada;
|
||||||
|
|
||||||
|
--tab-header-font-size: 1.0rem;
|
||||||
|
--tab-header-font-weight: 700;
|
||||||
|
--tab-header-color: #403f3e;
|
||||||
|
--tab-header-color-active: #4a0404;
|
||||||
|
|
||||||
|
--actor-input-font-size: 0.8rem;
|
||||||
|
--actor-input-font-weight: 500;
|
||||||
|
--actor-input-color: black;
|
||||||
|
|
||||||
|
--actor-label-font-size: 0.8rem;
|
||||||
|
--actor-label-font-weight: 700;
|
||||||
|
--actor-label-color: rgba(70, 67, 49, 0.76863);
|
||||||
|
|
||||||
|
// Debugging highlighters
|
||||||
|
--debug-background-color-red: rgba(255, 0, 0, 0.32941);
|
||||||
|
--debug-background-color-blue: rgba(29, 0, 255, 0.32941);
|
||||||
|
--debug-background-color-green: rgba(84, 255, 0, 0.32941);
|
||||||
|
|
||||||
|
--debug-box-shadow-red: inset 0 0 2px red;
|
||||||
|
--debug-box-shadow-blue: inset 0 0 2px blue;
|
||||||
|
--debug-box-shadow-green: inset 0 0 2px green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-app {
|
||||||
|
text-align: justify;
|
||||||
|
font-size: 16px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fonts: title, sidebar, scene nav
|
||||||
|
.sheet header.sheet-header h1 input,
|
||||||
|
.window-app .window-header,
|
||||||
|
#actors .directory-list,
|
||||||
|
#navigation #scene-list .scene.nav-item {
|
||||||
|
font-size: 1.0rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nav and title
|
||||||
|
.sheet nav.sheet-tabs {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inputs, buttons, sidebar, navigation
|
||||||
|
.window-app input,
|
||||||
|
.application input,
|
||||||
|
.fvtt-ecryme .item-form,
|
||||||
|
.sheet header.sheet-header .flex-group-center.flex-compteurs,
|
||||||
|
.sheet header.sheet-header .flex-group-center.flex-fatigue,
|
||||||
|
select,
|
||||||
|
button,
|
||||||
|
.item-checkbox,
|
||||||
|
#sidebar,
|
||||||
|
#players,
|
||||||
|
#navigation #nav-toggle {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-header {
|
||||||
|
background: rgba(0, 0, 0, 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fvtt-ecryme .window-content {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.strong-text {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs .item.active,
|
||||||
|
.blessures-list li ul li:first-child:hover,
|
||||||
|
a:hover {
|
||||||
|
text-shadow: 1px 0px 0px @color-accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rollable {
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
color: #000;
|
||||||
|
text-shadow: 0 0 10px red;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
&:hover {
|
||||||
|
border-width: 4px;
|
||||||
|
border-color: rgba(37, 124, 37, 0.7);
|
||||||
|
}
|
||||||
|
&:disabled {
|
||||||
|
color: @color-text-disabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select:disabled {
|
||||||
|
color: @color-text-disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border: 1px solid #7a7971;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grid utilities
|
||||||
|
.grid,
|
||||||
|
.grid-2col {
|
||||||
|
display: grid;
|
||||||
|
grid-column: span 2 / span 2;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
grid-gap: 10px;
|
||||||
|
gap: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-3col { grid-column: span 3 / span 3; grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||||
|
.grid-4col { grid-column: span 4 / span 4; grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
||||||
|
.grid-5col { grid-column: span 5 / span 5; grid-template-columns: repeat(5, minmax(0, 1fr)); }
|
||||||
|
.grid-6col { grid-column: span 5 / span 5; grid-template-columns: repeat(5, minmax(0, 1fr)); }
|
||||||
|
.grid-7col { grid-column: span 7 / span 7; grid-template-columns: repeat(7, minmax(0, 1fr)); }
|
||||||
|
.grid-8col { grid-column: span 8 / span 8; grid-template-columns: repeat(8, minmax(0, 1fr)); }
|
||||||
|
.grid-9col { grid-column: span 9 / span 9; grid-template-columns: repeat(9, minmax(0, 1fr)); }
|
||||||
|
.grid-10col { grid-column: span 10 / span 10; grid-template-columns: repeat(10, minmax(0, 1fr)); }
|
||||||
|
.grid-11col { grid-column: span 11 / span 11; grid-template-columns: repeat(11, minmax(0, 1fr)); }
|
||||||
|
.grid-12col { grid-column: span 12 / span 12; grid-template-columns: repeat(12, minmax(0, 1fr)); }
|
||||||
|
|
||||||
|
// Flex utilities
|
||||||
|
.flex-group-center,
|
||||||
|
.flex-group-left,
|
||||||
|
.flex-group-right {
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-group-left {
|
||||||
|
justify-content: flex-start;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-group-right {
|
||||||
|
justify-content: flex-end;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-center {
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-create-actor {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-shrink {
|
||||||
|
flex: 'flex-shrink';
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
// ============================================================
|
||||||
|
// HUD, token, pause, logo
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
// Token HUD extension
|
||||||
|
.tokenhudext {
|
||||||
|
display: flex;
|
||||||
|
flex: 0 !important;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
&.left {
|
||||||
|
justify-content: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
position: absolute;
|
||||||
|
top: 2.75rem;
|
||||||
|
right: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
justify-content: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
position: absolute;
|
||||||
|
top: 2.75rem;
|
||||||
|
left: 4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-icon.tokenhudicon {
|
||||||
|
width: fit-content;
|
||||||
|
height: fit-content;
|
||||||
|
min-width: 6rem;
|
||||||
|
flex-basis: auto;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1rem;
|
||||||
|
margin: 0.25rem;
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#token-hud .status-effects.active {
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token-sheet .window-content .flexcol .sheet-tabs {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pause screen
|
||||||
|
#pause {
|
||||||
|
font-size: 2rem;
|
||||||
|
|
||||||
|
> h3 { color: #CCC; }
|
||||||
|
|
||||||
|
> img {
|
||||||
|
content: @logo-image;
|
||||||
|
height: 200px;
|
||||||
|
width: 200px;
|
||||||
|
top: -200px;
|
||||||
|
left: calc(50% - 132px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logo
|
||||||
|
#logo {
|
||||||
|
content: @logo-image;
|
||||||
|
width: 100px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confront dice
|
||||||
|
.confront-dice {
|
||||||
|
border-width: 0px;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user