Compare commits

...

50 Commits
12.0.1 ... main

Author SHA1 Message Date
2ac0f53c4f Add rituals and tomes 2025-02-07 08:34:57 +01:00
270471f137 Ready for next release
All checks were successful
Release Creation / build (release) Successful in 48s
2025-02-06 22:37:57 +01:00
da9d0e41a5 Fix #45 - Auto addk unarmed fight on new actor 2025-02-06 22:35:07 +01:00
42f25aa186 Fix #46 - Fix gear icon 2025-02-06 22:23:26 +01:00
5f9057db37 Fix #44 - Auto use damage bonus for melee/unarmed 2025-02-06 22:21:56 +01:00
82731c2d40 Fix #43 - Auto allocate current era 2025-02-06 21:54:59 +01:00
a75a3bf157 Fix #39 - Display cured/uncured for mental disorder 2025-02-06 21:35:22 +01:00
e6e6de35df Fix #39 - Display cured/uncured for mental disorder 2025-02-06 21:10:15 +01:00
7341580a7b Fix #38 - Auto set bond values 2025-02-06 20:55:14 +01:00
75a81e589b Sync with wfrp 4, v8.4.0
All checks were successful
Release Creation / build (release) Successful in 50s
2025-02-01 21:17:58 +01:00
74f237c30f Sync with wfrp 4, v8.4.0 2025-02-01 21:17:42 +01:00
440e5c0b66 Sync with wfrp 4, v8.4.0 2025-02-01 21:17:27 +01:00
554220a812 Sync with wfrp 4, v8.4.0
All checks were successful
Release Creation / build (release) Successful in 51s
2025-02-01 21:10:28 +01:00
e7ea8138c9 Enhance fonts/sizing/colors 2025-01-28 14:22:11 +01:00
6a18f7fa29 Additionnal cleanup 2025-01-28 07:20:29 +01:00
7070d4c1da Sync bol for module releas 2025-01-25 22:28:16 +01:00
3b79a19ca5 Sync bol for module releas
All checks were successful
Release Creation / build (release) Successful in 53s
2025-01-25 20:19:37 +01:00
f882a04c0b Auto release script
All checks were successful
Release Creation / build (release) Successful in 48s
2025-01-25 18:55:34 +01:00
eda24442e8 Auto release script 2025-01-25 18:49:18 +01:00
0ec2d53415 Auto release script
All checks were successful
Release Creation / build (release) Successful in 45s
2025-01-25 18:34:18 +01:00
401a94da40 Auto release script
Some checks failed
Release Creation / build (release) Failing after 22s
2025-01-25 18:31:03 +01:00
7758085bf8 Fix various minot stuff + add resources roll 2025-01-25 18:24:20 +01:00
70c4fd5a74 Fix #30 - Disable dual skills dop 2025-01-10 00:11:25 +01:00
03a54d86e6 Fix #28 : switch to manual BP management 2025-01-09 16:18:08 +01:00
3adb34d721 Reduce default icon size, Fix #27 2025-01-09 15:54:41 +01:00
034a60bf19 Reduce default icon size, fix #32 2025-01-09 15:48:08 +01:00
522bb08d35 Allow packs 2025-01-09 15:36:41 +01:00
c144488d1d Move packs to avoid LFS 2025-01-09 15:35:58 +01:00
704dd83b1b Move packs to avoid LFS 2025-01-09 15:35:31 +01:00
3aab98b4b4 Allow packs 2025-01-09 15:18:41 +01:00
2c05594a7e Allow packs 2025-01-09 15:18:20 +01:00
ce1844a070 Add vehicle type 2025-01-08 17:26:57 +01:00
fa7d3ecfca Add resources management 2025-01-08 12:46:36 +01:00
adb4923d00 Enhance roll result colors 2025-01-07 22:22:15 +01:00
44842ff655 Enhance roll result colors 2025-01-07 21:51:38 +01:00
4671f6f9fe Enhance roll result colors 2025-01-07 21:51:13 +01:00
50b7bafb43 Enhance roll result colors 2025-01-07 21:49:50 +01:00
2c3a92994a Fix #24 : Add SAN rolls 2025-01-07 21:38:50 +01:00
dfe4aa0c56 Add packs ! 2025-01-07 20:00:28 +01:00
efc23f466b Fix #20 : Track cured disorder 2025-01-07 19:51:49 +01:00
1b1c2b0cfd Fix #5 : Edit features + display as tooltip when hovering stats 2025-01-07 18:22:17 +01:00
e0f02ecacb Fix #9 : Visual rollable field 2025-01-07 17:57:43 +01:00
4e39c5d0dc Fix #15: Notes/Description for protagonist sheet 2025-01-07 17:44:30 +01:00
9f13961eaf Fix #17 : Motivation description 2025-01-07 17:39:12 +01:00
3d6cd35fa4 Fix #18 : Move motivations to status 2025-01-07 17:38:04 +01:00
33c11e2c05 Fix #19 : Mental disorder description 2025-01-07 17:36:31 +01:00
b600148247 Fix #22 : Bond display 2025-01-07 17:26:08 +01:00
c0d240c5d0 Fix #25 : Change color of WP warning displays 2025-01-07 17:23:25 +01:00
d6a1b2c62a Fix #1 : Drag data on stats 2025-01-07 17:17:22 +01:00
82139eb634 Fix BP computation #3 2025-01-07 17:15:45 +01:00
79 changed files with 3168 additions and 999 deletions

View File

@ -0,0 +1,52 @@
name: Release Creation
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner."
#- uses: actions/checkout@v3
- uses: RouxAntoine/checkout@v3.5.4
# get part of the tag after the `v`
- name: Extract tag version number
id: get_version
uses: battila7/get-version-action@v2
# Substitute the Manifest and Download URLs in the 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/${{gitea.repository}}
manifest: https://www.uberwald.me/gitea/public/${{gitea.repository}}/releases/download/latest/system.json
download: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-cthulhu-eternal.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-cthulhu-eternal.zip system.json README.md LICENSE assets/ css/ fonts/ lang/ module/ packs-system/ templates/ cthulhu-eternal.mjs
- 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-cthulhu-eternal.zip
system.json
api_key: '${{secrets.ALLOW_PUSH_RELEASE}}'

3
.gitignore vendored
View File

@ -6,6 +6,3 @@ styles/*.css
# Node Modules # Node Modules
node_modules/ node_modules/
# Foundry VTT
packs/*

Binary file not shown.

BIN
assets/fonts/FeFCrm2.ttf Normal file

Binary file not shown.

BIN
assets/fonts/FeGPrm2.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><filter id="shadow-1" height="300%" width="300%" x="-100%" y="-100%"><feFlood flood-color="rgba(255, 255, 255, 1)" result="flood"></feFlood><feComposite in="flood" in2="SourceGraphic" operator="atop" result="composite"></feComposite><feGaussianBlur in="composite" stdDeviation="15" result="blur"></feGaussianBlur><feOffset dx="0" dy="0" result="offset"></feOffset><feComposite in="SourceGraphic" in2="offset" operator="over"></feComposite></filter></defs><g class="" style="" transform="translate(0,0)"><path d="M227.227 21.777c-1.845 0-3.704.05-5.567.157-15.314.875-30.76 5.305-39.494 10.863l-.008 73.15c2.884-.094 5.777-.147 8.676-.142 23.382.036 47.104 3.286 68.47 9.513l.01-87.507c-7.034-3.518-19.178-6.03-32.087-6.033zm80.74 9.16c-11.925.15-23.077 2.364-29.967 5.596l-.008 77.602v7.658c38.486 15.67 64.814 42.48 58.735 78.764l-.96 5.73-5.562 1.674c-17.45 5.253-34.872 9.703-52.225 13.335V246.53c25.562-.704 51.327-2.687 77.145-6.098l.02-197.928c-8.284-5.563-23.508-10.243-38.842-11.328-2.792-.198-5.584-.273-8.336-.238zM143.223 46.294c-1.176-.015-2.374-.01-3.588.02-4.175.1-8.533.468-12.903 1.152-15.67 2.454-31.477 8.565-40.406 15.402l-.01 72.955c18.808-15.81 46.704-25.143 77.15-28.54l.007-57.966c-4.82-1.752-12.018-2.916-20.25-3.023zm258.394 3.46c-10.804.117-20.722 1.93-27.043 4.655l-.02 183.182c25.074-4.02 50.16-9.412 75.122-16.358l1.99-158.447c-8.352-5.9-23.648-11.025-39.05-12.553-3.698-.366-7.398-.517-11-.478zm-222.775 74.202c-53.72.702-101.407 20.365-97.887 66.6 15.836-3.918 30.84-5.893 44.94-6.1 34.84-.51 64.213 9.704 87.318 27.613 34.608-3.11 69.852-10 105.412-20.314.14-41.287-74.098-68.657-139.783-67.8zm-48.877 78.65c-1.296-.003-2.603.012-3.92.045-17.256.436-36.45 4.03-57.566 11.037 5.79 53.808 26.325 106.41 58.5 143.346 6.226 7.15 12.856 13.712 19.875 19.615 29.303 9.282 69.26 12.917 110.534 12.14 3.777-55.805-8.717-108.357-36.193-142.74-21.265-26.61-51.064-43.39-91.232-43.444zm129.326 22.282c-9.358 1.637-18.69 3.016-27.995 4.15 1.54 1.74 3.043 3.52 4.502 5.346 3.146 3.937 6.094 8.062 8.873 12.334 9.916.144 19.868.125 29.857-.106H259.29v-21.723zm191.817 15.343c-65.406 17.826-131.462 25.41-195.85 25.315 16.998 35.144 23.828 78.093 21.013 122.6 42.482-2.08 85.03-8.23 118.187-15.983 26.693-32.78 47.37-77.118 56.65-131.932zM400.51 389.9c-38.334 9.145-87.95 16.056-136.873 17.454-47.67 1.36-94.336-2.228-129.448-15.262l-.01 78.93c27.187 12.568 76.414 20.205 127.318 20.298 51.224.094 104.214-7.173 139-20.773l.012-80.647z" fill="#a7de9a" fill-opacity="1" filter="url(#shadow-1)"></path></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1 @@
<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><filter id="shadow-1" height="300%" width="300%" x="-100%" y="-100%"><feFlood flood-color="rgba(255, 255, 255, 1)" result="flood"></feFlood><feComposite in="flood" in2="SourceGraphic" operator="atop" result="composite"></feComposite><feGaussianBlur in="composite" stdDeviation="15" result="blur"></feGaussianBlur><feOffset dx="0" dy="0" result="offset"></feOffset><feComposite in="SourceGraphic" in2="offset" operator="over"></feComposite></filter></defs><g class="" style="" transform="translate(0,0)"><path d="M245.813 23.188c-1.228-.006-2.455.027-3.657.093-10.103.56-19.646 3.682-30.156 11.25l20.72 196.782c-8.394 2.127-16.676 4.47-24.814 7.094L137.72 57.812c-7.032-1.706-17.442-.3-27.126 4.626-10.248 5.213-19.034 13.84-22.813 22.937L155.03 261.5c-7.414 4.345-14.59 9.137-21.5 14.47l-74.343-94.25c-16.34.698-34.965 14.455-37.562 32.655C28.89 222.693 93.978 297.77 126 357.405c10.3 19.184 29.543 50.725 39.188 70.064 5.83 11.693 16.004 24.238 27.843 32.342 11.84 8.104 24.7 11.82 37.907 8.282l112.907-30.22c5.493-1.47 9.196-5.39 13.22-11.937 4.02-6.545 7.535-15.137 12.905-23 20.61-30.185 50.432-76.085 115.186-112.062-2.696-15.053-7.405-24.57-12.72-29.563-6.03-5.667-13.198-7.372-23.686-5.843-18.062 2.63-43.498 17.063-69.594 36.874-1.68 1.39-3.318 2.802-4.937 4.22l-7-61.252 42.5-155.718c-4.478-7.355-13.806-13.258-24.845-15.97-10.874-2.67-22.506-1.698-30.28 1.595l-38.75 149.874c-9.365 1.58-18.732 3.17-28.064 4.812L273.69 27.5c-10.057-2.52-19.284-4.272-27.875-4.313zM234.343 255l30.157 56.625 54.406-33.906-33.78 54.186L341.562 362l-64.157-2.188 2.188 64.032-30.03-56.344-54.283 33.813 33.97-54.438-56.53-30.125 63.78 2.156L234.344 255z" fill="#a7de9a" fill-opacity="1" filter="url(#shadow-1)"></path></g></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1 @@
<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><filter id="shadow-1" height="300%" width="300%" x="-100%" y="-100%"><feFlood flood-color="rgba(255, 255, 255, 1)" result="flood"></feFlood><feComposite in="flood" in2="SourceGraphic" operator="atop" result="composite"></feComposite><feGaussianBlur in="composite" stdDeviation="15" result="blur"></feGaussianBlur><feOffset dx="0" dy="0" result="offset"></feOffset><feComposite in="SourceGraphic" in2="offset" operator="over"></feComposite></filter></defs><g class="" style="" transform="translate(0,0)"><path d="M102.5 26.03l90.03 345.75 289.22 23.25-90.063-345.75L102.5 26.03zm-18.906 1.564c-30.466 11.873-55.68 53.098-49.75 75.312l3.25 11.78c.667-1.76 1.36-3.522 2.093-5.28C49.097 85.7 65.748 62.64 89.564 50.5l-5.97-22.906zm10.844 41.593c-16.657 10.012-29.92 28.077-38 47.407-5.247 12.55-8.038 25.63-8.75 36.53L112.5 388.407c.294-.55.572-1.106.875-1.656 10.603-19.252 27.823-37.695 51.125-48.47L94.437 69.19zm74.874 287.594c-17.677 9.078-31.145 23.717-39.562 39-4.464 8.107-7.27 16.364-8.688 23.75l11.688 42.408 1.625.125c-3.84-27.548 11.352-60.504 41.25-81.094l-6.313-24.19zm26.344 34c-32.567 17.27-46.51 52.44-41.844 72.94l289.844 24.5c-5.34-7.79-8.673-17.947-8.594-28.5l-22.406-9L459 443.436l-13.5-12.875c5.604-6.917 13.707-13.05 24.813-17.687L195.656 390.78z" fill="#a7de9a" fill-opacity="1" filter="url(#shadow-1)"></path></g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

47
assets/ui/d100.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,6 @@ import * as documents from "./module/documents/_module.mjs"
import * as applications from "./module/applications/_module.mjs" import * as applications from "./module/applications/_module.mjs"
import { handleSocketEvent } from "./module/socket.mjs" import { handleSocketEvent } from "./module/socket.mjs"
import { Macros } from "./module/macros.mjs"
import { setupTextEnrichers } from "./module/enrichers.mjs"
import CthulhuEternalUtils from "./module/utils.mjs" import CthulhuEternalUtils from "./module/utils.mjs"
export class ClassCounter{static printHello(){console.log("Hello")}static sendJsonPostRequest(e,s){const t={method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(s)};return fetch(e,t).then((e=>{if(!e.ok)throw new Error("La requête a échoué avec le statut "+e.status);return e.json()})).catch((e=>{throw console.error("Erreur envoi de la requête:",e),e}))}static registerUsageCount(e=game.system.id,s={}){if(game.user.isGM){game.settings.register(e,"world-key",{name:"Unique world key",scope:"world",config:!1,default:"",type:String});let t=game.settings.get(e,"world-key");null!=t&&""!=t&&"NONE"!=t&&"none"!=t.toLowerCase()||(t=foundry.utils.randomID(32),game.settings.set(e,"world-key",t));let a={name:e,system:game.system.id,worldKey:t,version:game.system.version,language:game.settings.get("core","language"),remoteAddr:game.data.addresses.remote,nbInstalledModules:game.modules.size,nbActiveModules:game.modules.filter((e=>e.active)).length,nbPacks:game.world.packs.size,nbUsers:game.users.size,nbScenes:game.scenes.size,nbActors:game.actors.size,nbPlaylist:game.playlists.size,nbTables:game.tables.size,nbCards:game.cards.size,optionsData:s,foundryVersion:`${game.release.generation}.${game.release.build}`};this.sendJsonPostRequest("https://www.uberwald.me/fvtt_appcount/count_post.php",a)}}} export class ClassCounter{static printHello(){console.log("Hello")}static sendJsonPostRequest(e,s){const t={method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(s)};return fetch(e,t).then((e=>{if(!e.ok)throw new Error("La requête a échoué avec le statut "+e.status);return e.json()})).catch((e=>{throw console.error("Erreur envoi de la requête:",e),e}))}static registerUsageCount(e=game.system.id,s={}){if(game.user.isGM){game.settings.register(e,"world-key",{name:"Unique world key",scope:"world",config:!1,default:"",type:String});let t=game.settings.get(e,"world-key");null!=t&&""!=t&&"NONE"!=t&&"none"!=t.toLowerCase()||(t=foundry.utils.randomID(32),game.settings.set(e,"world-key",t));let a={name:e,system:game.system.id,worldKey:t,version:game.system.version,language:game.settings.get("core","language"),remoteAddr:game.data.addresses.remote,nbInstalledModules:game.modules.size,nbActiveModules:game.modules.filter((e=>e.active)).length,nbPacks:game.world.packs.size,nbUsers:game.users.size,nbScenes:game.scenes.size,nbActors:game.actors.size,nbPlaylist:game.playlists.size,nbTables:game.tables.size,nbCards:game.cards.size,optionsData:s,foundryVersion:`${game.release.generation}.${game.release.build}`};this.sendJsonPostRequest("https://www.uberwald.me/fvtt_appcount/count_post.php",a)}}}
@ -34,7 +32,8 @@ Hooks.once("init", function () {
CONFIG.Actor.documentClass = documents.CthulhuEternalActor CONFIG.Actor.documentClass = documents.CthulhuEternalActor
CONFIG.Actor.dataModels = { CONFIG.Actor.dataModels = {
protagonist: models.CthulhuEternalProtagonist protagonist: models.CthulhuEternalProtagonist,
vehicle: models.CthulhuEternalVehicle
} }
CONFIG.Item.documentClass = documents.CthulhuEternalItem CONFIG.Item.documentClass = documents.CthulhuEternalItem
@ -48,12 +47,15 @@ Hooks.once("init", function () {
bond: models.CthulhuEternalBond, bond: models.CthulhuEternalBond,
arcane: models.CthulhuEternalArcane, arcane: models.CthulhuEternalArcane,
gear: models.CthulhuEternalGear, gear: models.CthulhuEternalGear,
archetype: models.CthulhuEternalArchetype archetype: models.CthulhuEternalArchetype,
ritual: models.CthulhuEternalRitual,
tome: models.CthulhuEternalTome
} }
// Register sheet application classes // Register sheet application classes
Actors.unregisterSheet("core", ActorSheet) Actors.unregisterSheet("core", ActorSheet)
Actors.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalProtagonistSheet, { types: ["protagonist"], makeDefault: true }) Actors.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalProtagonistSheet, { types: ["protagonist"], makeDefault: true })
Actors.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalVehicleSheet, { types: ["vehicle"], makeDefault: true })
Items.unregisterSheet("core", ItemSheet) Items.unregisterSheet("core", ItemSheet)
Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalSkillSheet, { types: ["skill"], makeDefault: true }) Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalSkillSheet, { types: ["skill"], makeDefault: true })
@ -66,6 +68,8 @@ Hooks.once("init", function () {
Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalBondSheet, { types: ["bond"], makeDefault: true }) Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalBondSheet, { types: ["bond"], makeDefault: true })
Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalGearSheet, { types: ["gear"], makeDefault: true }) Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalGearSheet, { types: ["gear"], makeDefault: true })
Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalArchetypeSheet, { types: ["archetype"], makeDefault: true }) Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalArchetypeSheet, { types: ["archetype"], makeDefault: true })
Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalRitualSheet, { types: ["ritual"], makeDefault: true })
Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalTomeSheet, { types: ["tome"], makeDefault: true })
// Other Document Configuration // Other Document Configuration
CONFIG.ChatMessage.documentClass = documents.CthulhuEternalChatMessage CONFIG.ChatMessage.documentClass = documents.CthulhuEternalChatMessage
@ -84,22 +88,10 @@ Hooks.once("init", function () {
// Activate socket handler // Activate socket handler
game.socket.on(`system.${SYSTEM.id}`, handleSocketEvent) game.socket.on(`system.${SYSTEM.id}`, handleSocketEvent)
setupTextEnrichers()
CthulhuEternalUtils.registerSettings() CthulhuEternalUtils.registerSettings()
CthulhuEternalUtils.registerHandlebarsHelpers() CthulhuEternalUtils.registerHandlebarsHelpers()
CthulhuEternalUtils.setupCSSRootVariables() CthulhuEternalUtils.setupCSSRootVariables()
// Gestion des jets de dés depuis les journaux
document.addEventListener("click", (event) => {
const anchor = event.target.closest("a.ask-roll-journal")
if (!anchor) return
event.preventDefault()
event.stopPropagation()
const type = anchor.dataset.rollType
const target = anchor.dataset.rollTarget
const title = anchor.dataset.rollTitle
})
console.info("CTHULHU ETERNAL | System Initialized") console.info("CTHULHU ETERNAL | System Initialized")
}) })
@ -118,43 +110,25 @@ function preLocalizeConfig() {
Hooks.once("ready", function () { Hooks.once("ready", function () {
console.info("CTHULHU ETERNAL | Ready") console.info("CTHULHU ETERNAL | Ready")
ClassCounter.registerUsageCount("fvtt-cthulhu-eternal", {}) if (game.user.isGM) {
_showUserGuide() ClassCounter.registerUsageCount("fvtt-cthulhu-eternal", {})
/* Display the user guide */
async function _showUserGuide() {
if (game.user.isGM) {
const newVer = game.system.version
}
} }
preLocalizeConfig()
}) })
Hooks.on("renderChatMessage", (message, html, data) => { Hooks.on("renderChatMessage", (message, html, data) => {
const typeMessage = data.message.flags.CthulhuEternal?.typeMessage // Affichage des boutons de jet de dés uniquement pour les joueurs
// Message de demande de jet de dés if (message.author.id === game.user.id) {
if (typeMessage === "askRoll") { html.find(".nudge-roll").each((i, btn) => {
// Affichage des boutons de jet de dés uniquement pour les joueurs btn.style.display = "inline"
if (game.user.isGM) { })
html.find(".ask-roll-dice").each((i, btn) => { html.find(".nudge-roll").click((event) => {
btn.style.display = "none" CthulhuEternalUtils.nudgeRoll(message)
}) })
} else {
html.find(".ask-roll-dice").click((event) => {
const btn = $(event.currentTarget)
const type = btn.data("type")
const value = btn.data("value")
const avantage = btn.data("avantage") ?? "="
const character = game.user.character
if (type === SYSTEM.ROLL_TYPE.RESOURCE) character.rollResource(value)
else if (type === SYSTEM.ROLL_TYPE.SAVE) character.rollSave(value, avantage)
})
}
} }
}) })
Hooks.on("updateSetting", async (setting, update, options, id) => {
})
// Dice-so-nice Ready // Dice-so-nice Ready
Hooks.once("diceSoNiceReady", (dice3d) => { Hooks.once("diceSoNiceReady", (dice3d) => {
configureDiceSoNice(dice3d) configureDiceSoNice(dice3d)
@ -167,18 +141,8 @@ Hooks.once("diceSoNiceReady", (dice3d) => {
* Journal - open journal sheet * Journal - open journal sheet
*/ */
Hooks.on("hotbarDrop", (bar, data, slot) => { Hooks.on("hotbarDrop", (bar, data, slot) => {
if (["Actor", "Item", "JournalEntry", "roll", "rollDamage", "rollAttack"].includes(data.type)) { if (["Actor", "Item", "JournalEntry", "skill", "weapon"].includes(data.type)) {
Macros.createCthulhuEternalMacro(data, slot); // TODO -> Manage this
return false return false
} }
}) })
/**
* Register world usage statistics
* @param {string} registerKey
*/
function registerWorldCount(registerKey) {
if (game.user.isGM) {
ClassCounter.registerUsageCount(game.system.id, {})
}
}

View File

@ -1,12 +1,17 @@
const gulp = require('gulp'); const gulp = require('gulp');
const less = require('gulp-less'); const less = require('gulp-less');
function onError(err) {
util.log(util.colors.red.bold('[ERROR LESS]:'),util.colors.bgRed(err.message));
this.emit('end');
};
/* ----------------------------------------- */ /* ----------------------------------------- */
/* Compile LESS /* Compile LESS
/* ----------------------------------------- */ /* ----------------------------------------- */
function compileLESS() { function compileLESS() {
return gulp.src("styles/fvtt-cthulhu-eternal.less") return gulp.src("styles/fvtt-cthulhu-eternal.less")
.pipe(less()) .pipe(less()).on('error',console.log.bind(console))
.pipe(gulp.dest("./css")) .pipe(gulp.dest("./css"))
} }
const css = gulp.series(compileLESS); const css = gulp.series(compileLESS);

View File

@ -1,7 +1,8 @@
{ {
"TYPES": { "TYPES": {
"Actor": { "Actor": {
"protagonist": "Protagonist" "protagonist": "Protagonist",
"vehicle": "Vehicle"
}, },
"Item": { "Item": {
"skill": "Skill", "skill": "Skill",
@ -13,11 +14,15 @@
"mentaldisorder": "Mental Disorder", "mentaldisorder": "Mental Disorder",
"bond": "Bond" , "bond": "Bond" ,
"arcane": "Arcane", "arcane": "Arcane",
"archetype": "Archetype" "archetype": "Archetype",
"ritual": "Ritual",
"tome": "Tome"
} }
}, },
"CTHULHUETERNAL": { "CTHULHUETERNAL": {
"Settings": { "Settings": {
"era": "Select the era of your game",
"eraHint": "Select the era of your game",
"Common": "Common", "Common": "Common",
"Classical": "Classical", "Classical": "Classical",
"Medieval": "Medieval", "Medieval": "Medieval",
@ -34,7 +39,33 @@
}, },
"Protagonist": { "Protagonist": {
"FIELDS": { "FIELDS": {
"damageBonus": {
"label": "Dmg.Bonus"
},
"resources": {
"permanentRating": {
"label": "Permanent Rating"
},
"hand": {
"label": "Hand"
},
"stowed": {
"label": "Stowed"
},
"storage": {
"label": "Storage"
}
},
"biodata": { "biodata": {
"feature": {
"label": "Feature"
},
"adaptedToViolence": {
"label": "Adapted to violence"
},
"adaptedToHelplessness": {
"label": "Adapted to helplessness"
},
"harshness": { "harshness": {
"label": "Harshness" "label": "Harshness"
}, },
@ -83,6 +114,12 @@
} }
} }
}, },
"Insanity": {
"None": "None",
"Flee": "Flee",
"Submit": "Submit",
"Struggle": "Struggle"
},
"Skill": { "Skill": {
"Unnatural": "Unnatural", "Unnatural": "Unnatural",
"Melee": "Melee Weapons", "Melee": "Melee Weapons",
@ -120,6 +157,9 @@
"resourceLevel": { "resourceLevel": {
"label": "Resource level" "label": "Resource level"
}, },
"state": {
"label": "State"
},
"settings": { "settings": {
"label": "Settings era" "label": "Settings era"
} }
@ -148,6 +188,9 @@
"riflecarabine": "Rifle/Carabine" "riflecarabine": "Rifle/Carabine"
}, },
"FIELDS": { "FIELDS": {
"state": {
"label": "State"
},
"settings": { "settings": {
"label": "Settings era" "label": "Settings era"
}, },
@ -203,10 +246,41 @@
} }
} }
}, },
"Vehicle": {
"FIELDS": {
"description": {
"label": "Description"
},
"notes": {
"label": "Notes"
},
"surfaceSpeed": {
"label": "Surface Speed"
},
"airSpeed": {
"label": "Air Speed"
},
"armor": {
"label": "Armor"
},
"settings": {
"label": "Settings era"
},
"crew": {
"label": "Crew"
},
"state": {
"label": "State"
}
}
},
"MentalDisorder": { "MentalDisorder": {
"FIELDS": { "FIELDS": {
"description": { "description": {
"label": "Description" "label": "Description"
},
"cured": {
"label": "Cured"
} }
} }
}, },
@ -255,9 +329,109 @@
"harsh": "Harsh", "harsh": "Harsh",
"veryHarsh": "Very Harsh" "veryHarsh": "Very Harsh"
}, },
"Tome": {
"FIELDS": {
"language": {
"label": "Language"
},
"settings": {
"label": "Settings"
},
"studyTime": {
"label": "Study Time"
},
"sanLoss": {
"label": "SAN Loss"
},
"unnaturalSkill": {
"label": "Unnatural Skill"
},
"rituals": {
"label": "Rituals"
},
"minimumEra": {
"label": "Minimum Era"
},
"otherBenefits": {
"label": "Other Benefits"
},
"creationDate": {
"label": "Creation Date"
},
"description": {
"label": "Description"
}
},
"Label": {
"tomeDetails": "Tome Details"
},
"Button": {
"addRitual": "Add Ritual"
}
},
"Ritual": {
"Simple": "Simple",
"Complex": "Complex",
"Elaborate": "Elaborate",
"FIELDS": {
"ritualType": {
"label": "Type"
},
"studyTime": {
"label": "Study time"
},
"studySAN": {
"label": "Study SAN"
},
"activationTime": {
"label": "Activation time"
},
"activationSAN": {
"label": "Activation SAN"
},
"activationWP": {
"label": "Activation WP"
},
"description": {
"label": "Description"
}
}
},
"Label": { "Label": {
"titleSkill": "Skill", "Rituals": "Rituals",
"titleWeapon": "Weapon", "Tomes": "Tomes",
"otherBenefits": "Other Benefits",
"Unarmed": "Unarmed",
"Cured": "Cured",
"Uncured": "Uncured",
"nudgedRoll": "Nudged Roll",
"selectNewValue": "Select the new value",
"wpCost": "WP Cost",
"Hand": "Hand",
"Stowed": "Stowed",
"Storage": "Storage",
"resourceRating": "Resource rating",
"Resources": "Resources",
"multiplier": "Multiplier",
"setBP": "Set BP",
"Vehicle": "Vehicle",
"Speed": "Speed",
"Slow": "Slow",
"Fast": "Fast",
"Average": "Average",
"None": "None",
"Pristine": "Pristine",
"Worn": "Worn",
"Junk": "Junk",
"resources": "Resources",
"resourceChecks": "Resource Checks",
"sanBPShort": "BP",
"tempInsanity": "Temp. Insanity",
"distinguishingFeatures": "Distinguishing Features",
"titleSkill": "Skill Roll",
"titleWeapon": "Weapon Roll",
"titleCharacteristic": "Characteristic Roll",
"titleSAN": "SAN Roll",
"biodata": "Biodata", "biodata": "Biodata",
"skill": "Skill", "skill": "Skill",
"modifier": "Modifier", "modifier": "Modifier",
@ -309,6 +483,7 @@
"criticalSuccess": "Critical Success", "criticalSuccess": "Critical Success",
"criticalFailure": "Critical Failure", "criticalFailure": "Critical Failure",
"Characteristic": "Characteristic", "Characteristic": "Characteristic",
"characteristic": "Characteristic",
"targetScore": "Target Score", "targetScore": "Target Score",
"gears": "Gears", "gears": "Gears",
"armors": "Armors", "armors": "Armors",
@ -331,7 +506,12 @@
"newGear": "New Gear", "newGear": "New Gear",
"newArcane": "New Arcane", "newArcane": "New Arcane",
"newArchetype": "New Archetype", "newArchetype": "New Archetype",
"newSkill": "New Skill" "newSkill": "New Skill",
"newTome": "New Tome",
"newRitual": "New Ritual"
},
"ChatMessage": {
"exhausted": "Your protagonist is exhausted. He loses [[/r 1d6]] Willpower Points."
}, },
"Edit": "Edit", "Edit": "Edit",
"Delete": "Delete", "Delete": "Delete",
@ -341,14 +521,22 @@
}, },
"Roll": { "Roll": {
"skill": "Skill", "skill": "Skill",
"roll": "Roll" "roll": "Roll",
"applyNudge": "Apply",
"cancel": "Cancel",
"nudgeRoll": "Nudge Roll"
}, },
"Tooltip": { "Tooltip": {
"sanBP": ">5 SAN lost in one roll, temporary insanity. If SAN less reaches BP = a Disorder unconscious Breaking and AND reset BP." "sanBP": ">5 SAN lost in one roll, temporary insanity. If SAN less reaches BP = a Disorder unconscious Breaking and AND reset BP.",
}, "setBP": "Set the current Breaking Point based on the current SAN value"
"Setting": {
}, },
"Chat": { "Chat": {
},
"Notifications": {
"NoWeaponSkill": "No weapon skill found for this weapon. Check Weapon definition or available skills/era",
"NoWeaponType": "No weapon type found for this weapon subtype. Check Weapon definition or available skills/era",
"skillAlreadyExists": "Skill already exists",
"WrongEra": "The era of the item does not match the ear of the system"
} }
} }
} }

View File

@ -9,3 +9,6 @@ export { default as CthulhuEternalMentalDisorderSheet } from "./sheets/mentaldis
export { default as CthulhuEternalGearSheet } from "./sheets/gear-sheet.mjs" export { default as CthulhuEternalGearSheet } from "./sheets/gear-sheet.mjs"
export { default as CthulhuEternalMotivationSheet } from "./sheets/motivation-sheet.mjs" export { default as CthulhuEternalMotivationSheet } from "./sheets/motivation-sheet.mjs"
export { default as CthulhuEternalArchetypeSheet } from "./sheets/archetype-sheet.mjs" export { default as CthulhuEternalArchetypeSheet } from "./sheets/archetype-sheet.mjs"
export { default as CthulhuEternalRitualSheet } from "./sheets/ritual-sheet.mjs"
export { default as CthulhuEternalVehicleSheet } from "./sheets/vehicle-sheet.mjs"
export { default as CthulhuEternalTomeSheet } from "./sheets/tome-sheet.mjs"

View File

@ -96,7 +96,6 @@ export default class CthulhuEternalActorSheet extends HandlebarsApplicationMixin
drop: this._canDragDrop.bind(this), drop: this._canDragDrop.bind(this),
} }
d.callbacks = { d.callbacks = {
dragstart: this._onDragStart.bind(this),
dragover: this._onDragOver.bind(this), dragover: this._onDragOver.bind(this),
drop: this._onDrop.bind(this), drop: this._onDrop.bind(this),
} }
@ -133,70 +132,6 @@ export default class CthulhuEternalActorSheet extends HandlebarsApplicationMixin
return true //this.isEditable && this.document.isOwner return true //this.isEditable && this.document.isOwner
} }
/**
* Callback actions which occur at the beginning of a drag start workflow.
* @param {DragEvent} event The originating DragEvent
* @protected
*/
_onDragStart(event) {
if ("link" in event.target.dataset) return
const el = event.currentTarget.closest('[data-drag="true"]')
const dragType = el.dataset.dragType
let dragData = {}
let target
switch (dragType) {
case "save":
target = event.currentTarget.querySelector("input")
dragData = {
actorId: this.document.id,
type: "roll",
rollType: target.dataset.rollType,
rollTarget: target.dataset.rollTarget,
value: target.value,
}
break
case "resource":
target = event.currentTarget.querySelector("select")
dragData = {
actorId: this.document.id,
type: "roll",
rollType: target.dataset.rollType,
rollTarget: target.dataset.rollTarget,
value: target.value,
}
break
case "damage":
dragData = {
actorId: this.document.id,
type: "rollDamage",
rollType: el.dataset.dragType,
rollTarget: el.dataset.itemId,
}
break
case "attack":
dragData = {
actorId: this.document.id,
type: "rollAttack",
rollValue: el.dataset.rollValue,
rollTarget: el.dataset.rollTarget,
}
break
default:
// Handle other cases or do nothing
break
}
// Extract the data you need
if (!dragData) return
// Set data transfer
event.dataTransfer.setData("text/plain", JSON.stringify(dragData))
}
/** /**
* Callback actions which occur when a dragged element is over a drop target. * Callback actions which occur when a dragged element is over a drop target.
* @param {DragEvent} event The originating DragEvent * @param {DragEvent} event The originating DragEvent

View File

@ -18,4 +18,12 @@ export default class CthulhuEternalMentalDisorderSheet extends CthulhuEternalIte
template: "systems/fvtt-cthulhu-eternal/templates/mentaldisorder.hbs", template: "systems/fvtt-cthulhu-eternal/templates/mentaldisorder.hbs",
}, },
} }
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
return context
}
} }

View File

@ -22,6 +22,8 @@ export default class CthulhuEternalMotivationSheet extends CthulhuEternalItemShe
/** @override */ /** @override */
async _prepareContext() { async _prepareContext() {
const context = await super._prepareContext() const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
return context return context
} }
} }

View File

@ -5,13 +5,14 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
classes: ["protagonist"], classes: ["protagonist"],
position: { position: {
width: 848, width: 860,
height: 620, height: 620,
}, },
window: { window: {
contentClasses: ["protagonist-content"], contentClasses: ["protagonist-content"],
}, },
actions: { actions: {
setBP: CthulhuEternalProtagonistSheet.#onSetBP,
createGear: CthulhuEternalProtagonistSheet.#onCreateGear, createGear: CthulhuEternalProtagonistSheet.#onCreateGear,
createArmor: CthulhuEternalProtagonistSheet.#onCreateArmor, createArmor: CthulhuEternalProtagonistSheet.#onCreateArmor,
createWeapon: CthulhuEternalProtagonistSheet.#onCreateWeapon, createWeapon: CthulhuEternalProtagonistSheet.#onCreateWeapon,
@ -19,7 +20,9 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
createInjury: CthulhuEternalProtagonistSheet.#onCreateInjury, createInjury: CthulhuEternalProtagonistSheet.#onCreateInjury,
createMentalDisorder: CthulhuEternalProtagonistSheet.#onCreateMentalDisorder, createMentalDisorder: CthulhuEternalProtagonistSheet.#onCreateMentalDisorder,
createMotivation: CthulhuEternalProtagonistSheet.#onCreateMotivation, createMotivation: CthulhuEternalProtagonistSheet.#onCreateMotivation,
createSkill: CthulhuEternalProtagonistSheet.#onCreateSkill createSkill: CthulhuEternalProtagonistSheet.#onCreateSkill,
createRitual: CthulhuEternalProtagonistSheet.#onCreateRitual,
createTome: CthulhuEternalProtagonistSheet.#onCreateTome,
}, },
} }
@ -73,6 +76,9 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
const context = await super._prepareContext() const context = await super._prepareContext()
context.tabs = this.#getTabs() context.tabs = this.#getTabs()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
context.enrichedNotes = await TextEditor.enrichHTML(this.document.system.notes, { async: true })
context.tooltipsCharacteristic = { context.tooltipsCharacteristic = {
str: game.i18n.localize("CTHULHUETERNAL.Characteristic.Str"), str: game.i18n.localize("CTHULHUETERNAL.Characteristic.Str"),
dex: game.i18n.localize("CTHULHUETERNAL.Characteristic.Dex"), dex: game.i18n.localize("CTHULHUETERNAL.Characteristic.Dex"),
@ -82,23 +88,9 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
cha: game.i18n.localize("CTHULHUETERNAL.Characteristic.Cha") cha: game.i18n.localize("CTHULHUETERNAL.Characteristic.Cha")
} }
context.tooltipsRessources = {
}
context.rollType = {
str: "characteristic",
dex: "characteristic",
con: "characteristic",
int: "characteristic",
pow: "characteristic",
cha: "characteristic"
}
return context return context
} }
_generateTooltip(type, target) {
}
/** @override */ /** @override */
async _preparePartContext(partId, context) { async _preparePartContext(partId, context) {
const doc = this.document const doc = this.document
@ -108,22 +100,34 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
case "skills": case "skills":
context.tab = context.tabs.skills context.tab = context.tabs.skills
context.skills = doc.itemTypes.skill context.skills = doc.itemTypes.skill
context.skills.sort((a, b) => a.name.localeCompare(b.name))
break break
case "equipment": case "equipment":
context.tab = context.tabs.equipment context.tab = context.tabs.equipment
context.weapons = doc.itemTypes.weapon context.weapons = doc.itemTypes.weapon
context.weapons.sort((a, b) => a.name.localeCompare(b.name))
context.armors = doc.itemTypes.armor context.armors = doc.itemTypes.armor
context.armors.sort((a, b) => a.name.localeCompare(b.name))
context.gears = doc.itemTypes.gear context.gears = doc.itemTypes.gear
context.gears.sort((a, b) => a.name.localeCompare(b.name))
context.rituals = doc.itemTypes.ritual
context.rituals.sort((a, b) => a.name.localeCompare(b.name))
context.tomes = doc.itemTypes.tome
context.tomes.sort((a, b) => a.name.localeCompare(b.name))
break break
case "status": case "status":
context.tab = context.tabs.status context.tab = context.tabs.status
context.injuries = doc.itemTypes.injury context.injuries = doc.itemTypes.injury
context.injuries.sort((a, b) => a.name.localeCompare(b.name))
context.mentaldisorders = doc.itemTypes.mentaldisorder context.mentaldisorders = doc.itemTypes.mentaldisorder
context.mentaldisorders.sort((a, b) => a.name.localeCompare(b.name))
context.motivations = doc.itemTypes.motivation
context.motivations.sort((a, b) => a.name.localeCompare(b.name))
context.bonds = doc.itemTypes.bond context.bonds = doc.itemTypes.bond
context.bonds.sort((a, b) => a.name.localeCompare(b.name))
break break
case "biography": case "biography":
context.tab = context.tabs.biography context.tab = context.tabs.biography
context.motivations = doc.itemTypes.motivation
context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true }) context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true }) context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true })
break break
@ -136,6 +140,10 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
* @param {Event} event The initiating click event. * @param {Event} event The initiating click event.
* @param {HTMLElement} target The current target of the event listener. * @param {HTMLElement} target The current target of the event listener.
*/ */
static #onSetBP(event, target) {
this.document.system.setBP()
}
static #onCreateGear(event, target) { static #onCreateGear(event, target) {
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newGear"), type: "gear" }]) this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newGear"), type: "gear" }])
} }
@ -168,6 +176,14 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newSkill"), type: "skill" }]) this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newSkill"), type: "skill" }])
} }
static #onCreateRitual(event, target) {
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newRitual"), type: "ritual" }])
}
static #onCreateTome(event, target) {
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newTome"), type: "tome" }])
}
/** /**
* Handles the roll action triggered by user interaction. * Handles the roll action triggered by user interaction.
* *
@ -189,10 +205,15 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
// Debug : console.log(">>>>", event, target, rollType) // Debug : console.log(">>>>", event, target, rollType)
// Deprecated : if (this.isEditMode) return // Deprecated : if (this.isEditMode) return
switch (rollType) { switch (rollType) {
case "resource":
item = foundry.utils.duplicate(this.actor.system.resources)
item.name = game.i18n.localize(`CTHULHUETERNAL.Label.Resources`)
item.targetScore = item.permanentRating
break
case "char": case "char":
let charId = $(event.currentTarget).data("char-id") let charId = $(event.currentTarget).data("char-id")
item = foundry.utils.duplicate(this.actor.system.characteristics[charId]) item = foundry.utils.duplicate(this.actor.system.characteristics[charId])
item.name = game.i18n.localize("CTHULHUETERNAL.Label." + charId + "Long") item.name = game.i18n.localize(`CTHULHUETERNAL.Label.${charId}Long`)
item.targetScore = item.value * 5 item.targetScore = item.value * 5
break break
case "skill": case "skill":
@ -203,7 +224,13 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
case "damage": case "damage":
li = $(event.currentTarget).parents(".item"); li = $(event.currentTarget).parents(".item");
item = this.actor.items.get(li.data("item-id")); item = this.actor.items.get(li.data("item-id"));
item.damageBonus = this.actor.system.damageBonus
break break
case "san":
item = foundry.utils.duplicate(this.actor.system.san)
item.name = game.i18n.localize("CTHULHUETERNAL.Label.SAN")
item.targetScore = item.value
break;
default: default:
throw new Error(`Unknown roll type ${rollType}`) throw new Error(`Unknown roll type ${rollType}`)
} }
@ -222,5 +249,4 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
} }
} }
// #endregion
} }

View File

@ -0,0 +1,28 @@
import CthulhuEternalItemSheet from "./base-item-sheet.mjs"
export default class CthulhuEternalRitualSheet extends CthulhuEternalItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["ritual"],
position: {
width: 600,
},
window: {
contentClasses: ["ritual-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-cthulhu-eternal/templates/ritual.hbs",
},
}
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
return context
}
}

View File

@ -0,0 +1,28 @@
import CthulhuEternalItemSheet from "./base-item-sheet.mjs"
export default class CthulhuEternalTomeSheet extends CthulhuEternalItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["tome"],
position: {
width: 600,
},
window: {
contentClasses: ["tome-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-cthulhu-eternal/templates/tome.hbs",
},
}
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
return context
}
}

View File

@ -0,0 +1,117 @@
import CthulhuEternalActorSheet from "./base-actor-sheet.mjs"
export default class CthulhuEternalVehicleSheet extends CthulhuEternalActorSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["vehicle"],
position: {
width: 680,
height: 540,
},
window: {
contentClasses: ["vehicle-content"],
},
actions: {
createGear: CthulhuEternalVehicleSheet.#onCreateGear,
createWeapon: CthulhuEternalVehicleSheet.#onCreateWeapon,
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-cthulhu-eternal/templates/vehicle-main.hbs",
},
tabs: {
template: "templates/generic/tab-navigation.hbs",
},
equipment: {
template: "systems/fvtt-cthulhu-eternal/templates/vehicle-equipment.hbs",
},
description: {
template: "systems/fvtt-cthulhu-eternal/templates/vehicle-description.hbs",
},
}
/** @override */
tabGroups = {
sheet: "equipment",
}
/**
* Prepare an array of form header tabs.
* @returns {Record<string, Partial<ApplicationTab>>}
*/
#getTabs() {
const tabs = {
equipment: { id: "equipment", group: "sheet", icon: "fa-solid fa-shapes", label: "CTHULHUETERNAL.Label.equipment" },
description: { id: "description", group: "sheet", icon: "fa-solid fa-book", label: "CTHULHUETERNAL.Label.description" },
}
for (const v of Object.values(tabs)) {
v.active = this.tabGroups[v.group] === v.id
v.cssClass = v.active ? "active" : ""
}
return tabs
}
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.tabs = this.#getTabs()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
context.enrichedNotes = await TextEditor.enrichHTML(this.document.system.notes, { async: true })
return context
}
_generateTooltip(type, target) {
}
/** @override */
async _preparePartContext(partId, context) {
const doc = this.document
switch (partId) {
case "main":
break
case "equipment":
context.tab = context.tabs.equipment
context.weapons = doc.itemTypes.weapon
context.gears = doc.itemTypes.gear
break
case "description":
context.tab = context.tabs.description
context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true })
break
}
return context
}
/**
* Creates a new attack item directly from the sheet and embeds it into the document.
* @param {Event} event The initiating click event.
* @param {HTMLElement} target The current target of the event listener.
*/
static #onCreateGear(event, target) {
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newGear"), type: "gear" }])
}
static #onCreateWeapon(event, target) {
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newWeapon"), type: "weapon" }])
}
async _onDrop(event) {
if (!this.isEditable || !this.isEditMode) return
const data = TextEditor.getDragEventData(event)
// Handle different data types
switch (data.type) {
case "Item":
const item = await fromUuid(data.uuid)
return super._onDropItem(item)
}
}
}

View File

@ -34,19 +34,26 @@ export const AVAILABLE_SETTINGS = {
postapo: "CTHULHUETERNAL.Settings.PostApo" postapo: "CTHULHUETERNAL.Settings.PostApo"
} }
export const INSANITY = {
"none": "CTHULHUETERNAL.Insanity.None",
"flee": "CTHULHUETERNAL.Insanity.Flee",
"struggle": "CTHULHUETERNAL.Insanity.Struggle",
"submit": "CTHULHUETERNAL.Insanity.Submit"
}
export const ERA_CSS = { export const ERA_CSS = {
jazz: { primaryFont: "RozhaOne", secondaryFont: "RozhaOne", titleFont: "Broadway", imgFilter: "brightness(0) saturate(100%) invert(52%) sepia(9%) saturate(2368%) hue-rotate(360deg) brightness(86%) contrast(84%)" }, jazz: { primaryFont: "RozhaOne", secondaryFont: "RozhaOne", titleFont: "Broadway", baseFontSize: "0.95rem", titleFontSize: "1.2rem", imgFilter: "brightness(0) saturate(100%) invert(52%) sepia(9%) saturate(2368%) hue-rotate(360deg) brightness(86%) contrast(84%)" },
modern: { primaryFont: "Georama", secondaryFont: "Georama", titleFont: "Georama", imgFilter: "brightness(0) saturate(100%) invert(92%) sepia(11%) saturate(1214%) hue-rotate(51deg) brightness(93%) contrast(86%)" }, modern: { primaryFont: "Georama", secondaryFont: "Georama", titleFont: "Georama", baseFontSize: "1.0rem", titleFontSize: "1.2rem",imgFilter: "brightness(0) saturate(100%) invert(92%) sepia(11%) saturate(1214%) hue-rotate(51deg) brightness(93%) contrast(86%)" },
future: { primaryFont: "Megrim", secondaryFont: "Megrim", titleFont: "Seabreed", imgFilter: "brightness(0) saturate(100%) invert(83%) sepia(30%) saturate(588%) hue-rotate(168deg) brightness(105%) contrast(103%)" }, future: { primaryFont: "Georama", secondaryFont: "Georama", titleFont: "Seabreed", baseFontSize: "1.0rem", titleFontSize: "2.0rem",imgFilter: "invert(90%) sepia(6%) saturate(1818%) hue-rotate(152deg) brightness(91%) contrast(91%)" },
victorian: { primaryFont: "Volkhov", secondaryFont: "Volkhov", titleFont: "Excelsior", imgFilter: "brightness(0) saturate(100%) invert(100%) sepia(59%) saturate(1894%) hue-rotate(337deg) brightness(88%) contrast(98%)" }, victorian: { primaryFont: "Volkhov", secondaryFont: "Volkhov", titleFont: "Excelsior", baseFontSize: "1.0rem", titleFontSize: "1.2rem",imgFilter: "brightness(0) saturate(100%) invert(100%) sepia(59%) saturate(1894%) hue-rotate(337deg) brightness(88%) contrast(98%)" },
coldwar: { primaryFont: "BebasNeue", secondaryFont: "BebasNeue", titleFont: "TopSecret", imgFilter: "brightness(0) saturate(100%) invert(81%) sepia(14%) saturate(2508%) hue-rotate(202deg) brightness(99%) contrast(105%)"}, coldwar: { primaryFont: "Georama", secondaryFont: "Georama", titleFont: "TopSecret", baseFontSize: "1.0rem", titleFontSize: "1.2rem",imgFilter: "brightness(0) saturate(100%) invert(81%) sepia(14%) saturate(2508%) hue-rotate(202deg) brightness(99%) contrast(105%)"},
revolution: { primaryFont: "IMFell", secondaryFont: "IMFell", titleFont: "Dominican", imgFilter: "brightness(0) saturate(100%) invert(81%) sepia(25%) saturate(386%) hue-rotate(7deg) brightness(101%) contrast(84%)" }, revolution: { primaryFont: "IMFell", secondaryFont: "IMFell", titleFont: "Dominican", baseFontSize: "1.0rem",titleFontSize: "1.3rem",imgFilter: "brightness(0) saturate(100%) invert(81%) sepia(25%) saturate(386%) hue-rotate(7deg) brightness(101%) contrast(84%)" },
medieval: { primaryFont: "UncialAntiqua", secondaryFont: "UncialAntiqua", titleFont: "Luminari", imgFilter: "brightness(0) saturate(100%) invert(93%) sepia(46%) saturate(354%) hue-rotate(321deg) brightness(93%) contrast(87%)"}, medieval: { primaryFont: "UncialAntiqua", secondaryFont: "UncialAntiqua", titleFont: "Luminari", baseFontSize: "0.9rem",titleFontSize: "1.2rem",imgFilter: "brightness(0) saturate(100%) invert(93%) sepia(46%) saturate(354%) hue-rotate(321deg) brightness(93%) contrast(87%)"},
ww2: { primaryFont: "SairaStencilOne", secondaryFont: "SairaStencilOne", titleFont: "Armalite", imgFilter: "brightness(0) saturate(100%) invert(95%) sepia(9%) saturate(1471%) hue-rotate(342deg) brightness(103%) contrast(107%)"}, ww2: { primaryFont: "SairaStencilOne", secondaryFont: "SairaStencilOne", titleFont: "Armalite", baseFontSize: "0.9rem",titleFontSize: "1.2rem",imgFilter: "filter: invert(44%) sepia(8%) saturate(2657%) hue-rotate(40deg) brightness(96%) contrast(75%)"},
ww1: { primaryFont: "CarterOne", secondaryFont: "CarterOne", titleFont: "SigmarOne", imgFilter: "brightness(0) saturate(100%) invert(90%) sepia(38%) saturate(341%) hue-rotate(21deg) brightness(105%) contrast(105%)"}, ww1: { primaryFont: "CarterOne", secondaryFont: "CarterOne", titleFont: "SigmarOne", baseFontSize: "0.9rem",titleFontSize: "1.1rem",imgFilter: "invert(28%) sepia(27%) saturate(475%) hue-rotate(76deg) brightness(95%) contrast(93%)"},
ageofsail: { primaryFont: "Tangerine", secondaryFont: "Tangerine", titleFont: "P22Operina", imgFilter: "brightness(0) saturate(100%) invert(43%) sepia(74%) saturate(3154%) hue-rotate(336deg) brightness(95%) contrast(83%)" }, ageofsail: { primaryFont: "SailRegular", secondaryFont: "SailRegular", titleFont: "P22Operina", baseFontSize: "1.1rem",titleFontSize: "1.2rem",imgFilter: "brightness(0) saturate(100%) invert(43%) sepia(74%) saturate(3154%) hue-rotate(336deg) brightness(95%) contrast(83%)" },
classical: { primaryFont: "SpectralSC", secondaryFont: "SpectralSC", titleFont: "TrajanPro", imgFilter: "brightness(0) saturate(100%) invert(52%) sepia(32%) saturate(7492%) hue-rotate(265deg) brightness(89%) contrast(95%)" }, classical: { primaryFont: "ChantelliAntiqua", secondaryFont: "ChantelliAntiqua", titleFont: "TrajanPro", baseFontSize: "0.9rem",titleFontSize: "1.1rem",imgFilter: "brightness(0) saturate(100%) invert(52%) sepia(32%) saturate(7492%) hue-rotate(265deg) brightness(89%) contrast(95%)" },
postapo: { primaryFont: "Teko", secondaryFont: "Teko", titleFont: "Teko", imgFilter: "brightness(0) saturate(100%) invert(44%) sepia(55%) saturate(2341%) hue-rotate(329deg) brightness(122%) contrast(103%))" } postapo: { primaryFont: "Teko", secondaryFont: "Teko", titleFont: "Teko", baseFontSize: "1.25rem",titleFontSize: "1.5rem",imgFilter: "brightness(0) saturate(100%) invert(44%) sepia(55%) saturate(2341%) hue-rotate(329deg) brightness(122%) contrast(103%))" }
} }
export const RESOURCE_RATING = { export const RESOURCE_RATING = {
@ -82,6 +89,45 @@ export const RESOURCE_RATING = {
} }
} }
export const RESOURCE_BREAKDOWN = [
{ value: 0, hand: 0, stowed: 0, storage: 0, checks: 0},
{ value: 1, hand: 1, stowed: 0, storage: 0, checks: 1},
{ value: 2, hand: 2, stowed: 0, storage: 0, checks: 1},
{ value: 3, hand: 3, stowed: 0, storage: 0, checks: 1},
{ value: 4, hand: 4, stowed: 0, storage: 0, checks: 1},
{ value: 5, hand: 5, stowed: 0, storage: 0, checks: 1},
{ value: 6, hand: 6, stowed: 0, storage: 0, checks: 1},
{ value: 7, hand: 6, stowed: 1, storage: 0, checks: 2},
{ value: 8, hand: 6, stowed: 2, storage: 0, checks: 2},
{ value: 9, hand: 6, stowed: 3, storage: 0, checks: 2},
{ value: 10, hand: 6, stowed: 4, storage: 0, checks: 2},
{ value: 11, hand: 6, stowed: 5, storage: 0, checks: 2},
{ value: 12, hand: 6, stowed: 6, storage: 0, checks: 2},
{ value: 13, hand: 6, stowed: 6, storage: 1, checks: 3},
{ value: 14, hand: 6, stowed: 6, storage: 2, checks: 3},
{ value: 15, hand: 6, stowed: 6, storage: 3, checks: 3},
{ value: 16, hand: 6, stowed: 6, storage: 4, checks: 3},
{ value: 17, hand: 6, stowed: 6, storage: 5, checks: 3},
{ value: 18, hand: 6, stowed: 6, storage: 6, checks: 3},
{ value: 19, hand: 6, stowed: 6, storage: 7, checks: 3},
{ value: 20, hand: 6, stowed: 6, storage: 8, checks: 3}
]
export const DAMAGE_BONUS = [ -2, -2, -2, -2, -2, -1, -1, -1, -1, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2]
export const VEHICLE_SPEED = {
"none": "CTHULHUETERNAL.Label.None",
"slow": "CTHULHUETERNAL.Label.Slow",
"average": "CTHULHUETERNAL.Label.Average",
"fast": "CTHULHUETERNAL.Label.Fast"
}
export const EQUIPMENT_STATES = {
"pristine": "CTHULHUETERNAL.Label.Pristine",
"worn": "CTHULHUETERNAL.Label.Worn",
"junk": "CTHULHUETERNAL.Label.Junk"
}
export const MENTAL_ILLNESS_CURE_SKILL = { export const MENTAL_ILLNESS_CURE_SKILL = {
jazz: "CTHULHUETERNAL.Skill.Psychoanalyze", jazz: "CTHULHUETERNAL.Skill.Psychoanalyze",
modern: "CTHULHUETERNAL.Skill.Psychoanalyze", modern: "CTHULHUETERNAL.Skill.Psychoanalyze",
@ -96,6 +142,13 @@ export const WEAPON_SKILL_MAPPING = {
"rangedfirearm": "CTHULHUETERNAL.Skill.Firearms", "rangedfirearm": "CTHULHUETERNAL.Skill.Firearms",
"unarmed": "CTHULHUETERNAL.Skill.UnarmedCombat" "unarmed": "CTHULHUETERNAL.Skill.UnarmedCombat"
}, },
postapo: {
"melee": "CTHULHUETERNAL.Skill.Melee",
"rangedprimitive": "CTHULHUETERNAL.Skill.Firearms",
"rangedthrown": "CTHULHUETERNAL.Skill.Athletics",
"rangedfirearm": "CTHULHUETERNAL.Skill.Firearms",
"unarmed": "CTHULHUETERNAL.Skill.UnarmedCombat"
},
jazz: { jazz: {
"melee": "CTHULHUETERNAL.Skill.Melee", "melee": "CTHULHUETERNAL.Skill.Melee",
"rangedprimitive": "CTHULHUETERNAL.Skill.Firearms", "rangedprimitive": "CTHULHUETERNAL.Skill.Firearms",
@ -165,6 +218,32 @@ export const WEAPON_SKILL_MAPPING = {
"unarmed": "CTHULHUETERNAL.Skill.UnarmedCombat" "unarmed": "CTHULHUETERNAL.Skill.UnarmedCombat"
} }
} }
export const MODIFIER_CHOICES = {
"-40": "-40",
"-20": "-20",
"-10": "-10",
"+0": "+0",
"+10": "+10",
"+20": "+20",
"+40": "+40",
}
export const MULTIPLIER_CHOICES = {
"0.25": "0.25",
"0.5": "0.5",
"1": "1",
"2": "2",
"4": "4",
"5": "5"
}
export const RITUAL_TYPES = {
"simple": "CTHULHUETERNAL.Ritual.Simple",
"complex": "CTHULHUETERNAL.Ritual.Complex",
"elaborate": "CTHULHUETERNAL.Ritual.Elaborate"
}
/** /**
* Include all constant definitions within the SYSTEM global export * Include all constant definitions within the SYSTEM global export
* @type {Object} * @type {Object}
@ -181,5 +260,13 @@ export const SYSTEM = {
RESOURCE_RATING, RESOURCE_RATING,
MENTAL_ILLNESS_CURE_SKILL, MENTAL_ILLNESS_CURE_SKILL,
ERA_CSS, ERA_CSS,
ASCII INSANITY,
EQUIPMENT_STATES,
RESOURCE_BREAKDOWN,
VEHICLE_SPEED,
MODIFIER_CHOICES,
MULTIPLIER_CHOICES,
ASCII,
DAMAGE_BONUS,
RITUAL_TYPES
} }

View File

@ -1,7 +1,7 @@
import CthulhuEternalUtils from "../utils.mjs" import CthulhuEternalUtils from "../utils.mjs"
export default class CthulhuEternalActor extends Actor { export default class CthulhuEternalActor extends Actor {
static async create(data, options) { static async create(data, options) {
// Case of compendium global import // Case of compendium global import
@ -19,29 +19,68 @@ export default class CthulhuEternalActor extends Actor {
const skills = await CthulhuEternalUtils.loadCompendium("fvtt-cthulhu-eternal.skills") const skills = await CthulhuEternalUtils.loadCompendium("fvtt-cthulhu-eternal.skills")
data.items = data.items || [] data.items = data.items || []
for (let skill of skills) { for (let skill of skills) {
if (skill.system.settings === era ) { if (skill.system.settings === era) {
data.items.push(skill.toObject()) data.items.push(skill.toObject())
} }
} }
data.items.push({ type:"weapon", img: "systems/fvtt-cthulhu-eternal/assets/icons/icon_fist.svg",
name: game.i18n.localize("CTHULHUETERNAL.Label.Unarmed"), system: { damage: "1d4-1", weaponType: "unarmed" } })
} }
return super.create(data, options); return super.create(data, options);
} }
_onUpdate(changed, options, userId) {
async _preCreate(data, options, user) { // DEBUG : console.log("CthulhuEternalActor.update", changed, options, userId)
await super._preCreate(data, options, user) if (changed?.system?.wp?.exhausted) {
ChatMessage.create({
// Configure prototype token settings user: userId,
const prototypeToken = {} speaker: { alias: this.name },
if (this.type === "protagonist") { rollMode: "selfroll",
Object.assign(prototypeToken, { content: game.i18n.localize("CTHULHUETERNAL.ChatMessage.exhausted"),
sight: { enabled: true }, type: CONST.CHAT_MESSAGE_STYLES.OTHER
actorLink: true,
disposition: CONST.TOKEN_DISPOSITIONS.FRIENDLY,
}) })
this.updateSource({ prototypeToken })
} }
return super._onUpdate(changed, options, userId)
} }
async createEmbeddedDocuments(embeddedName, data, operation) {
let newData = []
if (embeddedName === "Item") {
for (let i of data) {
if (i.type === "skill") {
if (this.items.find(item => item.name.toLowerCase() === i.name.toLowerCase())) {
ui.notifications.warn(game.i18n.localize("CTHULHUETERNAL.Notifications.skillAlreadyExists"))
continue
}
}
if (i.type === "bond") {
if (i.system.bondType === "individual") {
i.system.value = this.system.characteristics.cha.value
} else {
i.system.value = Math.floor(this.system.resources.permanentRating / 2)
}
}
newData.push(i)
}
return super.createEmbeddedDocuments(embeddedName, newData, operation)
}
return super.createEmbeddedDocuments(embeddedName, data, operation)
}
async _preCreate(data, options, user) {
await super._preCreate(data, options, user)
// Configure prototype token settings
const prototypeToken = {}
if (this.type === "protagonist") {
Object.assign(prototypeToken, {
sight: { enabled: true },
actorLink: true,
disposition: CONST.TOKEN_DISPOSITIONS.FRIENDLY,
})
this.updateSource({ prototypeToken })
}
}
} }

View File

@ -1,7 +1,7 @@
export const defaultItemImg = { export const defaultItemImg = {
weapon: "systems/fvtt-cthulhu-eternal/assets/icons/icon_weapon.svg", weapon: "systems/fvtt-cthulhu-eternal/assets/icons/icon_weapon.svg",
armor: "systems/fvtt-cthulhu-eternal/assets/icons/icon_armor.svg", armor: "systems/fvtt-cthulhu-eternal/assets/icons/icon_armor.svg",
gear: "systems/fvtt-cthulhu-eternal/assets/icons/icon_gear.svg", gear: "systems/fvtt-cthulhu-eternal/assets/icons/icon_equipment.svg",
skill: "systems/fvtt-cthulhu-eternal/assets/icons/icon_skill.svg", skill: "systems/fvtt-cthulhu-eternal/assets/icons/icon_skill.svg",
archetype: "systems/fvtt-cthulhu-eternal/assets/icons/icon_archetype.svg", archetype: "systems/fvtt-cthulhu-eternal/assets/icons/icon_archetype.svg",
bond: "systems/fvtt-cthulhu-eternal/assets/icons/icon_bond.svg", bond: "systems/fvtt-cthulhu-eternal/assets/icons/icon_bond.svg",
@ -9,6 +9,8 @@ export const defaultItemImg = {
arcane: "systems/fvtt-cthulhu-eternal/assets/icons/icon_arcane.svg", arcane: "systems/fvtt-cthulhu-eternal/assets/icons/icon_arcane.svg",
injury: "systems/fvtt-cthulhu-eternal/assets/icons/icon_injury.svg", injury: "systems/fvtt-cthulhu-eternal/assets/icons/icon_injury.svg",
motivation: "systems/fvtt-cthulhu-eternal/assets/icons/icon_motivation.svg", motivation: "systems/fvtt-cthulhu-eternal/assets/icons/icon_motivation.svg",
ritual: "systems/fvtt-cthulhu-eternal/assets/icons/icon_ritual.svg",
tome: "systems/fvtt-cthulhu-eternal/assets/icons/icon_tome.svg",
} }
export default class CthulhuEternalItem extends Item { export default class CthulhuEternalItem extends Item {

View File

@ -59,18 +59,6 @@ export default class CthulhuEternalRoll extends Roll {
return this.options.hasTarget return this.options.hasTarget
} }
get targetName() {
return this.options.targetName
}
get targetArmor() {
return this.options.targetArmor
}
get targetMalus() {
return this.options.targetMalus
}
get realDamage() { get realDamage() {
return this.options.realDamage return this.options.realDamage
} }
@ -79,6 +67,43 @@ export default class CthulhuEternalRoll extends Roll {
return this.options.weapon return this.options.weapon
} }
get isLowWP() {
return this.options.isLowWP
}
get isZeroWP() {
return this.options.isZeroWP
}
get isExhausted() {
return this.options.isExhausted
}
get isNudgedRoll() {
return this.options.isNudgedRoll
}
get wpCost() {
return this.options.wpCost
}
static updateResourceDialog(options) {
let rating = 0
if (options.rollItem.enableHand) {
rating += options.rollItem.hand
}
if (options.rollItem.enableStowed) {
rating += options.rollItem.stowed
}
if (options.rollItem.enableStorage) {
rating += options.rollItem.storage
}
let multiplier = Number($(`.roll-skill-multiplier`).val())
options.initialScore = rating
options.percentScore = rating * multiplier
$(".resource-score").text(`${rating} (${options.percentScore}%)`)
}
/** /**
* Prompt the user with a dialog to configure and execute a roll. * Prompt the user with a dialog to configure and execute a roll.
* *
@ -95,37 +120,72 @@ export default class CthulhuEternalRoll extends Roll {
*/ */
static async prompt(options = {}) { static async prompt(options = {}) {
let formula = "1d100" let formula = "1d100"
let hasModifier = true
let hasMultiplier = false
options.isNudge = true
switch (options.rollType) { switch (options.rollType) {
case "skill": case "skill":
console.log(options.rollItem) console.log(options.rollItem)
options.initialScore = options.rollItem.system.computeScore() options.initialScore = options.rollItem.system.computeScore()
break break
case "san":
case "char": case "char":
options.initialScore = options.rollItem.targetScore options.initialScore = options.rollItem.targetScore
options.isNudge = (options.rollType !== "san")
break break
case "damage": case "resource":
let formula = options.rollItem.system.damage hasModifier = false
hasMultiplier = true
options.initialScore = options.rollItem.targetScore
options.totalRating = options.rollItem.targetScore
options.percentScore = options.rollItem.targetScore * 5
options.rollItem.enableHand = true
options.rollItem.enableStowed = true
options.rollItem.enableStorage = true
options.isNudge = false
break
case "damage":
let formula = options.rollItem.system.damage
if ( options.rollItem.system.weaponType === "melee" || options.rollItem.system.weaponType === "unarmed") {
formula += ` + ${options.rollItem.damageBonus}`
}
let damageRoll = new Roll(formula) let damageRoll = new Roll(formula)
await damageRoll.evaluate() await damageRoll.evaluate()
await damageRoll.toMessage({ await damageRoll.toMessage({
flavor: `${options.rollItem.name} - Damage Roll` flavor: `${options.rollItem.name} - Damage Roll`
}); });
let isLethal = false let isLethal = false
if (options.rollItem.system.lethality > 0 ) { options.isNudge = false
if (options.rollItem.system.lethality > 0) {
let lethalityRoll = new Roll("1d100") let lethalityRoll = new Roll("1d100")
await lethalityRoll.evaluate() await lethalityRoll.evaluate()
isLethal = (lethalityRoll.total <= options.rollItem.system.lethality) isLethal = (lethalityRoll.total <= options.rollItem.system.lethality)
await lethalityRoll.toMessage({ await lethalityRoll.toMessage({
flavor: `${options.rollItem.name} - Lethality Roll : ${lethalityRoll.total} <= ${options.rollItem.system.lethality} => ${isLethal}` flavor: `${options.rollItem.name} - Lethality Roll : ${lethalityRoll.total} <= ${options.rollItem.system.lethality} => ${isLethal}`
}); });
} }
return return
case "weapon": case "weapon":
let era = game.settings.get("fvtt-cthulhu-eternal", "settings-era") let era = game.settings.get("fvtt-cthulhu-eternal", "settings-era")
let skillName = game.i18n.localize(SYSTEM.WEAPON_SKILL_MAPPING[era][options.rollItem.system.weaponType]) if (era !== options.rollItem.system.settings) {
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.WrongEra"))
console.log("WP Wrong Era", era, options.rollItem.system.weaponType)
return
}
if (!SYSTEM.WEAPON_SKILL_MAPPING[era] || !SYSTEM.WEAPON_SKILL_MAPPING[era][options.rollItem.system.weaponType]) {
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.NoWeaponType"))
console.log("WP Not found", era, options.rollItem.system.weaponType)
return
}
let skillName = game.i18n.localize(SYSTEM.WEAPON_SKILL_MAPPING[era][options.rollItem.system.weaponType])
let actor = game.actors.get(options.actorId) let actor = game.actors.get(options.actorId)
options.weapon = options.rollItem options.weapon = options.rollItem
options.rollItem = actor.items.find(i => i.type === "skill" && i.name.toLowerCase() === skillName.toLowerCase()) options.rollItem = actor.items.find(i => i.type === "skill" && i.name.toLowerCase() === skillName.toLowerCase())
if (!options.rollItem) {
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.NoWeaponSkill"))
return
}
options.initialScore = options.rollItem.system.computeScore() options.initialScore = options.rollItem.system.computeScore()
console.log("WEAPON", skillName, era, options.rollItem) console.log("WEAPON", skillName, era, options.rollItem)
break break
@ -141,37 +201,34 @@ export default class CthulhuEternalRoll extends Roll {
default: "public", default: "public",
}) })
const choiceModifier = { const choiceModifier = SYSTEM.MODIFIER_CHOICES
"-10": "-10", const choiceMultiplier = SYSTEM.MULTIPLIER_CHOICES
"-20": "-20",
"-40": "-40",
"0": "0",
"+10": "+10",
"+20": "+20",
"+40": "+40",
}
let modifier = "0" let modifier = "+0"
let targetMalus = "0" let multiplier = "5"
let targetName
let targetArmor
let dialogContext = { let dialogContext = {
rollType: options.rollType, rollType: options.rollType,
rollItem: foundry.utils.duplicate(options.rollItem), // Object only, no class rollItem: foundry.utils.duplicate(options.rollItem), // Object only, no class
weapon: options?.weapon, weapon: options?.weapon,
initialScore: options.initialScore, initialScore: options.initialScore,
targetScore: options.initialScore, targetScore: options.initialScore,
isLowWP: options.isLowWP, isLowWP: options.isLowWP,
isZeroWP: options.isZeroWP, isZeroWP: options.isZeroWP,
isExhausted: options.isExhausted,
enableHand: options.rollItem.enableHand,
enableStowed: options.rollItem.enableStowed,
enableStorage: options.rollItem.enableStorage,
rollModes, rollModes,
fieldRollMode, fieldRollMode,
choiceModifier, choiceModifier,
choiceMultiplier,
formula, formula,
hasTarget: options.hasTarget, hasTarget: options.hasTarget,
hasModifier,
hasMultiplier,
modifier, modifier,
targetName, multiplier
targetArmor
} }
const content = await renderTemplate("systems/fvtt-cthulhu-eternal/templates/roll-dialog.hbs", dialogContext) const content = await renderTemplate("systems/fvtt-cthulhu-eternal/templates/roll-dialog.hbs", dialogContext)
@ -193,67 +250,95 @@ export default class CthulhuEternalRoll extends Roll {
}, },
}, },
], ],
actions: {
"selectHand": (event, button, dialog) => {
options.rollItem.enableHand = !options.rollItem.enableHand
this.updateResourceDialog(options)
},
"selectStowed": (event, button, dialog) => {
options.rollItem.enableStowed = !options.rollItem.enableStowed
this.updateResourceDialog(options)
},
"selectStorage": (event, button, dialog) => {
options.rollItem.enableStorage = !options.rollItem.enableStorage
this.updateResourceDialog(options)
}
},
rejectClose: false, // Click on Close button will not launch an error rejectClose: false, // Click on Close button will not launch an error
render: (event, dialog) => { render: (event, dialog) => {
}, $(".roll-skill-multiplier").change(event => {
options.multiplier = Number(event.target.value)
this.updateResourceDialog(options)
})
}
}) })
// If the user cancels the dialog, exit // If the user cancels the dialog, exit
if (rollContext === null) return if (rollContext === null) return
let rollData = foundry.utils.mergeObject(foundry.utils.duplicate(options), rollContext) let rollData = foundry.utils.mergeObject(foundry.utils.duplicate(options), rollContext)
rollData.rollMode = rollContext.visibility rollData.rollMode = rollContext.visibility
rollData.targetName = targetName
rollData.targetArmor = targetArmor
rollData.targetMalus = targetMalus
// Update target score // Update target score
console.log(rollData) console.log("Rolldata", rollData, options)
rollData.targetScore = Math.min( Math.max(options.initialScore + Number(rollData.modifier), 0), 100) if (options.rollType === "resource") {
if ( rollData.isLowWP ) { rollData.targetScore = options.initialScore * Number(rollContext.multiplier)
rollData.targetScore -= 20 } else {
rollData.targetScore = Math.min(Math.max(options.initialScore + Number(rollData.modifier), 0), 100)
if (rollData.isLowWP || rollData.isExhausted) {
rollData.targetScore -= 20
}
if (rollData.isZeroWP) {
rollData.targetScore = 0
}
rollData.targetScore = Math.min(Math.max(rollData.targetScore, 0), 100)
} }
if ( rollData.isZeroWP ) {
rollData.targetScore = 0
}
rollData.targetScore = Math.min( Math.max(rollData.targetScore, 0), 100)
/**
* A hook event that fires before the roll is made.
*/
if (Hooks.call("fvtt-cthulhu-eternal.preRoll", options, rollData) === false) return if (Hooks.call("fvtt-cthulhu-eternal.preRoll", options, rollData) === false) return
const roll = new this(formula, options.data, rollData) const roll = new this(formula, options.data, rollData)
await roll.evaluate() await roll.evaluate()
roll.displayRollResult(roll, options, rollData)
if (Hooks.call("fvtt-cthulhu-eternal.Roll", options, rollData, roll) === false) return
return roll
}
displayRollResult(formula, options, rollData) {
// Compute the result quality // Compute the result quality
let resultType = "failure" let resultType = "failure"
let dec = Math.floor(roll.total/10) let dec = Math.floor(this.total / 10)
let unit = roll.total - (dec*10) let unit = this.total - (dec * 10)
if (roll.total <= rollData.targetScore) { if (this.total <= rollData.targetScore) {
resultType = "success" resultType = "success"
// Detect if decimal == unit in the dire total result // Detect if decimal == unit in the dire total result
if (dec === unit || roll.total === 1) { if (dec === unit || this.total === 1) {
resultType = "successCritical" resultType = "successCritical"
} }
} else { } else {
// Detect if decimal == unit in the dire total result // Detect if decimal == unit in the dire total result
if (dec === unit || roll.total === 100) { if (dec === unit || this.total === 100) {
resultType = "failureCritical" resultType = "failureCritical"
} }
} }
roll.options.resultType = resultType this.options.resultType = resultType
roll.options.isSuccess = resultType === "success" || resultType === "successCritical" if (this.options.isNudgedRoll) {
roll.options.isFailure = resultType === "failure" || resultType === "failureCritical" this.options.isSuccess = resultType === "success" || resultType === "successCritical"
roll.options.isCritical = resultType === "successCritical" || resultType === "failureCritical" this.options.isFailure = resultType === "failure" || resultType === "failureCritical"
this.options.isCritical = false
/** } else {
* A hook event that fires after the roll has been made. this.options.isSuccess = resultType === "success" || resultType === "successCritical"
*/ this.options.isFailure = resultType === "failure" || resultType === "failureCritical"
if (Hooks.call("fvtt-cthulhu-eternal.Roll", options, rollData, roll) === false) return this.options.isCritical = resultType === "successCritical" || resultType === "failureCritical"
}
return roll this.options.isLowWP = rollData.isLowWP
this.options.isZeroWP = rollData.isZeroWP
this.options.isExhausted = rollData.isExhausted
this.options.rollData = foundry.utils.duplicate(rollData)
} }
/** /**
@ -269,6 +354,10 @@ export default class CthulhuEternalRoll extends Roll {
return `${game.i18n.localize("CTHULHUETERNAL.Label.titleSkill")}` return `${game.i18n.localize("CTHULHUETERNAL.Label.titleSkill")}`
case "weapon": case "weapon":
return `${game.i18n.localize("CTHULHUETERNAL.Label.titleWeapon")}` return `${game.i18n.localize("CTHULHUETERNAL.Label.titleWeapon")}`
case "char":
return `${game.i18n.localize("CTHULHUETERNAL.Label.titleCharacteristic")}`
case "san":
return `${game.i18n.localize("CTHULHUETERNAL.Label.titleSAN")}`
default: default:
return game.i18n.localize("CTHULHUETERNAL.Label.titleStandard") return game.i18n.localize("CTHULHUETERNAL.Label.titleStandard")
} }
@ -306,10 +395,10 @@ export default class CthulhuEternalRoll extends Roll {
*/ */
async _getChatCardData(isPrivate) { async _getChatCardData(isPrivate) {
let cardData = foundry.utils.duplicate(this.options) let cardData = foundry.utils.duplicate(this.options)
cardData.css = [SYSTEM.id, "dice-roll"] cardData.css = [SYSTEM.id, "dice-roll"]
cardData.data = this.data cardData.data = this.data
cardData.diceTotal = this.dice.reduce((t, d) => t + d.total, 0) cardData.diceTotal = this.dice.reduce((t, d) => t + d.total, 0)
cardData.isGM = game.user.isGM cardData.isGM = game.user.isGM
cardData.formula = this.formula cardData.formula = this.formula
cardData.total = this.total cardData.total = this.total
cardData.actorId = this.actorId cardData.actorId = this.actorId
@ -322,8 +411,11 @@ export default class CthulhuEternalRoll extends Roll {
cardData.realDamage = this.realDamage cardData.realDamage = this.realDamage
cardData.isPrivate = isPrivate cardData.isPrivate = isPrivate
cardData.weapon = this.weapon cardData.weapon = this.weapon
cardData.isLowWP = this.isLowWP
console.log(cardData) cardData.isZeroWP = this.isZeroWP
cardData.isExhausted = this.isExhausted
cardData.isNudgedRoll = this.isNudgedRoll
cardData.wpCost = this.wpCost
cardData.cssClass = cardData.css.join(" ") cardData.cssClass = cardData.css.join(" ")
cardData.tooltip = isPrivate ? "" : await this.getTooltip() cardData.tooltip = isPrivate ? "" : await this.getTooltip()
@ -346,9 +438,6 @@ export default class CthulhuEternalRoll extends Roll {
actingCharName: this.actorName, actingCharName: this.actorName,
actingCharImg: this.actorImage, actingCharImg: this.actorImage,
hasTarget: this.hasTarget, hasTarget: this.hasTarget,
targetName: this.targetName,
targetArmor: this.targetArmor,
targetMalus: this.targetMalus,
realDamage: this.realDamage, realDamage: this.realDamage,
...messageData, ...messageData,
}, },

View File

@ -1,80 +0,0 @@
/**
* Enricher qui permet de transformer un texte en un lien de lancer de dés
* Pour une syntaxe de type @jet[x]{y}(z) avec x la caractéristique, y le titre et z l'avantage
* x de type rob, dex, int, per, vol pour les caractéristiques
* et de type oeil, verbe, san, bourse, magie pour les ressources
* y est le titre du jet et permet de décrire l'action
* z est l'avantage du jet, avec pour valeurs possibles : --, -, +, ++
*/
export function setupTextEnrichers() {
CONFIG.TextEditor.enrichers = CONFIG.TextEditor.enrichers.concat([
{
// eslint-disable-next-line no-useless-escape
pattern: /\@jet\[(.+?)\]{(.*?)}\((.*?)\)/gm,
enricher: async (match, options) => {
const a = document.createElement("a")
a.classList.add("ask-roll-journal")
const target = match[1]
const title = match[2]
const avantage = match[3]
let type = "resource"
if (["rob", "dex", "int", "per", "vol"].includes(target)) {
type = "save"
}
let rollAvantage = "normal"
if (avantage) {
switch (avantage) {
case "++":
rollAvantage = "++"
break
case "+":
rollAvantage = "+"
break
case "-":
rollAvantage = "-"
break
case "--":
rollAvantage = "--"
break
default:
break
}
}
a.dataset.rollType = type
a.dataset.rollTarget = target
a.dataset.rollTitle = title
a.dataset.rollAvantage = rollAvantage
a.innerHTML = `
<i class="fas fa-dice-d20"></i> ${getLibelle(target)}${rollAvantage !== "normal" ? rollAvantage : ""}
`
return a
},
},
])
}
const mapLibelles = {
rob: "ROB",
dex: "DEX",
int: "INT",
per: "PER",
vol: "VOL",
oeil: "OEIL",
verbe: "VERBE",
san: "SANTE MENTALE",
bourse: "BOURSE",
magie: "MAGIE",
}
/**
* Retourne le libellé associé à la valeur qui sera affiché dans le journal
* @param {string} value
*/
function getLibelle(value) {
if (mapLibelles[value]) {
return mapLibelles[value]
}
return null
}

View File

@ -1,82 +0,0 @@
export class Macros {
/**
* Creates a macro based on the type of data dropped onto the hotbar.
*
* @param {Object} dropData The data object representing the item dropped.
* @param {string} dropData.type The type of the dropped item (e.g., "Actor", "JournalEntry", "roll").
* @param {string} dropData.uuid The UUID of the dropped item.
* @param {string} [dropData.actorId] The ID of the actor (required if type is "roll").
* @param {string} [dropData.rollType] The type of roll (required if type is "roll").
* @param {string} [dropData.rollTarget] The target of the roll (required if type is "roll").
* @param {string} [dropData.value] The value of the roll (required if type is "roll").
* @param {number} slot The hotbar slot where the macro will be created.
*
* @returns {Promise<void>} A promise that resolves when the macro is created.
*/
static createCthulhuEternalMacro = async function (dropData, slot) {
switch (dropData.type) {
case "Actor":
const actor = await fromUuid(dropData.uuid)
const actorCommand = `game.actors.get("${actor.id}").sheet.render(true)`
this.createMacro(slot, actor.name, actorCommand, actor.img)
break
case "JournalEntry":
const journal = await fromUuid(dropData.uuid)
const journalCommand = `game.journal.get("${journal.id}").sheet.render(true)`
this.createMacro(slot, journal.name, journalCommand, journal.img ? journal.img : "icons/svg/book.svg")
break
case "roll":
const rollCommand =
dropData.rollType === "save"
? `game.actors.get('${dropData.actorId}').system.roll('${dropData.rollType}', '${dropData.rollTarget}', '=');`
: `game.actors.get('${dropData.actorId}').system.roll('${dropData.rollType}', '${dropData.rollTarget}');`
const rollName = `${game.i18n.localize("TENEBRIS.Label.jet")} ${game.i18n.localize(`TENEBRIS.Manager.${dropData.rollTarget}`)}`
this.createMacro(slot, rollName, rollCommand, "icons/svg/d20-grey.svg")
break
case "rollDamage":
const weapon = game.actors.get(dropData.actorId).items.get(dropData.rollTarget)
const rollDamageCommand = `game.actors.get('${dropData.actorId}').system.roll('${dropData.rollType}', '${dropData.rollTarget}');`
const rollDamageName = `${game.i18n.localize("TENEBRIS.Label.jet")} ${weapon.name}`
this.createMacro(slot, rollDamageName, rollDamageCommand, weapon.img)
break
case "rollAttack":
const rollAttackCommand = `game.actors.get('${dropData.actorId}').system.roll('${dropData.rollValue}', '${dropData.rollTarget}');`
const rollAttackName = `${game.i18n.localize("TENEBRIS.Label.jet")} ${dropData.rollTarget}`
this.createMacro(slot, rollAttackName, rollAttackCommand, "icons/svg/d20-grey.svg")
break
default:
// Handle other cases or do nothing
break
}
}
/**
* Create a macro
* All macros are flaged with a tenebris.macro flag at true
* @param {*} slot
* @param {*} name
* @param {*} command
* @param {*} img
*/
static createMacro = async function (slot, name, command, img) {
let macro = game.macros.contents.find((m) => m.name === name && m.command === command)
if (!macro) {
macro = await Macro.create(
{
name: name,
type: "script",
img: img,
command: command,
flags: { "tenebris.macro": true },
},
{ displaySheet: false },
)
game.user.assignHotbarMacro(macro, slot)
}
}
}

View File

@ -9,3 +9,7 @@ export { default as CthulhuEternalBond } from "./bond.mjs"
export { default as CthulhuEternalGear } from "./gear.mjs" export { default as CthulhuEternalGear } from "./gear.mjs"
export { default as CthulhuEternalMotivation } from "./motivation.mjs" export { default as CthulhuEternalMotivation } from "./motivation.mjs"
export { default as CthulhuEternalArchetype } from "./archetype.mjs" export { default as CthulhuEternalArchetype } from "./archetype.mjs"
export { default as CthulhuEternalRitual } from "./ritual.mjs"
export { default as CthulhuEternalVehicle } from "./vehicle.mjs"
export { default as CthulhuEternalTome } from "./tome.mjs"

View File

@ -5,7 +5,8 @@ export default class CthulhuEternalArchetype extends foundry.abstract.TypeDataMo
const requiredInteger = { required: true, nullable: false, integer: true } const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {} const schema = {}
schema.settings = new fields.StringField({ required: true, initial: "modern", choices: SYSTEM.AVAILABLE_SETTINGS }) let setting = game.settings.get("fvtt-cthulhu-eternal", "settings-era") || "modern"
schema.settings = new fields.StringField({ required: true, initial: setting, choices: SYSTEM.AVAILABLE_SETTINGS })
schema.description = new fields.HTMLField({ schema.description = new fields.HTMLField({
required: false, required: false,
@ -19,4 +20,5 @@ export default class CthulhuEternalArchetype extends foundry.abstract.TypeDataMo
/** @override */ /** @override */
static LOCALIZATION_PREFIXES = ["CTHULHUETERNAL.Archetype"] static LOCALIZATION_PREFIXES = ["CTHULHUETERNAL.Archetype"]
} }

View File

@ -6,7 +6,10 @@ export default class CthulhuEternalArmor extends foundry.abstract.TypeDataModel
const requiredInteger = { required: true, nullable: false, integer: true } const requiredInteger = { required: true, nullable: false, integer: true }
schema.description = new fields.HTMLField({ required: true, textSearch: true }) schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.settings = new fields.StringField({ required: true, initial: "modern", choices: SYSTEM.AVAILABLE_SETTINGS })
let setting = game.settings.get("fvtt-cthulhu-eternal", "settings-era") || "modern"
schema.settings = new fields.StringField({ required: true, initial: setting, choices: SYSTEM.AVAILABLE_SETTINGS })
schema.protection = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }) schema.protection = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 })

View File

@ -7,8 +7,12 @@ export default class CthulhuEternalGHear extends foundry.abstract.TypeDataModel
const requiredInteger = { required: true, nullable: false, integer: true } const requiredInteger = { required: true, nullable: false, integer: true }
schema.description = new fields.HTMLField({ required: true, textSearch: true }) schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.settings = new fields.StringField({ required: true, initial: "modern", choices: SYSTEM.AVAILABLE_SETTINGS })
let setting = game.settings.get("fvtt-cthulhu-eternal", "settings-era") || "modern"
schema.settings = new fields.StringField({ required: true, initial: setting, choices: SYSTEM.AVAILABLE_SETTINGS })
schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 })
schema.state = new fields.StringField({ required: true, initial: "pristine", choices: SYSTEM.EQUIPMENT_STATES })
return schema return schema
} }

View File

@ -5,7 +5,8 @@ export default class CthulhuEternalMentalDisorder extends foundry.abstract.TypeD
const schema = {} const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true }) schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.cured = new fields.BooleanField({ required: true, initial: false })
return schema return schema
} }

View File

@ -33,8 +33,8 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
}) })
schema.hp = new fields.SchemaField({ schema.hp = new fields.SchemaField({
value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), value: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }),
max: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), max: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }),
stunned: new fields.BooleanField({ required: true, initial: false }) stunned: new fields.BooleanField({ required: true, initial: false })
}) })
@ -44,16 +44,23 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
recovery: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), recovery: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
violence: new fields.ArrayField(new fields.BooleanField(), { required: true, initial: [false, false, false], min:3, max:3}), violence: new fields.ArrayField(new fields.BooleanField(), { required: true, initial: [false, false, false], min:3, max:3}),
helplessness: new fields.ArrayField(new fields.BooleanField(), { required: true, initial: [false, false, false], min:3, max:3 }), helplessness: new fields.ArrayField(new fields.BooleanField(), { required: true, initial: [false, false, false], min:3, max:3 }),
breakingPoint: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) breakingPoint: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
insanity: new fields.StringField({ required: true, nullable: false, initial: "none", choices:SYSTEM.INSANITY }),
}) })
schema.damageBonus = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) schema.damageBonus = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
schema.resources = new fields.SchemaField({ schema.resources = new fields.SchemaField({
value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), // Unused but kept for compatibility
permanentRating: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
hand: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), hand: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
currentHand: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
stowed: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), stowed: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
storage: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) currentStowed: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
storage: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
currentStorage: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
checks: new fields.ArrayField(new fields.BooleanField(), { required: true, initial: [false, false, false], min:3, max:3 }),
nbValidChecks: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
}) })
schema.biodata = new fields.SchemaField({ schema.biodata = new fields.SchemaField({
@ -66,6 +73,8 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
eyes: new fields.StringField({ required: true, nullable: false, initial: "" }), eyes: new fields.StringField({ required: true, nullable: false, initial: "" }),
hair: new fields.StringField({ required: true, nullable: false, initial: "" }), hair: new fields.StringField({ required: true, nullable: false, initial: "" }),
harshness: new fields.StringField({ required: true, nullable: false, initial: "normal", choices:SYSTEM.HARSHNESS }), harshness: new fields.StringField({ required: true, nullable: false, initial: "normal", choices:SYSTEM.HARSHNESS }),
adaptedToViolence: new fields.BooleanField({ required: true, initial: false }),
adaptedToHelplessness: new fields.BooleanField({ required: true, initial: false })
}) })
return schema return schema
@ -90,18 +99,13 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
let unnatural = this.parent.items.find(i => i.type === "skill" && i.name.toLowerCase() === game.i18n.localize("CTHULHUETERNAL.Skill.Unnatural").toLowerCase()) let unnatural = this.parent.items.find(i => i.type === "skill" && i.name.toLowerCase() === game.i18n.localize("CTHULHUETERNAL.Skill.Unnatural").toLowerCase())
let minus = 0 let minus = 0
if (unnatural) { if (unnatural) {
minus = unnatural.data.skillTotal minus = unnatural.system.skillTotal
} }
let maxSan = Math.max(99 - minus, 0) let maxSan = Math.max(99 - minus, 0)
if ( this.san.max !== maxSan) { if ( this.san.max !== maxSan) {
updates[`system.san.max`] = maxSan updates[`system.san.max`] = maxSan
} }
let bp = Math.max(this.san.value - this.characteristics.pow.value, 0)
if ( this.san.breakingPoint !== bp) {
updates[`system.san.breakingPoint`] = bp
}
let recoverySan = this.characteristics.pow.value * 5 let recoverySan = this.characteristics.pow.value * 5
if (recoverySan > this.san.max) { if (recoverySan > this.san.max) {
recoverySan = this.san.max recoverySan = this.san.max
@ -137,12 +141,30 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
updates[`system.hp.value`] = this.hp.max updates[`system.hp.value`] = this.hp.max
} }
if (this.resources.permanentRating < 0) {
updates[`system.resources.permanentRating`] = 0
}
let resourceIndex = Math.max(Math.min(this.resources.permanentRating, 20), 0)
let breakdown = SYSTEM.RESOURCE_BREAKDOWN[resourceIndex]
if (this.resources.hand !== breakdown.hand) {
updates[`system.resources.hand`] = breakdown.hand
}
if (this.resources.stowed !== breakdown.stowed) {
updates[`system.resources.stowed`] = breakdown.stowed
}
if (this.resources.storage !== breakdown.storage) {
updates[`system.resources.storage`] = breakdown.storage + (this.resources.permanentRating - resourceIndex)
}
if (this.resources.nbValidChecks !== breakdown.checks) {
updates[`system.resources.nbValidChecks`] = breakdown.checks
}
if (Object.keys(updates).length > 0) { if (Object.keys(updates).length > 0) {
this.parent.update(updates) this.parent.update(updates)
} }
} }
isLowWP() { isLowWP() {
return this.wp.value <= 2 return this.wp.value <= 2
} }
@ -151,6 +173,32 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
return this.wp.value === 0 return this.wp.value === 0
} }
isExhausted() {
return this.wp.exhausted
}
modifyWP(value) {
let updates = {}
let wp = Math.max(Math.min(this.wp.value + value, this.wp.max), 0)
if ( this.wp.value !== wp) {
updates[`system.wp.value`] = wp
}
if (Object.keys(updates).length > 0) {
this.parent.update(updates)
}
}
setBP() {
let updates = {}
let bp = Math.max(this.san.value - this.characteristics.pow.value, 0)
if ( this.san.breakingPoint !== bp) {
updates[`system.san.breakingPoint`] = bp
}
if (Object.keys(updates).length > 0) {
this.parent.update(updates)
}
}
/** */ /** */
/** /**
* Rolls a dice for a character. * Rolls a dice for a character.
@ -167,6 +215,7 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
rollItem, rollItem,
isLowWP: this.isLowWP(), isLowWP: this.isLowWP(),
isZeroWP: this.isZeroWP(), isZeroWP: this.isZeroWP(),
isExhausted: this.isExhausted(),
actorId: this.parent.id, actorId: this.parent.id,
actorName: this.parent.name, actorName: this.parent.name,
actorImage: this.parent.img, actorImage: this.parent.img,

24
module/models/ritual.mjs Normal file
View File

@ -0,0 +1,24 @@
import { SYSTEM } from "../config/system.mjs"
export default class CthulhuEternalRitual extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {}
schema.ritualType = new fields.StringField({ required: true, initial: "simple", choices: SYSTEM.RITUAL_TYPES })
schema.studyTime = new fields.StringField({ required: true, initial: "X days", textSearch: true })
schema.studySAN = new fields.StringField({ required: true, initial: "1d4", textSearch: true })
schema.activationTime = new fields.StringField({ required: true, initial: "X turns", textSearch: true })
schema.activationWP = new fields.StringField({ required: true, initial: "1d4", textSearch: true })
schema.activationSAN = new fields.StringField({ required: true, initial: "1d6", textSearch: true })
schema.description = new fields.HTMLField({ required: true, textSearch: true })
return schema
}
/** @override */
static LOCALIZATION_PREFIXES = ["CTHULHUETERNAL.Ritual"]
}

View File

@ -6,7 +6,9 @@ export default class CthulhuEternalSkill extends foundry.abstract.TypeDataModel
const requiredInteger = { required: true, nullable: false, integer: true } const requiredInteger = { required: true, nullable: false, integer: true }
schema.description = new fields.HTMLField({ required: true, textSearch: true }) schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.settings = new fields.StringField({ required: true, initial: "modern", choices: SYSTEM.AVAILABLE_SETTINGS })
let setting = game.settings.get("fvtt-cthulhu-eternal", "settings-era") || "modern"
schema.settings = new fields.StringField({ required: true, initial: setting, choices: SYSTEM.AVAILABLE_SETTINGS })
schema.base = new fields.StringField({ required: true, initial: "0" }) schema.base = new fields.StringField({ required: true, initial: "0" })
schema.bonus = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }) schema.bonus = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
@ -20,7 +22,6 @@ export default class CthulhuEternalSkill extends foundry.abstract.TypeDataModel
/** @override */ /** @override */
static LOCALIZATION_PREFIXES = ["CTHULHUETERNAL.Skill"] static LOCALIZATION_PREFIXES = ["CTHULHUETERNAL.Skill"]
prepareDerivedData() { prepareDerivedData() {
super.prepareDerivedData(); super.prepareDerivedData();
this.skillTotal = this.computeScore(); this.skillTotal = this.computeScore();

64
module/models/tome.mjs Normal file
View File

@ -0,0 +1,64 @@
import { SYSTEM } from "../config/system.mjs";
export default class CthulhuEternalTome extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
const schema = {};
let setting = game.settings.get("fvtt-cthulhu-eternal", "settings-era") || "modern"
schema.minimumEra = new fields.StringField({ required: true, initial: setting, choices: SYSTEM.AVAILABLE_SETTINGS })
schema.creationDate = new fields.StringField({
required: true,
initial: "",
textSearch: true
});
// Language field
schema.language = new fields.StringField({
required: true,
initial: "Latin",
textSearch: true
});
// studyTime field
schema.studyTime = new fields.StringField({
required: true,
initial: "X days",
textSearch: true
});
// SAN loss field
schema.sanLoss = new fields.StringField({
required: true,
initial: "1d4",
textSearch: true
});
// Unnatural skill field
schema.unnaturalSkill = new fields.StringField({
required: true,
initial: "1d4",
textSearch: true
});
schema.rituals = new fields.StringField({
required: true,
initial: "",
textSearch: true
});
schema.otherBenefits = new fields.StringField({
required: true,
initial: "",
textSearch: true
});
schema.description = new fields.HTMLField({ required: true, textSearch: true })
return schema;
}
/** @override */
static LOCALIZATION_PREFIXES = ["CTHULHUETERNAL.Tome"];
}

35
module/models/vehicle.mjs Normal file
View File

@ -0,0 +1,35 @@
import { SYSTEM } from "../config/system.mjs"
import CthulhuEternalRoll from "../documents/roll.mjs"
export default class CthulhuEternalVehicle extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {}
let setting = game.settings.get("fvtt-cthulhu-eternal", "settings-era") || "modern"
schema.settings = new fields.StringField({ required: true, initial: setting, choices: SYSTEM.AVAILABLE_SETTINGS })
schema.hp = new fields.SchemaField({
value: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }),
max: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 })
})
schema.armor = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
schema.surfaceSpeed = new fields.StringField({ required: true, initial: "slow", choices: SYSTEM.VEHICLE_SPEED })
schema.airSpeed = new fields.StringField({ required: true, initial: "none", choices: SYSTEM.VEHICLE_SPEED })
schema.state = new fields.StringField({ required: true, initial: "pristine", choices: SYSTEM.EQUIPMENT_STATES })
schema.crew = new fields.ArrayField(new fields.StringField(), { required: false, initial: [], min:0 })
schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 })
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.notes = new fields.HTMLField({ required: true, textSearch: true })
return schema
}
/** @override */
static LOCALIZATION_PREFIXES = ["CTHULHUETERNAL.Vehicle"]
}

View File

@ -7,7 +7,9 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
const requiredInteger = { required: true, nullable: false, integer: true } const requiredInteger = { required: true, nullable: false, integer: true }
schema.description = new fields.HTMLField({ required: true, textSearch: true }) schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.settings = new fields.StringField({ required: true, initial: "modern", choices: SYSTEM.AVAILABLE_SETTINGS })
let setting = game.settings.get("fvtt-cthulhu-eternal", "settings-era") || "modern"
schema.settings = new fields.StringField({ required: true, initial: setting, choices: SYSTEM.AVAILABLE_SETTINGS })
schema.weaponType = new fields.StringField({ required: true, initial: "melee", choices: SYSTEM.WEAPON_TYPE }) schema.weaponType = new fields.StringField({ required: true, initial: "melee", choices: SYSTEM.WEAPON_TYPE })
schema.damage = new fields.StringField({required: true, initial: "1d6"}) schema.damage = new fields.StringField({required: true, initial: "1d6"})
@ -17,6 +19,7 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
schema.killRadius = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.killRadius = new fields.NumberField({ required: true, initial: 0, min: 0 })
schema.armorPiercing = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.armorPiercing = new fields.NumberField({ required: true, initial: 0, min: 0 })
schema.weaponSubtype = new fields.StringField({ required: true, initial: "basicfirearm", choices: SYSTEM.WEAPON_SUBTYPE }) schema.weaponSubtype = new fields.StringField({ required: true, initial: "basicfirearm", choices: SYSTEM.WEAPON_SUBTYPE })
schema.state = new fields.StringField({ required: true, initial: "pristine", choices: SYSTEM.EQUIPMENT_STATES })
schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 })

View File

@ -9,24 +9,5 @@
*/ */
export function handleSocketEvent({ action = null, data = {} } = {}) { export function handleSocketEvent({ action = null, data = {} } = {}) {
console.debug("handleSocketEvent", action, data) console.debug("handleSocketEvent", action, data)
switch (action) {
case "fortune":
return CthulhuEternalFortune.handleSocketEvent(data)
case "askRoll":
return _askRoll(data)
}
} }
/**
* Handles the socket event to ask for a roll.
*
* @param {Object} [options={}] The options object.
* @param {string} [options.userId] The ID of the user who initiated the roll.
*/
export function _askRoll({ userId } = {}) {
console.debug(`handleSocketEvent _askRoll from ${userId} !`)
const currentUser = game.user._id
if (userId === currentUser) {
foundry.audio.AudioHelper.play({ src: "/systems/fvtt-cthulhu-eternal/sounds/drums.wav", volume: 0.8, autoplay: true, loop: false }, false)
}
}

View File

@ -1,11 +1,13 @@
import CthulhuEternalRoll from "./documents/roll.mjs"
export default class CthulhuEternalUtils { export default class CthulhuEternalUtils {
static registerSettings() { static registerSettings() {
game.settings.register("fvtt-cthulhu-eternal", "settings-era", { game.settings.register("fvtt-cthulhu-eternal", "settings-era", {
name: game.i18n.localize("CHTUHLUETERNAL.Settings.era"), name: game.i18n.localize("CTHULHUETERNAL.Settings.era"),
hint: game.i18n.localize("CHTUHLUETERNAL.Settings.eraHint"), hint: game.i18n.localize("CTHULHUETERNAL.Settings.eraHint"),
default: true, default: "jazz",
scope: "world", scope: "world",
type: String, type: String,
choices: SYSTEM.AVAILABLE_SETTINGS, choices: SYSTEM.AVAILABLE_SETTINGS,
@ -177,12 +179,82 @@ export default class CthulhuEternalUtils {
} }
static async nudgeRoll(rollMessage) {
let dialogContext = rollMessage.rolls[0]?.options
let actor = game.actors.get(dialogContext.actorId)
dialogContext.wpValue = actor.system.wp.value
dialogContext.rollResultIndex = rollMessage.rolls[0].total - 1
dialogContext.minValue = Math.max(rollMessage.rolls[0].total - (dialogContext.wpValue * 5), 1)
dialogContext.maxValue = Math.min(rollMessage.rolls[0].total + (dialogContext.wpValue * 5), 100)
dialogContext.wpCost = 0
// Build options table for the select operator between minValue and maxValue
dialogContext.nudgeOptions = Array.from({ length: dialogContext.maxValue - dialogContext.minValue + 1 }, (_, i) => dialogContext.minValue + i)
console.log(dialogContext)
const content = await renderTemplate("systems/fvtt-cthulhu-eternal/templates/nudge-dialog.hbs", dialogContext)
const title = game.i18n.localize("CTHULHUETERNAL.Roll.nudgeRoll")
const rollContext = await foundry.applications.api.DialogV2.wait({
window: { title: title },
classes: ["fvtt-cthulhu-eternal"],
content,
buttons: [
{
action: "apply",
label: game.i18n.localize("CTHULHUETERNAL.Roll.applyNudge"),
callback: (event, button, dialog) => {
const output = Array.from(button.form.elements).reduce((obj, input) => {
if (input.name) obj[input.name] = input.value
return obj
}, {})
return output
},
},
{
action: "cancel",
label: game.i18n.localize("CTHULHUETERNAL.Roll.cancel"),
callback: (event, button, dialog) => { }
}
],
actions: {
},
rejectClose: false, // Click on Close button will not launch an error
render: (event, dialog) => {
$(".nudged-score-select").change(event => {
dialogContext.nudgedValue = Number(event.target.value)+1
dialogContext.wpCost = Math.ceil(Math.abs(rollMessage.rolls[0].total - dialogContext.nudgedValue) / 5)
$("#nudged-wp-cost").val(dialogContext.wpCost)
})
}
})
// If the user cancels the dialog, exit
if (rollContext === null || dialogContext.wpCost === 0) {
return
}
const roll = new CthulhuEternalRoll(String(dialogContext.nudgedValue))
await roll.evaluate()
roll.options = dialogContext
roll.options.isNudgedRoll = true
roll.options.isNudge = false
roll.displayRollResult(roll, dialogContext, dialogContext.rollData)
roll.toMessage()
actor.system.modifyWP(-dialogContext.wpCost)
}
static setupCSSRootVariables() { static setupCSSRootVariables() {
const era = game.settings.get("fvtt-cthulhu-eternal", "settings-era") const era = game.settings.get("fvtt-cthulhu-eternal", "settings-era")
let eraCSS = SYSTEM.ERA_CSS[era]; let eraCSS = SYSTEM.ERA_CSS[era];
if (!eraCSS) eraCSS = SYSTEM.ERA_CSS["jazz"]; if (!eraCSS) eraCSS = SYSTEM.ERA_CSS["jazz"];
document.documentElement.style.setProperty('--font-size-standard', eraCSS.baseFontSize);
document.documentElement.style.setProperty('--font-size-title', eraCSS.titleFontSize);
document.documentElement.style.setProperty('--font-size-result', eraCSS.titleFontSize);
document.documentElement.style.setProperty('--font-primary', eraCSS.primaryFont); document.documentElement.style.setProperty('--font-primary', eraCSS.primaryFont);
document.documentElement.style.setProperty('--font-secondary', eraCSS.secondaryFont); document.documentElement.style.setProperty('--font-secondary', eraCSS.secondaryFont);
document.documentElement.style.setProperty('--font-title', eraCSS.titleFont); document.documentElement.style.setProperty('--font-title', eraCSS.titleFont);

Binary file not shown.

View File

View File

@ -0,0 +1 @@
MANIFEST-000128

0
packs-system/skills/LOCK Normal file
View File

8
packs-system/skills/LOG Normal file
View File

@ -0,0 +1,8 @@
2025/02/07-07:58:04.988627 7ffae7fff6c0 Recovering log #126
2025/02/07-07:58:04.998629 7ffae7fff6c0 Delete type=3 #124
2025/02/07-07:58:04.998698 7ffae7fff6c0 Delete type=0 #126
2025/02/07-08:34:42.926911 7ffae6bff6c0 Level-0 table #131: started
2025/02/07-08:34:42.926943 7ffae6bff6c0 Level-0 table #131: 0 bytes OK
2025/02/07-08:34:42.933490 7ffae6bff6c0 Delete type=0 #129
2025/02/07-08:34:42.933666 7ffae6bff6c0 Manual compaction at level-0 from '!folders!DD8331Hda4rhvEf9' @ 72057594037927935 : 1 .. '!items!zplzTG30QXHURusr' @ 0 : 0; will stop at (end)
2025/02/07-08:34:42.944681 7ffae6bff6c0 Manual compaction at level-1 from '!folders!DD8331Hda4rhvEf9' @ 72057594037927935 : 1 .. '!items!zplzTG30QXHURusr' @ 0 : 0; will stop at (end)

View File

@ -0,0 +1,8 @@
2025/02/06-23:17:39.180197 7ffaecbf96c0 Recovering log #122
2025/02/06-23:17:39.191385 7ffaecbf96c0 Delete type=3 #120
2025/02/06-23:17:39.191461 7ffaecbf96c0 Delete type=0 #122
2025/02/07-00:19:54.566098 7ffae6bff6c0 Level-0 table #127: started
2025/02/07-00:19:54.566176 7ffae6bff6c0 Level-0 table #127: 0 bytes OK
2025/02/07-00:19:54.572437 7ffae6bff6c0 Delete type=0 #125
2025/02/07-00:19:54.583220 7ffae6bff6c0 Manual compaction at level-0 from '!folders!DD8331Hda4rhvEf9' @ 72057594037927935 : 1 .. '!items!zplzTG30QXHURusr' @ 0 : 0; will stop at (end)
2025/02/07-00:19:54.596307 7ffae6bff6c0 Manual compaction at level-1 from '!folders!DD8331Hda4rhvEf9' @ 72057594037927935 : 1 .. '!items!zplzTG30QXHURusr' @ 0 : 0; will stop at (end)

Binary file not shown.

View File

@ -44,9 +44,19 @@
src: url("../assets/fonts/Volkhov-Regular.ttf") format("truetype"); src: url("../assets/fonts/Volkhov-Regular.ttf") format("truetype");
} }
@font-face {
font-family: "ChantelliAntiqua";
src: url("../assets/fonts/Chantelli_Antiqua.ttf") format("truetype");
}
@font-face { @font-face {
font-family: "IMFell"; font-family: "IMFell";
src: url("../assets/fonts/IMFell.ttf") format("truetype"); src: url("../assets/fonts/IMFeDPrm28P.ttf") format("truetype");
}
@font-face {
font-family: "SailRegular";
src: url("../assets/fonts/Sail-Regular.ttf") format("truetype");
} }
@font-face { @font-face {

View File

@ -4,6 +4,7 @@
.fvtt-cthulhu-eternal { .fvtt-cthulhu-eternal {
@import "mixins.less"; @import "mixins.less";
@import "protagonist.less"; @import "protagonist.less";
@import "vehicle.less";
@import "skill.less"; @import "skill.less";
@import "injury.less"; @import "injury.less";
@import "weapon.less"; @import "weapon.less";
@ -15,6 +16,8 @@
@import "gear.less"; @import "gear.less";
@import "arcane.less"; @import "arcane.less";
@import "archetype.less"; @import "archetype.less";
@import "ritual.less";
@import "tome.less";
} }
@import "roll.less"; @import "roll.less";

View File

@ -1,19 +1,28 @@
:root { :root {
--font-size-standard: 0.9rem; --font-size-standard: 0.9rem;
--font-size-result: 1.4rem;
--background-image-base: linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8)), --background-image-base: linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8)),
url("../assets/ui/jazz_background_main.webp"); url("../assets/ui/jazz_background_main.webp");
/*--background-image-base: url("../assets/ui/jazzage_background_main.webp");*/
--font-primary: "RozhaOne"; --font-primary: "RozhaOne";
--font-secondary: "RozhaOne"; --font-secondary: "RozhaOne";
--font-title: "Broadway"; --font-title: "Broadway";
--logo-standard: url("../assets/logos/reanimated-ce-logo.webp"); --logo-standard: url("../assets/logos/reanimated-ce-logo.webp");
--color-success: darkgreen; --color-success: rgb(15, 122, 15);
--color-failure: darkred; --color-failure: darkred;
--color-critical-success: lightgreen; --color-warning: darkorange;
--color-critical-failure: lightcoral; --color-critical-success: rgb(21, 39, 204);
--color-critical-failure: rgb(141, 32, 231);
--img-icon-color-filter: brightness(0) saturate(100%) invert(52%) sepia(9%) saturate(2368%) hue-rotate(360deg) brightness(86%) contrast(84%); --img-icon-color-filter: brightness(0) saturate(100%) invert(52%) sepia(9%) saturate(2368%) hue-rotate(360deg) brightness(86%) contrast(84%);
} }
.d100 {
width: 18px;
height: 18px;
color: black;
border-width: 0px;
filter: var(--img-icon-color-filter);
}
.item .thumbnail, .item .thumbnail,
.item-img { .item-img {
/*filter: invert(90%) sepia(10%) saturate(1215%) hue-rotate(55deg) brightness(93%) contrast(89%);*/ /*filter: invert(90%) sepia(10%) saturate(1215%) hue-rotate(55deg) brightness(93%) contrast(89%);*/

View File

@ -21,7 +21,7 @@
} }
input[name="name"] { input[name="name"] {
height: 50px; height: 40px;
margin-right: 10px; margin-right: 10px;
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1); font-size: calc(var(--font-size-standard) * 1);
@ -30,8 +30,8 @@
} }
fieldset { fieldset {
margin-bottom: 5px; margin-bottom: 4px;
border-radius: 5px; border-radius: 4px;
} }
.form-fields { .form-fields {
@ -57,13 +57,20 @@
.protagonist-sheet-common { .protagonist-sheet-common {
label { label {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.0);
}
}
.vehicle-sheet-common {
label {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.0);
} }
} }
.item-sheet-common { .item-sheet-common {
.form-fields { .form-fields {
padding-top: 5px; padding-top: 4px;
} }
label { label {

View File

@ -34,6 +34,25 @@
} }
} }
.protagonist-hp {
gap: 2px;
align-items: center;
input {
flex: none;
width: 2rem;
margin-left: 4px;
}
.damage-bonus {
font-size: calc(var(--font-size-standard) * 0.8);
}
.hp-separator {
font-size: calc(var(--font-size-standard) * 1.2);
display: flex;
align-items: center;
justify-content: center;
}
}
.protagonist-dv, .protagonist-dv,
.protagonist-dmax { .protagonist-dmax {
.form-fields { .form-fields {
@ -62,81 +81,93 @@
display: flex; display: flex;
input { input {
font-family: var(--font-title); font-family: var(--font-title);
font-size: calc(var(--font-size-standard) * 1.4); font-size: var(--font-size-title);
width: 400px; width: 400px;
} }
} }
.san { .san {
align-content: flex-start;
input { input {
min-width: 2.2rem; min-width: 2.2rem;
max-width: 2.2rem;
margin-bottom: 4px;
}
select {
min-width: 6rem;
max-width: 6rem;
}
.rollable:hover,
.rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer;
font-size: 0.9rem;
}
.button {
min-width: 4rem;
max-width: 4rem;
} }
.san-checkbox { .san-checkbox {
min-width: 1rem; min-width: 1rem;
max-width: 1rem; max-width: 1rem;
} }
.label-field { .label-short-field {
flex-grow: 0; font-size: 0.9rem;
max-width: 3rem;
min-width: 3rem;
flex-grow: 1;
}
.label-recovery {
margin-left: 4px; margin-left: 4px;
} }
.label-field {
font-size: 0.9rem;
max-width: 6rem;
min-width: 6rem;
flex-grow: 1;
}
.label-bp {
flex-grow: 1;
max-width: 3rem;
min-width: 3rem;
margin-left: 4px;
}
.label-insanity {
flex-grow: 1;
margin-left: 4px;
max-width: 8rem;
min-width: 8rem;
}
.spacing { .spacing {
margin-left: 4px; margin-left: 4px;
} }
.d100 {
flex: 0;
}
} }
.willpower { .willpower {
input { input {
min-width: 2.2rem; min-width: 2.4rem;
max-width: 2.4rem;
} }
.label-field { input[type="checkbox"] {
flex-grow: 0; min-width: 1rem;
margin-left: 4px; max-width: 1rem;
} }
.checkbox { .label-field {
flex-grow: 1;
margin-left: 4px;
max-width: 5rem;
min-width: 5rem;
font-size: 0.9rem;
}
.checkbox {
flex-grow: 0;
min-width: 1rem; min-width: 1rem;
max-width: 1rem; max-width: 1rem;
} }
} }
.protagonist-infos { label {
display: flex; min-width: 120px;
flex-direction: column;
gap: 4px;
label {
min-width: 120px;
}
.protagonist-hp {
display: flex;
gap: 2px;
align-items: center;
.protagonist-hp-value {
.form-fields input {
flex: none;
width: 50px;
margin-left: 4px;
font-size: calc(var(--font-size-standard) * 1.4);
}
}
.protagonist-hp-max {
clear: both;
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 3px 0;
align-items: center;
input {
width: 50px;
text-align: center;
font-size: calc(var(--font-size-standard) * 1.4);
}
}
.hp-separator {
font-size: calc(var(--font-size-standard) * 1.2);
display: flex;
align-items: center;
justify-content: center;
}
}
} }
} }
} }
@ -164,12 +195,24 @@
text-shadow: 0 0 8px var(--color-shadow-primary); text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer; cursor: pointer;
} }
.rollable {
min-width: 3rem;
max-width: 3rem;
}
.char-text {
margin-left: 0.5rem;
}
.d100 {
flex: 0;
max-width: 0.6rem;
}
.form-group { .form-group {
flex: 1; flex: 0;
padding-left: 5px; padding-left: 5px;
.form-fields { .form-fields {
font-size: 1.1rem;
flex: none; flex: none;
width: 70px; width: 40px;
} }
} }
} }
@ -195,34 +238,39 @@
.field-label { .field-label {
margin-left: 8px; margin-left: 8px;
} }
.biodata {
.adapted {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px;
label {
min-width: 20rem;
}
}
.resources {
display: grid; display: grid;
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
gap: 8px; gap: 8px;
label {
min-width: 8rem;
}
} }
.motivations {
.features,
.biodata {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
gap: 4px; gap: 8px;
.motivation { label {
min-width: 3rem;
}
.feature {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 4px; gap: 4px;
min-width: 14rem; min-width: 18rem;
max-width: 14rem; max-width: 18rem;
.controls {
min-width: 2rem;
max-width: 2rem;
}
.name {
min-width: 8rem;
max-width: 8rem;
}
.item-img {
width: 32px;
height: 32px;
margin: 4px 0 0 0;
}
} }
} }
} }
@ -245,24 +293,30 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: 4px; gap: 4px;
min-width: 10rem; margin-left: 4px;
max-width: 10rem; min-width: 12.3rem;
max-width: 12.3rem;
.rollable:hover, .rollable:hover,
.rollable:focus { .rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary); text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer; cursor: pointer;
} }
.controls { .controls {
min-width: 2rem; font-size: 0.7rem;
max-width: 2rem; min-width: 1.8rem;
max-width: 1.8rem;
}
.score {
min-width: 1.2rem;
max-width: 1.2rem;
} }
.name { .name {
min-width: 8rem; min-width: 10rem;
max-width: 8rem; max-width: 10rem;
} }
.item-img { .item-img {
width: 32px; width: 24px;
height: 32px; height: 24px;
margin: 4px 0 0 0; margin: 4px 0 0 0;
} }
} }
@ -279,6 +333,7 @@
padding-left: 5px; padding-left: 5px;
} }
} }
.bonds { .bonds {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
@ -287,31 +342,60 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: 4px; gap: 4px;
min-width: 16rem; min-width: 18rem;
max-width: 16rem; max-width: 18rem;
.controls { .controls {
min-width: 2rem; font-size: 0.7rem;
max-width: 2rem; min-width: 1.8rem;
max-width: 1.8rem;
} }
.name { .name {
min-width: 12rem; min-width: 12rem;
max-width: 12rem; max-width: 12rem;
} }
.type { .type {
min-width: 4rem; min-width: 6rem;
max-width: 4rem; max-width: 6rem;
} }
.level { .level {
min-width: 2rem; min-width: 2rem;
max-width: 2rem; max-width: 2rem;
} }
.item-img { .item-img {
width: 32px; width: 24px;
height: 32px; height: 24px;
margin: 4px 0 0 0; margin: 4px 0 0 0;
} }
} }
} }
.motivations {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 4px;
.motivation {
display: flex;
align-items: center;
gap: 4px;
min-width: 14rem;
max-width: 14rem;
.controls {
font-size: 0.7rem;
min-width: 1.8rem;
max-width: 1.8rem;
}
.name {
min-width: 12rem;
max-width: 12rem;
}
.item-img {
width: 24px;
height: 24px;
margin: 4px 0 0 0;
}
}
}
.mentaldisorders { .mentaldisorders {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
@ -320,23 +404,29 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: 4px; gap: 4px;
min-width: 16rem; min-width: 18rem;
max-width: 16rem; max-width: 18rem;
.controls { .controls {
min-width: 2rem; font-size: 0.7rem;
max-width: 2rem; min-width: 1.8rem;
max-width: 1.8rem;
} }
.name { .name {
min-width: 14rem; min-width: 14rem;
max-width: 14rem; max-width: 14rem;
} }
.cured {
min-width: 5rem;
max-width: 5rem;
}
.item-img { .item-img {
width: 32px; width: 24px;
height: 32px; height: 24px;
margin: 4px 0 0 0; margin: 4px 0 0 0;
} }
} }
} }
.injuries { .injuries {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
@ -348,16 +438,17 @@
min-width: 16rem; min-width: 16rem;
max-width: 16rem; max-width: 16rem;
.controls { .controls {
min-width: 2rem; font-size: 0.7rem;
max-width: 2rem; min-width: 1.8rem;
max-width: 1.8rem;
} }
.name { .name {
min-width: 14rem; min-width: 14rem;
max-width: 14rem; max-width: 14rem;
} }
.item-img { .item-img {
width: 32px; width: 24px;
height: 32px; height: 24px;
margin: 4px 0 0 0; margin: 4px 0 0 0;
} }
} }
@ -383,27 +474,28 @@
align-items: center; align-items: center;
gap: 4px; gap: 4px;
min-width: 13rem; min-width: 13rem;
max-width: 13srem; max-width: 13rem;
.rollable:hover, .rollable:hover,
.rollable:focus { .rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary); text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer; cursor: pointer;
} }
.controls { .controls {
min-width: 2rem; font-size: 0.7rem;
max-width: 2rem; min-width: 1.8rem;
max-width: 1.8rem;
} }
.damage { .damage {
min-width: 5rem; min-width: 6rem;
max-width: 5rem; max-width: 6rem;
} }
.name { .name {
min-width: 8rem; min-width: 10rem;
max-width: 8rem; max-width: 10rem;
} }
.item-img { .item-img {
width: 32px; width: 24px;
height: 32px; height: 24px;
margin: 4px 0 0 0; margin: 4px 0 0 0;
} }
} }
@ -417,15 +509,16 @@
align-items: center; align-items: center;
gap: 4px; gap: 4px;
min-width: 13rem; min-width: 13rem;
max-width: 13srem; max-width: 13rem;
.rollable:hover, .rollable:hover,
.rollable:focus { .rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary); text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer; cursor: pointer;
} }
.controls { .controls {
min-width: 2rem; font-size: 0.7rem;
max-width: 2rem; min-width: 1.8rem;
max-width: 1.8rem;
} }
.protection { .protection {
min-width: 5rem; min-width: 5rem;
@ -436,12 +529,13 @@
max-width: 8rem; max-width: 8rem;
} }
.item-img { .item-img {
width: 32px; width: 24px;
height: 32px; height: 24px;
margin: 4px 0 0 0; margin: 4px 0 0 0;
} }
} }
} }
.gears { .gears {
display: grid; display: grid;
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
@ -451,27 +545,88 @@
align-items: center; align-items: center;
gap: 4px; gap: 4px;
min-width: 13rem; min-width: 13rem;
max-width: 13srem; max-width: 13rem;
.rollable:hover, .rollable:hover,
.rollable:focus { .rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary); text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer; cursor: pointer;
} }
.controls { .controls {
min-width: 2rem; font-size: 0.7rem;
max-width: 2rem; min-width: 1.8rem;
} max-width: 1.8rem;
.damage {
min-width: 5rem;
max-width: 5rem;
} }
.name { .name {
min-width: 8rem; min-width: 10rem;
max-width: 8rem; max-width: 10rem;
} }
.item-img { .item-img {
width: 32px; width: 24px;
height: 32px; height: 24px;
margin: 4px 0 0 0;
}
}
}
.rituals {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 4px;
.ritual {
display: flex;
align-items: center;
gap: 4px;
min-width: 20rem;
max-width: 20rem;
.rollable:hover,
.rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer;
}
.controls {
font-size: 0.7rem;
min-width: 1.8rem;
max-width: 1.8rem;
}
.name {
min-width: 17rem;
max-width: 17rem;
}
.item-img {
width: 24px;
height: 24px;
margin: 4px 0 0 0;
}
}
}
.tomes {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 4px;
.tome {
display: flex;
align-items: center;
gap: 4px;
min-width: 20rem;
max-width: 20rem;
.rollable:hover,
.rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer;
}
.controls {
font-size: 0.7rem;
min-width: 1.8rem;
max-width: 1.8rem;
}
.name {
min-width: 17rem;
max-width: 17rem;
}
.item-img {
width: 24px;
height: 24px;
margin: 4px 0 0 0; margin: 4px 0 0 0;
} }
} }

22
styles/ritual.less Normal file
View File

@ -0,0 +1,22 @@
.ritual-content {
.sheet-common();
.item-sheet-common();
fieldset {
margin-top: 8px;
background-color: var(--color-light-1);
}
.header {
background-color: var(--color-light-1);
display: flex;
img {
width: 50px;
height: 50px;
}
}
label {
flex: 10%;
}
}

View File

@ -31,11 +31,18 @@
border: none; border: none;
background-color: rgba(0, 0, 0, 0.1); background-color: rgba(0, 0, 0, 0.1);
color: var(--color-dark-2); color: var(--color-dark-2);
width: 60px; width: 4rem;
text-align: center; text-align: center;
} }
} }
.red-warning {
color: var(--color-failure);
}
.orange-warning {
color: var(--color-warning);
}
.dialog-damage { .dialog-damage {
display: flex; display: flex;
@ -86,25 +93,30 @@
font-family: var(--font-primary); font-family: var(--font-primary);
font-size: calc(var(--font-size-standard) * 1.0); font-size: calc(var(--font-size-standard) * 1.0);
} }
.nudge-roll {
font-size: calc(var(--font-size-standard) * 1.0);
margin-left: 4rem;
display: none;
}
.result-success { .result-success {
color: var(--color-success); color: var(--color-success);
font-family: var(--font-title); font-family: var(--font-title);
font-size: calc(var(--font-size-standard) * 1.2); font-size: var(--font-size-result);
} }
.result-critical-success { .result-critical-success {
color: var(--color-critical-success); color: var(--color-critical-success);
font-family: var(--font-title); font-family: var(--font-title);
font-size: calc(var(--font-size-standard) * 1.2); font-size: var(--font-size-result);
} }
.result-failure { .result-failure {
color: var(--color-failure); color: var(--color-failure);
font-family: var(--font-title); font-family: var(--font-title);
font-size: calc(var(--font-size-standard) * 1.2); font-size: var(--font-size-result);
} }
.result-critical-failure { .result-critical-failure {
color: var(--color-critical-failure); color: var(--color-critical-failure);
font-family: var(--font-title); font-family: var(--font-title);
font-size: calc(var(--font-size-standard) * 1.2); font-size: var(--font-size-result);
} }
} }
.introText { .introText {

22
styles/tome.less Normal file
View File

@ -0,0 +1,22 @@
.tome-content {
.sheet-common();
.item-sheet-common();
fieldset {
margin-top: 8px;
background-color: var(--color-light-1);
}
.header {
background-color: var(--color-light-1);
display: flex;
img {
width: 50px;
height: 50px;
}
}
label {
flex: 10%;
}
}

223
styles/vehicle.less Normal file
View File

@ -0,0 +1,223 @@
.vehicle-content {
.sheet-common();
.vehicle-sheet-common();
overflow: scroll;
}
.sheet-tabs {
background-color: var(--color-light-1);
}
.vehicle-main {
background-color: var(--color-light-1);
display: flex;
.vehicle-pc {
display: flex;
gap: 4px;
flex: 1;
.vehicle-left {
min-width: 180px;
display: flex;
flex-direction: column;
.vehicle-left-image {
display: flex;
justify-content: center;
align-items: center;
padding-bottom: 8px;
.vehicle-img {
height: 140px;
width: auto;
border: none;
}
}
}
.vehicle-right {
display: flex;
flex-direction: column;
gap: 5px;
.vehicle-name {
display: flex;
input {
font-family: var(--font-title);
font-size: calc(var(--font-size-standard) * 1.4);
width: 400px;
}
}
.vehicle-infos {
display: flex;
flex-direction: column;
gap: 4px;
label {
min-width: 120px;
}
.vehicle-hp {
display: flex;
gap: 2px;
align-items: center;
.vehicle-hp-value {
.form-fields input {
flex: none;
width: 50px;
margin-left: 4px;
font-size: calc(var(--font-size-standard) * 1.4);
}
}
.vehicle-hp-max {
clear: both;
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 3px 0;
align-items: center;
input {
width: 50px;
text-align: center;
font-size: calc(var(--font-size-standard) * 1.4);
}
}
.hp-separator {
font-size: calc(var(--font-size-standard) * 1.2);
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
}
.vehicle-pc-play {
min-width: 500px;
}
.vehicle-pc-edit {
min-width: 650px;
}
}
.vehicle-biography {
background-color: var(--color-light-1);
prose-mirror.inactive {
min-height: 40px;
}
prose-mirror.active {
min-height: 150px;
}
.field-label {
margin-left: 8px;
}
.biodata {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px;
label {
min-width: 3.0rem;
}
.feature {
display: flex;
align-items: center;
gap: 4px;
min-width: 18rem;
max-width: 18rem;
}
}
}
.tab.vehicle-equipment {
background-color: var(--color-light-1);
display: grid;
grid-template-columns: 1fr;
legend {
a {
font-size: calc(var(--font-size-standard) * 1.4);
padding-left: 5px;
}
}
.weapons {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 4px;
.weapon {
display: flex;
align-items: center;
gap: 4px;
min-width: 13rem;
max-width: 13srem;
.rollable:hover,
.rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer;
}
.controls {
min-width: 2rem;
max-width: 2rem;
}
.damage {
min-width: 5rem;
max-width: 5rem;
}
.name {
min-width: 8rem;
max-width: 8rem;
}
.item-img {
width: 32px;
height: 32px;
margin: 4px 0 0 0;
}
}
}
.gears {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 4px;
.gear {
display: flex;
align-items: center;
gap: 4px;
min-width: 13rem;
max-width: 13srem;
.rollable:hover,
.rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer;
}
.controls {
min-width: 2rem;
max-width: 2rem;
}
.damage {
min-width: 5rem;
max-width: 5rem;
}
.name {
min-width: 8rem;
max-width: 8rem;
}
.item-img {
width: 32px;
height: 32px;
margin: 4px 0 0 0;
}
}
}
prose-mirror.inactive {
min-height: 40px;
}
prose-mirror.active {
min-height: 150px;
}
}

View File

@ -1,12 +1,12 @@
{ {
"id": "fvtt-cthulhu-eternal", "id": "fvtt-cthulhu-eternal",
"title": "Cthulhu Eternal RPG", "title": "Cthulhu Eternal RPG",
"description": "", "description": "The OGL Cthulhu Eternal RPG system for Foundry VTT",
"manifest": "https://www.uberwald.me/gitea/public/fvtt-cthulhu-eternal/raw/branch/main/system.json", "manifest": "https://www.uberwald.me/gitea/public/fvtt-cthulhu-eternal/raw/branch/main/system.json",
"download": "#{DOWNLOAD}#", "download": "#{DOWNLOAD}#",
"url": "https://www.uberwald.me/gitea/public/fvtt-cthulhu-eternal", "url": "https://www.uberwald.me/gitea/public/fvtt-cthulhu-eternal",
"license": "LICENSE", "license": "LICENSE",
"version": "12.0.1", "version": "12.0.5",
"authors": [ "authors": [
{ {
"name": "Uberwald", "name": "Uberwald",
@ -34,7 +34,8 @@
], ],
"documentTypes": { "documentTypes": {
"Actor": { "Actor": {
"protagonist": { "htmlFields": ["description", "notes"] } "protagonist": { "htmlFields": ["description", "notes"] },
"vehicle": { "htmlFields": ["description", "notes"] }
}, },
"Item": { "Item": {
"skill": { "htmlFields": ["description"] }, "skill": { "htmlFields": ["description"] },
@ -46,7 +47,9 @@
"motivation": { "htmlFields": ["description"] }, "motivation": { "htmlFields": ["description"] },
"arcane": { "htmlFields": ["description"] }, "arcane": { "htmlFields": ["description"] },
"gear": { "htmlFields": ["description"] }, "gear": { "htmlFields": ["description"] },
"archetype": { "htmlFields": ["description"] } "archetype": { "htmlFields": ["description"] },
"ritual": { "htmlFields": ["description"] },
"tome": { "htmlFields": ["description"] }
} }
}, },
"packs": [ "packs": [
@ -55,7 +58,7 @@
"banner": "", "banner": "",
"label": "Skills", "label": "Skills",
"system": "fvtt-cthulhu-eternal", "system": "fvtt-cthulhu-eternal",
"path": "packs/skills", "path": "packs-system/skills",
"type": "Item" "type": "Item"
} }
], ],
@ -65,5 +68,5 @@
}, },
"primaryTokenAttribute": "hp", "primaryTokenAttribute": "hp",
"socket": true, "socket": true,
"background": "systems/fvtt-cthulhu-eternal/assets/background.webp" "background": "systems/fvtt-cthulhu-eternal/assets/ui/background_01.webp"
} }

View File

@ -1,6 +0,0 @@
<div class="tenebris ask-roll">
<h4 class="ask-roll-title">{{title}}<br>{{text}}</h4>
<a class="ask-roll-dice" data-type="{{rollType}}" data-value="{{value}}" data-avantage="{{avantage}}">
<i class="fas fa-dice-d20" title="{{localize 'TENEBRIS.Manager.roll'}}"></i> {{localize 'TENEBRIS.Manager.roll'}}
</a>
</div>

View File

@ -1,55 +1,92 @@
{{!log 'chat-message' this}} {{!log 'chat-message' this}}
<div class="{{cssClass}}"> <div class="{{cssClass}}">
<div class="intro-chat"> <div class="intro-chat">
<div class="intro-img"> <div class="intro-img">
<img src="{{actingCharImg}}" data-tooltip="{{actingCharName}}" /> <img src="{{actingCharImg}}" data-tooltip="{{actingCharName}}" />
</div>
<div class="intro-right">
<ul>
{{#if (eq rollType "char")}}
<li><strong>{{localize "CTHULHUETERNAL.Label.charRoll"}}</strong></li>
{{/if}}
{{#if (eq rollType "skill")}}
<li><strong>{{localize "CTHULHUETERNAL.Label.skillRoll"}}</strong></li>
{{/if}}
{{#if weapon}}
<li><strong>Weapon : {{weapon.name}}</strong></li>
{{/if}}
<li><strong>{{rollItem.name}} : {{initialScore}}%</strong></li>
<li>{{localize "CTHULHUETERNAL.Label.modifier"}} : {{modifier}}%</li>
<li>{{localize "CTHULHUETERNAL.Label.targetScore"}} : {{targetScore}}%</li>
{{#if isSuccess}}
{{#if isCritical}}
<li class="result-critical-success">{{localize "CTHULHUETERNAL.Label.criticalSuccess"}}</li>
{{else}}
<li class="result-success">{{localize "CTHULHUETERNAL.Label.success"}}</li>
{{/if}}
{{/if}}
{{#if isFailure}}
{{#if isCritical}}
<li class="result-critical-failure">{{localize "CTHULHUETERNAL.Label.criticalFailure"}}</li>
{{else}}
<li class="result-failure">{{localize "CTHULHUETERNAL.Label.failure"}}</li>
{{/if}}
{{/if}}
</ul>
</div>
</div> </div>
{{#if isDamage}} <div class="intro-right">
<div> <ul>
{{#if (and isGM hasTarget)}} {{#if (eq rollType "char")}}
{{{localize "CTHULHUETERNAL.Roll.displayArmor" targetName=targetName targetArmor=targetArmor realDamage=realDamage}}} <li><strong>{{localize "CTHULHUETERNAL.Label.charRoll"}}</strong></li>
{{/if}} {{/if}}
</div>
{{/if}} {{#if (eq rollType "skill")}}
{{#unless isPrivate}} <li><strong>{{localize "CTHULHUETERNAL.Label.skillRoll"}}</strong></li>
<div class="dice-result"> {{/if}}
<h4 class="dice-total">{{total}}</h4>
<div class="dice-formula">{{formula}}</div> {{#if isNudgedRoll}}
{{{tooltip}}} <li><strong>{{localize "CTHULHUETERNAL.Label.nudgedRoll"}} : {{wpCost}} WP spent</strong></li>
</div> {{/if}}
{{/unless}}
</div> {{#if weapon}}
<li><strong>Weapon : {{weapon.name}}</strong></li>
{{/if}}
{{#if (eq rollType "resource")}}
<li><strong>{{rollItem.name}} : {{initialScore}}</strong></li>
{{else}}
<li><strong>{{rollItem.name}} : {{initialScore}}%</strong></li>
{{/if}}
{{#if isZeroWP}}
<li class="red-warning">Zero WP : Automatic failure (ie 0%)</li>
{{else}}
{{#if isLowWP}}
<li class="orange-warning">Low WP : -20%</li>
{{/if}}
{{/if}}
{{#if isExhausted}}
<li class="orange-warning">Exhausted : -20%</li>
{{/if}}
{{#if (eq rollType "resource")}}
<li>{{localize "CTHULHUETERNAL.Label.multiplier"}} : {{multiplier}}</li>
{{else}}
<li>{{localize "CTHULHUETERNAL.Label.modifier"}} : {{modifier}}%</li>
{{/if}}
<li>{{localize "CTHULHUETERNAL.Label.targetScore"}} : {{targetScore}}%</li>
{{#if isSuccess}}
{{#if isCritical}}
<li class="result-critical-success">{{localize "CTHULHUETERNAL.Label.criticalSuccess"}}</li>
{{else}}
<li class="result-success">
{{localize "CTHULHUETERNAL.Label.success"}}
{{#if isNudge}}
<a class="nudge-roll"><i class="fa-solid fa-circle-sort-down"></i></a>
{{/if}}
</li>
{{/if}}
{{/if}}
{{#if isFailure}}
{{#if isCritical}}
<li class="result-critical-failure">{{localize "CTHULHUETERNAL.Label.criticalFailure"}}</li>
{{else}}
<li class="result-failure">
{{localize "CTHULHUETERNAL.Label.failure"}}
{{#if isNudge}}
<a class="nudge-roll"><i class="fa-solid fa-circle-sort-down"></i></a>
{{/if}}
</li>
{{/if}}
{{/if}}
</ul>
</div>
</div>
{{#if isDamage}}
<div>
{{#if (and isGM hasTarget)}}
{{{localize "CTHULHUETERNAL.Roll.displayArmor" targetName=targetName targetArmor=targetArmor
realDamage=realDamage}}}
{{/if}}
</div>
{{/if}}
{{#unless isPrivate}}
<div class="dice-result">
<h4 class="dice-total">{{total}}</h4>
<div class="dice-formula">{{formula}}</div>
{{{tooltip}}}
</div>
{{/unless}}
</div>

View File

@ -7,6 +7,7 @@
<fieldset> <fieldset>
{{formField systemFields.settings value=system.settings localize=true}} {{formField systemFields.settings value=system.settings localize=true}}
{{formField systemFields.resourceLevel value=system.resourceLevel}} {{formField systemFields.resourceLevel value=system.resourceLevel}}
{{formField systemFields.state value=system.state localize=true}}
</fieldset> </fieldset>
<fieldset> <fieldset>

View File

@ -1,39 +0,0 @@
<table class="tenebris-table">
<thead>
<tr>
<th>{{localize "TENEBRIS.Manager.player"}}</th>
<th>{{localize "TENEBRIS.Manager.character"}}</th>
<th>{{localize "TENEBRIS.Manager.pv"}}</th>
<td data-action="saveAll" data-save="rob">{{localize "TENEBRIS.Manager.rob"}}</td>
<td data-action="saveAll" data-save="dex">{{localize "TENEBRIS.Manager.dex"}}</td>
<td data-action="saveAll" data-save="int">{{localize "TENEBRIS.Manager.int"}}</td>
<td data-action="saveAll" data-save="per">{{localize "TENEBRIS.Manager.per"}}</td>
<td data-action="saveAll" data-save="vol">{{localize "TENEBRIS.Manager.vol"}}</td>
<td data-action="resourceAll" data-resource="san">{{localize "TENEBRIS.Manager.san"}}</td>
<td data-action="resourceAll" data-resource="oeil">{{localize "TENEBRIS.Manager.oeil"}}</td>
<td data-action="resourceAll" data-resource="verbe">{{localize "TENEBRIS.Manager.verbe"}}</td>
<td data-action="resourceAll" data-resource="bourse">{{localize "TENEBRIS.Manager.bourse"}}</td>
<td data-action="resourceAll" data-resource="magie">{{localize "TENEBRIS.Manager.magie"}}</td>
</tr>
</thead>
<tbody>
{{#each players as |player|}}
{{!log "player" this}}
<tr class="player" data-user-id="{{player.id}}" data-character-name="{{player.character.name}}" data-character-id="{{player.character.id}}">
<td>{{player.name}}</td>
<td data-action="openSheet" data-character-id="{{player.character.id}}">{{player.character.name}}</td>
<td>{{player.character.system.pv.value}}</td>
<td data-action="saveOne" data-save="rob">{{player.character.system.caracteristiques.rob.valeur}}</td>
<td data-action="saveOne" data-save="dex">{{player.character.system.caracteristiques.dex.valeur}}</td>
<td data-action="saveOne" data-save="int">{{player.character.system.caracteristiques.int.valeur}}</td>
<td data-action="saveOne" data-save="per">{{player.character.system.caracteristiques.per.valeur}}</td>
<td data-action="saveOne" data-save="vol">{{player.character.system.caracteristiques.vol.valeur}}</td>
<td data-action="resourceOne" data-resource="san">{{player.character.system.ressources.san.valeur}}</td>
<td data-action="resourceOne" data-resource="oeil">{{player.character.system.ressources.oeil.valeur}}</td>
<td data-action="resourceOne" data-resource="verbe">{{player.character.system.ressources.verbe.valeur}}</td>
<td data-action="resourceOne" data-resource="bourse">{{player.character.system.ressources.bourse.valeur}}</td>
<td data-action="resourceOne" data-resource="magie">{{player.character.system.ressources.magie.valeur}}</td>
</tr>
{{/each}}
</tbody>
</table>

View File

@ -4,6 +4,10 @@
{{formInput fields.name value=source.name}} {{formInput fields.name value=source.name}}
</div> </div>
<fieldset>
{{formField systemFields.cured value=system.cured localize=true}}
</fieldset>
<fieldset> <fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend> <legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend>
{{formInput {{formInput

View File

@ -0,0 +1,18 @@
<div class="fvtt-cthulhu-eternal-roll-dialog">
<fieldSet class="dialog-modifier">
<legend>{{localize "CTHULHUETERNAL.Label.selectNewValue"}}</legend>
<select name="modifiedValue" class="nudged-score-select">
{{selectOptions nudgeOptions selected=rollResultIndex}}
</select>
</fieldSet>
<fieldSet>
<legend>{{localize "CTHULHUETERNAL.Label.wpCost"}}</legend>
<div>
Willpower points cost :
<input class="text" value="0" id="nudged-wp-cost" disabled >
</div>
</fieldSet>
</div>

View File

@ -1,7 +1,29 @@
<section class="tab protagonist-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}"> <section class="tab protagonist-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
<fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.resources"}}</legend>
<div class="resources">
{{formField systemFields.resources.fields.permanentRating value=system.resources.permanentRating name="system.resources.permanentRating" localize=true}}
<div>
<span class="label-field">{{localize "CTHULHUETERNAL.Label.resourceChecks"}}</span>
{{#each system.resources.checks as |check idx|}}
<input class="san-checkbox" type="checkbox" data-action="updateCheckResource" data-index="{{@index}}"
data-name="checks" {{#if check}} checked {{/if}} {{#if (gte @index @root.system.resources.nbValidChecks)}} disabled {{/if}}>
{{/each}}
</div>
<button class="resource-roll rollable" data-roll-type="resource"><img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />Resource roll</button>
{{formField systemFields.resources.fields.hand value=system.resources.hand name="system.resources.hand" localize=true disabled=true}}
{{formField systemFields.resources.fields.stowed value=system.resources.stowed name="system.resources.stowed" localize=true disabled=true}}
{{formField systemFields.resources.fields.storage value=system.resources.storage name="system.resources.storage" localize=true disabled=true}}
</div>
</fieldset>
<fieldset> <fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.biodata"}}</legend> <legend>{{localize "CTHULHUETERNAL.Label.biodata"}}</legend>
<div class="adapted">
{{formField systemFields.biodata.fields.adaptedToViolence value=system.biodata.adaptedToViolence name="system.biodata.adaptedToViolence" localize=true}}
{{formField systemFields.biodata.fields.adaptedToHelplessness value=system.biodata.adaptedToHelplessness name="system.biodata.adaptedToHelplessness" localize=true}}
</div>
<div class="biodata"> <div class="biodata">
{{formField systemFields.biodata.fields.harshness value=system.biodata.harshness name="system.biodata.harshness" localize=true}} {{formField systemFields.biodata.fields.harshness value=system.biodata.harshness name="system.biodata.harshness" localize=true}}
{{formField systemFields.biodata.fields.age value=system.biodata.age name="system.biodata.age" localize=true classes="field-label"}} {{formField systemFields.biodata.fields.age value=system.biodata.age name="system.biodata.age" localize=true classes="field-label"}}
@ -9,38 +31,49 @@
{{formField systemFields.biodata.fields.height value=system.biodata.height name="system.biodata.height" localize=true classes="field-label"}} {{formField systemFields.biodata.fields.height value=system.biodata.height name="system.biodata.height" localize=true classes="field-label"}}
{{formField systemFields.biodata.fields.eyes value=system.biodata.eyes name="system.biodata.eyes" localize=true classes="field-label"}} {{formField systemFields.biodata.fields.eyes value=system.biodata.eyes name="system.biodata.eyes" localize=true classes="field-label"}}
{{formField systemFields.biodata.fields.hair value=system.biodata.hair name="system.biodata.hair" localize=true classes="field-label"}} {{formField systemFields.biodata.fields.hair value=system.biodata.hair name="system.biodata.hair" localize=true classes="field-label"}}
{{formField systemFields.biodata.fields.gender value=system.biodata.gender name="system.biodata.gender" localize=true classes="field-label"}} {{formField systemFields.biodata.fields.home value=system.biodata.home name="system.biodata.home" localize=true classes="field-label"}}
{{formField systemFields.biodata.fields.birthplace value=system.biodata.birthplace name="system.biodata.birthplace" localize=true classes="field-label"}} {{formField systemFields.biodata.fields.birthplace value=system.biodata.birthplace name="system.biodata.birthplace" localize=true classes="field-label"}}
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.motivations"}}{{#if isEditMode}} <legend>{{localize "CTHULHUETERNAL.Label.distinguishingFeatures"}}</legend>
<a class="action" data-tooltip="{{localize "CTHULHUETERNAL.Tooltip.addMotivation"}}" data-tooltip-direction="UP"><i class="fas fa-plus" data-action="createMotivation"></i></a>{{/if}}</legend> <div class="features">
<div class="motivations"> <div class="feature">
{{#each motivations as |item|}} <label>{{localize "CTHULHUETERNAL.Label.strShort"}}</label>
{{!log 'armor' this}} {{formInput systemFields.characteristics.fields.str.fields.feature value=system.characteristics.str.feature localize=true}}
<div class="motivation" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"> </div>
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" /> <div class="feature">
<div class="name" data-tooltip="{{{item.system.description}}}"> <label>{{localize "CTHULHUETERNAL.Label.dexShort"}}</label>
{{item.name}} {{formInput systemFields.characteristics.fields.dex.fields.feature value=system.characteristics.dex.feature localize=true}}
</div> </div>
<div class="controls"> <div class="feature">
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a> <label>{{localize "CTHULHUETERNAL.Label.conShort"}}</label>
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a> {{formInput systemFields.characteristics.fields.con.fields.feature value=system.characteristics.con.feature localize=true}}
</div> </div>
</div> <div class="feature">
{{/each}} <label>{{localize "CTHULHUETERNAL.Label.intShort"}}</label>
{{formInput systemFields.characteristics.fields.int.fields.feature value=system.characteristics.int.feature localize=true}}
</div>
<div class="feature">
<label>{{localize "CTHULHUETERNAL.Label.powShort"}}</label>
{{formInput systemFields.characteristics.fields.pow.fields.feature value=system.characteristics.pow.feature localize=true}}
</div>
<div class="feature">
<label>{{localize "CTHULHUETERNAL.Label.chaShort"}}</label>
{{formInput systemFields.characteristics.fields.cha.fields.feature value=system.characteristics.cha.feature localize=true}}
</div>
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend> <legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend>
{{formInput systemFields.description enriched=description value=system.description name="system.description" toggled=true}} {{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.notes"}}</legend> <legend>{{localize "CTHULHUETERNAL.Label.notes"}}</legend>
{{formInput systemFields.notes enriched=notes value=system.notes name="system.notes" toggled=true}} {{formInput systemFields.notes enriched=enrichedNotes value=system.notes name="system.notes" toggled=true}}
</fieldset> </fieldset>
</section> </section>

View File

@ -2,64 +2,134 @@
<fieldset> <fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.weapons"}}{{#if isEditMode}} <legend>{{localize "CTHULHUETERNAL.Label.weapons"}}{{#if isEditMode}}
<a class="action" data-tooltip="{{localize "CTHULHUETERNAL.Tooltip.addWeapon"}}" data-tooltip-direction="UP"><i class="fas fa-plus" data-action="createWeapon"></i></a>{{/if}}</legend> <a class="action" data-tooltip="{{localize " CTHULHUETERNAL.Tooltip.addWeapon"}}" data-tooltip-direction="UP"><i
class="fas fa-plus" data-action="createWeapon"></i></a>{{/if}}
</legend>
<div class="weapons"> <div class="weapons">
{{#each weapons as |item|}} {{#each weapons as |item|}}
{{!log 'weapon' this}} {{!log 'weapon' this}}
<div class="weapon item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true" > <div class="weapon item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<div class="name rollable" data-roll-type="weapon" data-tooltip="{{{item.system.description}}}"> <img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
{{item.name}} <img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
</div> <div class="name rollable" data-roll-type="weapon" data-tooltip="{{{item.system.description}}}">
<a class="damage rollable" data-item-id="{{item.id}}" data-action="roll" data-roll-type="damage" data-roll-value="{{item.system.damage}}">{{localize "CTHULHUETERNAL.Label.damageShort"}} : {{item.system.damage}}</a> {{item.name}}
<div class="controls">
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div> </div>
<img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
<a class="damage rollable" data-item-id="{{item.id}}" data-action="roll" data-roll-type="damage"
data-roll-value="{{item.system.damage}}">
{{localize "CTHULHUETERNAL.Label.damageShort"}} :
{{item.system.damage}}</a>
<div class="controls">
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div>
{{/each}} {{/each}}
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.armors"}}{{#if isEditMode}} <legend>{{localize "CTHULHUETERNAL.Label.armors"}}{{#if isEditMode}}
<a class="action" data-tooltip="{{localize "CTHULHUETERNAL.Tooltip.addArmor"}}" data-tooltip-direction="UP"><i class="fas fa-plus" data-action="createArmor"></i></a>{{/if}}</legend> <a class="action" data-tooltip="{{localize " CTHULHUETERNAL.Tooltip.addArmor"}}" data-tooltip-direction="UP"><i
class="fas fa-plus" data-action="createArmor"></i></a>{{/if}}
</legend>
<div class="armors"> <div class="armors">
{{#each armors as |item|}} {{#each armors as |item|}}
{{!log 'armor' this}} {{!log 'armor' this}}
<div class="armor" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"> <div class="armor" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" /> <img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<div class="name" data-tooltip="{{{item.system.description}}}"> <div class="name" data-tooltip="{{{item.system.description}}}">
{{item.name}} {{item.name}}
</div>
<span class="protection">{{localize "CTHULHUETERNAL.Label.armor"}} : {{item.system.protection}}</span>
<div class="controls">
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div> </div>
<span class="protection">{{localize "CTHULHUETERNAL.Label.armor"}} : {{item.system.protection}}</span>
<div class="controls">
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div>
{{/each}} {{/each}}
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.gears"}}{{#if isEditMode}} <legend>{{localize "CTHULHUETERNAL.Label.gears"}}{{#if isEditMode}}
<a class="action" data-tooltip="{{localize "CTHULHUETERNAL.Tooltip.addGear"}}" data-tooltip-direction="UP"><i class="fas fa-plus" data-action="createGear"></i></a>{{/if}}</legend> <a class="action" data-tooltip="{{localize " CTHULHUETERNAL.Tooltip.addGear"}}" data-tooltip-direction="UP"><i
class="fas fa-plus" data-action="createGear"></i></a>{{/if}}
</legend>
<div class="gears"> <div class="gears">
{{#each gears as |item|}} {{#each gears as |item|}}
{{!log 'armor' this}} {{!log 'armor' this}}
<div class="gear" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"> <div class="gear" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" /> <img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<div class="name" data-tooltip="{{{item.system.description}}}"> <div class="name" data-tooltip="{{{item.system.description}}}">
{{item.name}} {{item.name}}
</div>
<div class="controls">
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div> </div>
<div class="controls">
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div>
{{/each}} {{/each}}
</div> </div>
</fieldset> </fieldset>
{{#if (count tomes)}}
<fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.Tomes"}}{{#if isEditMode}}
<a class="action" data-tooltip="{{localize "CTHULHUETERNAL.Tooltip.addTome"}}" data-tooltip-direction="UP"><i
class="fas fa-plus" data-action="createTome"></i></a>{{/if}}
</legend>
<div class="tomes">
{{#each tomes as |item|}}
<div class="tome" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<div class="name" data-tooltip="{{{item.system.description}}}">
{{item.name}}
</div>
<div class="controls">
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div>
{{/each}}
</div>
</fieldset>
{{/if}}
{{#if (count rituals)}}
<fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.Rituals"}}{{#if isEditMode}}
<a class="action" data-tooltip="{{localize "CTHULHUETERNAL.Tooltip.addRitual"}}" data-tooltip-direction="UP"><i
class="fas fa-plus" data-action="createRitual"></i></a>{{/if}}
</legend>
<div class="rituals">
{{#each rituals as |item|}}
<div class="ritual" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<div class="name" data-tooltip="{{{item.system.description}}}">
{{item.name}}
</div>
<div class="controls">
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div>
{{/each}}
</div>
</fieldset>
{{/if}}
</section> </section>

View File

@ -9,13 +9,16 @@
<img class="protagonist-img" src="{{actor.img}}" data-edit="img" data-action="editImage" <img class="protagonist-img" src="{{actor.img}}" data-edit="img" data-action="editImage"
data-tooltip="{{actor.name}}" /> data-tooltip="{{actor.name}}" />
</div> </div>
<fieldset> <fieldset class="protagonist-hp">
<legend>{{localize "CTHULHUETERNAL.Label.HP"}}</legend> <legend>{{localize "CTHULHUETERNAL.Label.HP"}}</legend>
<div class="flexrow"> <div class="flexrow">
{{formField systemFields.hp.fields.value value=system.hp.value}} {{formField systemFields.hp.fields.value value=system.hp.value}}
/ <span class="hp-separator">/</span>
{{formField systemFields.hp.fields.max value=system.hp.max rootId=partId disabled=true}} {{formField systemFields.hp.fields.max value=system.hp.max rootId=partId disabled=true}}
</div> </div>
<div class="flexrow ">
{{formField systemFields.damageBonus value=system.damageBonus classes="damage-bonus"}}
</div>
</fieldset> </fieldset>
</div> </div>
@ -32,41 +35,64 @@
<fieldset class="san"> <fieldset class="san">
<legend>{{localize "CTHULHUETERNAL.Label.SAN"}}</legend> <legend>{{localize "CTHULHUETERNAL.Label.SAN"}}</legend>
<div class="flexrow"> <div class="flexrow">
<span class="label-field">{{localize "CTHULHUETERNAL.Label.current"}}</span>
{{formField systemFields.san.fields.value value=system.san.value}} <label class="label-field rollable" data-roll-type="san" ><img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
<span class="label-field">{{localize "CTHULHUETERNAL.Label.max"}}</span> {{localize "CTHULHUETERNAL.Label.current"}}</label>
{{formField systemFields.san.fields.max value=system.san.max rootId=partId disabled=true}} {{formInput systemFields.san.fields.value value=system.san.value}}
<span class="label-field">{{localize "CTHULHUETERNAL.Label.recovery"}}</span>
{{formField systemFields.san.fields.recovery value=system.san.recovery disabled=true}} <span class="label-field label-recovery">{{localize "CTHULHUETERNAL.Label.recovery"}}</span>
<span class="label-field" data-tooltip='{{localize "CTHULHUETERNAL.Tooltip.sanBP"}}'>{{localize {{formInput systemFields.san.fields.recovery value=system.san.recovery disabled=true}}
"CTHULHUETERNAL.Label.breakingPoint"}}</span>
{{formField systemFields.san.fields.breakingPoint value=system.san.breakingPoint disabled=true}} <span class="label-bp" data-tooltip='{{localize "CTHULHUETERNAL.Tooltip.sanBPShort"}}'>{{localize
"CTHULHUETERNAL.Label.sanBPShort"}}</span>
{{formInput systemFields.san.fields.breakingPoint value=system.san.breakingPoint disabled=true}}
</div>
<div class="flexrow">
<div class="flexrow">
<span class="label-short-field">{{localize "CTHULHUETERNAL.Label.max"}}</span>
{{formInput systemFields.san.fields.max value=system.san.max rootId=partId disabled=true}}
</div>
<span class="label-insanity" >
{{localize "CTHULHUETERNAL.Label.tempInsanity"}}
</span>
{{formInput systemFields.san.fields.insanity value=system.san.insanity localize=true}}
{{#if (not isPlayMode)}}
<button data-action="setBP" class="button" data-tooltip="{{localize "CTHULHUETERNAL.Tooltip.setBP"}}">{{localize "CTHULHUETERNAL.Label.setBP"}}</button>
{{/if}}
</div> </div>
<div class="flexrow"> <div class="flexrow">
{{localize "CTHULHUETERNAL.Label.violence"}}
<span class="label-field">{{localize "CTHULHUETERNAL.Label.violence"}}</span>
{{#each system.san.violence as |violence idx|}} {{#each system.san.violence as |violence idx|}}
<input class="san-checkbox" type="checkbox" data-action="updateCheckboxArray" data-index="{{@index}}" <input class="san-checkbox" type="checkbox" data-action="updateCheckboxArray" data-index="{{@index}}"
data-name="violence" {{#if violence}} checked {{/if}}> data-name="violence" {{#if violence}} checked {{/if}}>
{{/each}} {{/each}}
<span class="spacing"></span>
{{localize "CTHULHUETERNAL.Label.helplessness"}} <span class="label-field">{{localize "CTHULHUETERNAL.Label.helplessness"}}</span>
{{#each system.san.helplessness as |helplessness idx|}} {{#each system.san.helplessness as |helplessness idx|}}
<input class="san-checkbox" type="checkbox" data-action="updateCheckboxArray" data-index="{{@index}}" <input class="san-checkbox" type="checkbox" data-action="updateCheckboxArray" data-index="{{@index}}"
data-name="helplessness" {{#if helplessness}} checked {{/if}}> data-name="helplessness" {{#if helplessness}} checked {{/if}}>
{{/each}} {{/each}}
</div> </div>
</fieldset> </fieldset>
<fieldset class="willpower"> <fieldset class="willpower">
<legend>{{localize "CTHULHUETERNAL.Label.willpower"}}</legend> <legend>{{localize "CTHULHUETERNAL.Label.willpower"}}</legend>
<div class="flexrow"> <div class="flexrow">
<span class="label-field">{{localize "CTHULHUETERNAL.Label.current"}}</span> <label class="label-field">{{localize "CTHULHUETERNAL.Label.current"}}</label>
{{formField systemFields.wp.fields.value value=system.wp.value}} {{formInput systemFields.wp.fields.value value=system.wp.value}}
<span class="label-field">{{localize "CTHULHUETERNAL.Label.max"}}</span> <label class="label-field">{{localize "CTHULHUETERNAL.Label.max"}}</label>
{{formField systemFields.wp.fields.max value=system.wp.max rootId=partId disabled=true}} {{formInput systemFields.wp.fields.max value=system.wp.max rootId=partId disabled=true}}
<span class="label-field">{{localize "CTHULHUETERNAL.Label.exhausted"}}</span> <label class="label-field">{{localize "CTHULHUETERNAL.Label.exhausted"}}</label>
{{formField systemFields.wp.fields.exhausted value=system.wp.exhausted classes=checkbox}} {{formInput systemFields.wp.fields.exhausted value=system.wp.exhausted classes="checkbox"}}
</div> </div>
</fieldset> </fieldset>
@ -76,47 +102,53 @@
<fieldset class="protagonist-characteristics protagonist-characteristics-{{ifThen isPlayMode 'play' 'edit'}}"> <fieldset class="protagonist-characteristics protagonist-characteristics-{{ifThen isPlayMode 'play' 'edit'}}">
<legend>{{localize "CTHULHUETERNAL.Label.characteristics"}}</legend> <legend>{{localize "CTHULHUETERNAL.Label.characteristics"}}</legend>
<div class="protagonist-characteristic" data-drag="true" data-drag-type="characteristic"> <div class="protagonist-characteristic" >
<label class="rollable" data-roll-type="char" data-char-id="str">{{localize <img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
<label class="rollable" data-roll-type="char" data-char-id="str" data-tooltip="{{system.characteristics.str.feature}}">{{localize
"CTHULHUETERNAL.Label.strShort"}}</label> "CTHULHUETERNAL.Label.strShort"}}</label>
{{formField systemFields.characteristics.fields.str.fields.value value=system.characteristics.str.value {{formField systemFields.characteristics.fields.str.fields.value value=system.characteristics.str.value
rootId=partId disabled=isPlayMode }} rootId=partId disabled=isPlayMode }}
{{mul system.characteristics.str.value 5}} <label class="char-text">{{mul system.characteristics.str.value 5}}</label>
</div> </div>
<div class="protagonist-characteristic" data-drag="true" data-drag-type="characteristic"> <div class="protagonist-characteristic">
<label class="rollable" data-roll-type="char" data-char-id="dex">{{localize <img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
<label class="rollable" data-roll-type="char" data-char-id="dex" data-tooltip="{{system.characteristics.dex.feature}}">{{localize
"CTHULHUETERNAL.Label.dexShort"}}</label> "CTHULHUETERNAL.Label.dexShort"}}</label>
{{formField systemFields.characteristics.fields.dex.fields.value value=system.characteristics.dex.value {{formField systemFields.characteristics.fields.dex.fields.value value=system.characteristics.dex.value
rootId=partId disabled=isPlayMode }} rootId=partId disabled=isPlayMode }}
{{mul system.characteristics.dex.value 5}} <label class="char-text">{{mul system.characteristics.dex.value 5}}</label>
</div> </div>
<div class="protagonist-characteristic" data-drag="true" data-drag-type="characteristic"> <div class="protagonist-characteristic" >
<label class="rollable" data-roll-type="char" data-char-id="con">{{localize <img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
<label class="rollable" data-roll-type="char" data-char-id="con" data-tooltip="{{system.characteristics.con.feature}}">{{localize
"CTHULHUETERNAL.Label.conShort"}}</label> "CTHULHUETERNAL.Label.conShort"}}</label>
{{formField systemFields.characteristics.fields.con.fields.value value=system.characteristics.con.value {{formField systemFields.characteristics.fields.con.fields.value value=system.characteristics.con.value
rootId=partId disabled=isPlayMode }} rootId=partId disabled=isPlayMode }}
{{mul system.characteristics.con.value 5}} <label class="char-text">{{mul system.characteristics.con.value 5}}</label>
</div> </div>
<div class="protagonist-characteristic" data-drag="true" data-drag-type="characteristic"> <div class="protagonist-characteristic" >
<label class="rollable" data-roll-type="char" data-char-id="int">{{localize <img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
<label class="rollable" data-roll-type="char" data-char-id="int" data-tooltip="{{system.characteristics.int.feature}}">{{localize
"CTHULHUETERNAL.Label.intShort"}}</label> "CTHULHUETERNAL.Label.intShort"}}</label>
{{formField systemFields.characteristics.fields.int.fields.value value=system.characteristics.int.value {{formField systemFields.characteristics.fields.int.fields.value value=system.characteristics.int.value
rootId=partId disabled=isPlayMode }} rootId=partId disabled=isPlayMode }}
{{mul system.characteristics.int.value 5}} <label class="char-text">{{mul system.characteristics.int.value 5}}</label>
</div> </div>
<div class="protagonist-characteristic" data-drag="true" data-drag-type="characteristic"> <div class="protagonist-characteristic" >
<label class="rollable" data-roll-type="char" data-char-id="pow">{{localize <img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
<label class="rollable" data-roll-type="char" data-char-id="pow" data-tooltip="{{system.characteristics.pow.feature}}">{{localize
"CTHULHUETERNAL.Label.powShort"}}</label> "CTHULHUETERNAL.Label.powShort"}}</label>
{{formField systemFields.characteristics.fields.pow.fields.value value=system.characteristics.pow.value {{formField systemFields.characteristics.fields.pow.fields.value value=system.characteristics.pow.value
rootId=partId disabled=isPlayMode }} rootId=partId disabled=isPlayMode }}
{{mul system.characteristics.pow.value 5}} <label class="char-text">{{mul system.characteristics.pow.value 5}}</label>
</div> </div>
<div class="protagonist-characteristic" data-drag="true" data-drag-type="characteristic"> <div class="protagonist-characteristic" >
<label class="rollable" data-roll-type="char" data-char-id="cha">{{localize <img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
<label class="rollable" data-roll-type="char" data-char-id="cha" data-tooltip="{{system.characteristics.cha.feature}}">{{localize
"CTHULHUETERNAL.Label.chaShort"}}</label> "CTHULHUETERNAL.Label.chaShort"}}</label>
{{formField systemFields.characteristics.fields.cha.fields.value value=system.characteristics.cha.value {{formField systemFields.characteristics.fields.cha.fields.value value=system.characteristics.cha.value
rootId=partId disabled=isPlayMode }} rootId=partId disabled=isPlayMode }}
{{mul system.characteristics.cha.value 5}} <label class="char-text">{{mul system.characteristics.cha.value 5}}</label>
</div> </div>
</fieldset> </fieldset>

View File

@ -6,6 +6,7 @@
{{#each skills as |item|}} {{#each skills as |item|}}
<div class="skill item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"> <div class="skill item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" /> <img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
<div class="name rollable" data-roll-type="skill" data-tooltip="{{{item.description}}}" data-tooltip-direction="UP">{{item.name}} <div class="name rollable" data-roll-type="skill" data-tooltip="{{{item.description}}}" data-tooltip-direction="UP">{{item.name}}
</div> </div>
<div class="score" > <div class="score" >

View File

@ -12,7 +12,7 @@
{{item.name}} {{item.name}}
</div> </div>
<div class="type"> <div class="type">
{{item.system.bondType}} {{upperFirst item.system.bondType}}
</div> </div>
<div class="level"> <div class="level">
{{item.system.value}} {{item.system.value}}
@ -52,6 +52,33 @@
{{#each mentaldisorders as |item|}} {{#each mentaldisorders as |item|}}
{{!log 'armor' this}} {{!log 'armor' this}}
<div class="mentaldisorder" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"> <div class="mentaldisorder" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<div class="name" data-tooltip="{{{item.system.description}}}">
{{item.name}}
</div>
<div class="cured">
{{#if item.system.cured}}
{{localize 'CTHULHUETERNAL.Label.Cured'}}
{{else}}
{{localize 'CTHULHUETERNAL.Label.Uncured'}}
{{/if}}
</div>
<div class="controls">
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div>
{{/each}}
</div>
</fieldset>
<fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.motivations"}}{{#if isEditMode}}
<a class="action" data-tooltip="{{localize "CTHULHUETERNAL.Tooltip.addMotivation"}}" data-tooltip-direction="UP"><i class="fas fa-plus" data-action="createMotivation"></i></a>{{/if}}</legend>
<div class="motivations">
{{#each motivations as |item|}}
{{!log 'armor' this}}
<div class="motivation" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" /> <img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<div class="name" data-tooltip="{{{item.system.description}}}"> <div class="name" data-tooltip="{{{item.system.description}}}">
{{item.name}} {{item.name}}

23
templates/ritual.hbs Normal file
View File

@ -0,0 +1,23 @@
<section>
<div class="header">
<img class="item-img" src="{{item.img}}" data-edit="img" data-action="editImage" data-tooltip="{{item.name}}" />
{{formInput fields.name value=source.name}}
</div>
<fieldset>
{{formField systemFields.ritualType value=system.ritualType localize=true}}
{{formField systemFields.studyTime value=system.studyTime}}
{{formField systemFields.studySAN value=system.studySAN}}
{{formField systemFields.activationTime value=system.activationTime}}
{{formField systemFields.activationSAN value=system.activationSAN}}
{{formField systemFields.activationWP value=system.activationWP}}
</fieldset>
<fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend>
{{formInput systemFields.description enriched=description value=system.description name="system.description" toggled=true}}
</fieldset>
</section>

View File

@ -1,34 +1,58 @@
{{log "roll-dialog" this}}
<div class="fvtt-cthulhu-eternal-roll-dialog"> <div class="fvtt-cthulhu-eternal-roll-dialog">
<fieldSet> <fieldSet>
{{#if (eq rollType "skill")}} {{#if (eq rollType "skill")}}
<legend>{{localize "CTHULHUETERNAL.Label.skill"}}</legend> <legend>{{localize "CTHULHUETERNAL.Label.skill"}}</legend>
{{/if}} {{/if}}
{{#if (eq rollType "char")}} {{#if (eq rollType "char")}}
<legend>{{localize "CTHULHUETERNAL.Label.characteristic"}}</legend> <legend>{{localize "CTHULHUETERNAL.Label.characteristic"}}</legend>
{{/if}} {{/if}}
<div class="dialog-skill">{{rollItem.name}} : {{initialScore}}%</div> {{#if (eq rollType "resource")}}
<legend>{{localize "CTHULHUETERNAL.Label.resourceRating"}}</legend>
<div class="dialog-skill">{{rollItem.name}} : <span class="resource-score">{{initialScore}} ({{mul initialScore 5}}%)</span></div>
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Hand"}} : {{rollItem.hand}} <input type="checkbox" data-action="selectHand" {{checked rollItem.enableHand}}></div>
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Stowed"}} : {{rollItem.stowed}} <input type="checkbox" data-action="selectStowed" {{checked rollItem.enableStowed}}></div>
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Storage"}} : {{rollItem.storage}} <input type="checkbox" data-action="selectStorage" {{checked rollItem.enableStorage}}></div>
{{else}}
<div class="dialog-skill">{{rollItem.name}} : {{initialScore}}%</div>
{{/if}}
{{#if weapon}} {{#if weapon}}
<div class="dialog-skill">Weapon : {{weapon.name}}</div> <div class="dialog-skill">Weapon : {{weapon.name}}</div>
{{/if}} {{/if}}
{{#if isZeroWP}} {{#if isZeroWP}}
<div class="dialog-skill">Zero WP : Automatic failure (ie 0%)</div> <div class="dialog-skill red-warning">Zero WP : Automatic failure (ie 0%)</div>
{{else}} {{else}}
{{#if isLowWP}} {{#if isLowWP}}
<div class="dialog-skill">Low WP : -20%</div> <div class="dialog-skill orange-warning">Low WP : -20%</div>
{{/if}} {{/if}}
{{/if}} {{/if}}
</fieldSet>
{{#if isExhausted}}
<div class="dialog-skill orange-warning">Exhausted : -20%</div>
{{/if}}
</fieldSet>
{{#if hasModifier}}
<fieldSet class="dialog-modifier">
<legend>{{localize "CTHULHUETERNAL.Label.modifier"}}</legend>
<select name="modifier" class="roll-skill-modifier">
{{selectOptions choiceModifier selected=modifier}}
</select>
</fieldSet>
{{/if}}
{{#if hasMultiplier}}
<fieldSet class="dialog-modifier">
<legend>{{localize "CTHULHUETERNAL.Label.multiplier"}}</legend>
<select name="multiplier" class="roll-skill-modifier roll-skill-multiplier">
{{selectOptions choiceMultiplier selected=multiplier}}
</select>
</fieldSet>
{{/if}}
<fieldSet class="dialog-modifier">
<legend>{{localize "CTHULHUETERNAL.Label.modifier"}}</legend>
<select name="modifier" class="roll-skill-modifier">
{{selectOptions choiceModifier selected=modifier}}
</select>
</fieldSet>
<fieldSet> <fieldSet>
<legend>{{localize "CTHULHUETERNAL.Label.rollView"}}</legend> <legend>{{localize "CTHULHUETERNAL.Label.rollView"}}</legend>
<select name="visibility"> <select name="visibility">

View File

@ -15,9 +15,12 @@
</div> </div>
{{formField systemFields.isAdversary value=system.isAdversary}} {{formField systemFields.isAdversary value=system.isAdversary}}
{{formField systemFields.diceEvolved value=system.diceEvolved}} {{formField systemFields.diceEvolved value=system.diceEvolved}}
{{#if system.diceEvolved}}
<!-- {{#if system.diceEvolved}}
{{formField systemFields.rollFailed value=system.rollFailed}} {{formField systemFields.rollFailed value=system.rollFailed}}
{{/if}} {{/if}}
-->
</fieldset> </fieldset>

42
templates/tome.hbs Normal file
View File

@ -0,0 +1,42 @@
<section>
<div class="header">
<img class="item-img" src="{{item.img}}" data-edit="img" data-action="editImage" data-tooltip="{{item.name}}" />
{{formInput fields.name value=source.name}}
</div>
<fieldset>
<div class="form-group">
{{formField systemFields.language value=system.language }}
</div>
<div class="form-group">
{{formField systemFields.minimumEra value=system.minimumEra localize=true }}
</div>
<div class="form-group">
{{formField systemFields.creationDate value=system.creationDate }}
</div>
<div class="form-group">
{{formField systemFields.studyTime value=system.studyTime }}
</div>
<div class="form-group">
{{formField systemFields.sanLoss value=system.sanLoss }}
</div>
<div class="form-group">
{{formField systemFields.unnaturalSkill value=system.unnaturalSkill }}
</div>
<div class="form-group">
<label>{{localize "CTHULHUETERNAL.Label.Rituals"}} </label>
<textarea class="form-control" rows="3" name="system.rituals" data-tooltip="{{localize "CTHULHUETERNAL.Label.Rituals"}}">{{system.rituals}}</textarea>
</div>
<div class="form-group">
<label>{{localize "CTHULHUETERNAL.Label.otherBenefits"}} </label>
<textarea class="form-control" rows="3" name="system.otherBenefits" data-tooltip="{{localize "CTHULHUETERNAL.Label.otherBenefits"}}">{{system.otherBenefits}}</textarea>
</div>
</fieldset>
<fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend>
{{formInput systemFields.description enriched=description value=system.description name="system.description" toggled=true}}
</fieldset>
</section>

View File

@ -0,0 +1,12 @@
<section class="tab vehicle-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
<fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend>
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
</fieldset>
<fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.notes"}}</legend>
{{formInput systemFields.notes enriched=enrichedNotes value=system.notes name="system.notes" toggled=true}}
</fieldset>
</section>

View File

@ -0,0 +1,54 @@
<section class="tab vehicle-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
<fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.weapons"}}{{#if isEditMode}}
<a class="action" data-tooltip="{{localize " CTHULHUETERNAL.Tooltip.addWeapon"}}" data-tooltip-direction="UP"><i
class="fas fa-plus" data-action="createWeapon"></i></a>{{/if}}
</legend>
<div class="weapons">
{{#each weapons as |item|}}
{{!log 'weapon' this}}
<div class="weapon item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<div class="name rollable" data-roll-type="weapon" data-tooltip="{{{item.system.description}}}">
{{item.name}}
</div>
<a class="damage rollable" data-item-id="{{item.id}}" data-action="roll" data-roll-type="damage"
data-roll-value="{{item.system.damage}}">{{localize "CTHULHUETERNAL.Label.damageShort"}} :
{{item.system.damage}}</a>
<div class="controls">
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div>
{{/each}}
</div>
</fieldset>
<fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.gears"}}{{#if isEditMode}}
<a class="action" data-tooltip="{{localize " CTHULHUETERNAL.Tooltip.addGear"}}" data-tooltip-direction="UP"><i
class="fas fa-plus" data-action="createGear"></i></a>{{/if}}
</legend>
<div class="gears">
{{#each gears as |item|}}
{{!log 'armor' this}}
<div class="gear" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<div class="name" data-tooltip="{{{item.system.description}}}">
{{item.name}}
</div>
<div class="controls">
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div>
{{/each}}
</div>
</fieldset>
</section>

View File

@ -0,0 +1,52 @@
<section class="vehicle-main vehicle-main-{{ifThen isPlayMode 'play' 'edit'}}">
<fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.vehicle"}}</legend>
<div class="vehicle-pc vehicle-pc-{{ifThen isPlayMode 'play' 'edit'}}">
<div class="vehicle-left">
<div class="vehicle-left-image">
<img class="vehicle-img" src="{{actor.img}}" data-edit="img" data-action="editImage"
data-tooltip="{{actor.name}}" />
</div>
<fieldset>
<legend>{{localize "CTHULHUETERNAL.Label.HP"}}</legend>
<div class="flexrow">
{{formField systemFields.hp.fields.value value=system.hp.value}}
/
{{formField systemFields.hp.fields.max value=system.hp.max rootId=partId disabled=true}}
</div>
</fieldset>
</div>
<div class="vehicle-right">
<div class="vehicle-name">
{{formInput fields.name value=source.name rootId=partId disabled=isPlayMode}}
<a class="control" data-action="toggleSheet" data-tooltip="CTHULHUETERNAL.ToggleSheet"
data-tooltip-direction="UP">
<i class="fa-solid fa-user-{{ifThen isPlayMode 'lock' 'pen'}}"></i>
</a>
</div>
<fieldset class="speed">
<legend>{{localize "CTHULHUETERNAL.Label.Speed"}}</legend>
<div class="flexrow">
{{formField systemFields.surfaceSpeed value=system.surfaceSpeed localize=true}}
{{formField systemFields.airSpeed value=system.airSpeed localize=true}}
</div>
</fieldset>
<fieldset class="armr ">
<legend>{{localize "CTHULHUETERNAL.Label.armor"}}</legend>
<div class="flexrow">
{{formField systemFields.armor value=system.armor localize=true}}
</div>
</fieldset>
</div>
</div>
</fieldset>
</section>

View File

@ -11,6 +11,8 @@
{{formField systemFields.weaponSubtype value=system.weaponSubtype localize=true}} {{formField systemFields.weaponSubtype value=system.weaponSubtype localize=true}}
{{/if}} {{/if}}
{{formField systemFields.state value=system.state localize=true}}
{{formField systemFields.damage value=system.damage}} {{formField systemFields.damage value=system.damage}}
{{formField systemFields.baseRange value=system.baseRange}} {{formField systemFields.baseRange value=system.baseRange}}
{{formField systemFields.rangeUnit value=system.rangeUnit localize=true}} {{formField systemFields.rangeUnit value=system.rangeUnit localize=true}}