Compare commits
	
		
			13 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b21c5ac9bb | |||
| a43bebc63b | |||
| 2b418695c4 | |||
| 5dbb168891 | |||
| 009024296c | |||
| 968c7da5c5 | |||
| 67ff06f953 | |||
| 24c5c685d0 | |||
| d62b5472fe | |||
| a1ef74a3ad | |||
| ff89b62133 | |||
| b3eb908f05 | |||
| 2ac0f53c4f | 
| @@ -27,7 +27,7 @@ jobs: | ||||
|       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 | ||||
|         manifest: https://www.uberwald.me/gitea/public/fvtt-cthulhu-eternal/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 | ||||
| @@ -50,3 +50,14 @@ jobs: | ||||
|           ./fvtt-cthulhu-eternal.zip | ||||
|           system.json | ||||
|         api_key: '${{secrets.ALLOW_PUSH_RELEASE}}' | ||||
|      | ||||
|     - name: Publish to Foundry server   | ||||
|       uses: djlechuck/foundryvtt-publish-package-action@v1 | ||||
|       with: | ||||
|         token: ${{ secrets.FOUNDRYVTT_RELEASE_TOKEN }} | ||||
|         id: 'fvtt-cthulhu-eternal' | ||||
|         version: ${{github.event.release.tag_name}} | ||||
|         manifest: 'https://www.uberwald.me/gitea/public/fvtt-cthulhu-eternal/releases/download/latest/system.json' | ||||
|         notes: 'https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-cthulhu-eternal.zip' | ||||
|         compatibility-minimum: '12' | ||||
|         compatibility-verified: '12' | ||||
							
								
								
									
										15
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,6 +1,15 @@ | ||||
|  | ||||
| <h2><em>Cthulhu Eternal RPG</em> for Foundry Virtual TableTop</h2> | ||||
| # Cthulhu Eternal RPG for FoundryVTT | ||||
|  | ||||
| <div align="center"> | ||||
| Cthulhu Eternal : https://cthulhueternal.com/  | ||||
|  | ||||
| </div> | ||||
| The system contains :  | ||||
|   | ||||
| - Protagonist, Creature and Vehicle sheet | ||||
| - Arcane, Archetype, Armor, Bond, Gear, Injury, Mental Disorder, Motivation, Ritual, Skill, Tome, Weapon items | ||||
| - Support for all available eras | ||||
| - Pre-filled compendium for each era | ||||
| - Specific look&fell for each era | ||||
| - And much more ! | ||||
|  | ||||
| Discord Contact : LeRatierBretonnien (at Official Foundry Discord of French Foundry Discord) | ||||
|   | ||||
							
								
								
									
										1
									
								
								assets/icons/icon_ritual.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/icons/icon_ritual.svg
									
									
									
									
									
										Normal 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 | 
							
								
								
									
										1
									
								
								assets/icons/icon_tome.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/icons/icon_tome.svg
									
									
									
									
									
										Normal 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 | 
							
								
								
									
										8
									
								
								changelog.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								changelog.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| # 12.0.12 | ||||
|  | ||||
| - Add missing skills for WW1, WW2, future and post-apocalyptic | ||||
| - Fix packaging  | ||||
|    | ||||
| # 12.0.11 | ||||
|  | ||||
| - Initial release | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -33,7 +33,8 @@ Hooks.once("init", function () { | ||||
|   CONFIG.Actor.documentClass = documents.CthulhuEternalActor | ||||
|   CONFIG.Actor.dataModels = { | ||||
|     protagonist: models.CthulhuEternalProtagonist, | ||||
|     vehicle: models.CthulhuEternalVehicle | ||||
|     vehicle: models.CthulhuEternalVehicle, | ||||
|     creature: models.CthulhuEternalCreature | ||||
|   } | ||||
|  | ||||
|   CONFIG.Item.documentClass = documents.CthulhuEternalItem | ||||
| @@ -47,13 +48,16 @@ Hooks.once("init", function () { | ||||
|     bond: models.CthulhuEternalBond, | ||||
|     arcane: models.CthulhuEternalArcane, | ||||
|     gear: models.CthulhuEternalGear, | ||||
|     archetype: models.CthulhuEternalArchetype | ||||
|     archetype: models.CthulhuEternalArchetype, | ||||
|     ritual: models.CthulhuEternalRitual, | ||||
|     tome: models.CthulhuEternalTome | ||||
|   } | ||||
|  | ||||
|   // Register sheet application classes | ||||
|   Actors.unregisterSheet("core", ActorSheet) | ||||
|   Actors.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalProtagonistSheet, { types: ["protagonist"], makeDefault: true }) | ||||
|   Actors.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalVehicleSheet, { types: ["vehicle"], makeDefault: true }) | ||||
|   Actors.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalCreatureSheet, { types: ["creature"], makeDefault: true }) | ||||
|  | ||||
|   Items.unregisterSheet("core", ItemSheet) | ||||
|   Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalSkillSheet, { types: ["skill"], makeDefault: true }) | ||||
| @@ -66,6 +70,8 @@ Hooks.once("init", function () { | ||||
|   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.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 | ||||
|   CONFIG.ChatMessage.documentClass = documents.CthulhuEternalChatMessage | ||||
| @@ -91,6 +97,7 @@ Hooks.once("init", function () { | ||||
|   console.info("CTHULHU ETERNAL | System Initialized") | ||||
| }) | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Perform one-time configuration of system configuration objects. | ||||
|  */ | ||||
| @@ -127,7 +134,7 @@ Hooks.on("renderChatMessage", (message, html, data) => { | ||||
|  | ||||
| // Dice-so-nice Ready | ||||
| Hooks.once("diceSoNiceReady", (dice3d) => { | ||||
|   configureDiceSoNice(dice3d) | ||||
|   //configureDiceSoNice(dice3d) | ||||
| }) | ||||
|  | ||||
| /** | ||||
|   | ||||
							
								
								
									
										167
									
								
								lang/en.json
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								lang/en.json
									
									
									
									
									
								
							| @@ -2,7 +2,8 @@ | ||||
|   "TYPES": { | ||||
|     "Actor": { | ||||
|       "protagonist": "Protagonist", | ||||
|       "vehicle": "Vehicle" | ||||
|       "vehicle": "Vehicle", | ||||
|       "creature": "Creature" | ||||
|     }, | ||||
|     "Item": { | ||||
|       "skill": "Skill", | ||||
| @@ -14,7 +15,9 @@ | ||||
|       "mentaldisorder": "Mental Disorder", | ||||
|       "bond": "Bond" , | ||||
|       "arcane": "Arcane", | ||||
|       "archetype": "Archetype" | ||||
|       "archetype": "Archetype", | ||||
|       "ritual": "Ritual", | ||||
|       "tome": "Tome" | ||||
|     } | ||||
|   }, | ||||
|   "CTHULHUETERNAL": { | ||||
| @@ -112,6 +115,83 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "Creature": { | ||||
|       "FIELDS": { | ||||
|         "damageBonus": { | ||||
|           "label": "Dmg.Bonus" | ||||
|         }, | ||||
|         "resources": { | ||||
|           "permanentRating": { | ||||
|             "label": "Permanent Rating" | ||||
|           }, | ||||
|           "hand": { | ||||
|             "label": "Hand" | ||||
|           }, | ||||
|           "stowed": { | ||||
|             "label": "Stowed" | ||||
|           }, | ||||
|           "storage": { | ||||
|             "label": "Storage" | ||||
|           } | ||||
|         }, | ||||
|         "biodata": { | ||||
|           "feature": { | ||||
|             "label": "Feature" | ||||
|           }, | ||||
|           "adaptedToViolence": { | ||||
|             "label": "Adapted to violence" | ||||
|           }, | ||||
|           "adaptedToHelplessness": { | ||||
|             "label": "Adapted to helplessness" | ||||
|           }, | ||||
|           "harshness": { | ||||
|             "label": "Harshness" | ||||
|           }, | ||||
|           "age": { | ||||
|             "label": "Age" | ||||
|           }, | ||||
|           "gender": { | ||||
|             "label": "Gender" | ||||
|           }, | ||||
|           "hair": { | ||||
|             "label": "Hair" | ||||
|           }, | ||||
|           "eyes": { | ||||
|             "label": "Eyes" | ||||
|           }, | ||||
|           "height": { | ||||
|             "label": "Height" | ||||
|           }, | ||||
|           "home": { | ||||
|             "label": "Home" | ||||
|           }, | ||||
|           "birthplace": { | ||||
|             "label": "Birthplace" | ||||
|           }, | ||||
|           "label": "Biodata" | ||||
|         }, | ||||
|         "characteristics:": { | ||||
|           "str": { | ||||
|             "label": "Strength" | ||||
|           }, | ||||
|           "dex": { | ||||
|             "label": "Dexterity" | ||||
|           }, | ||||
|           "int": { | ||||
|             "label": "Intelligence" | ||||
|           }, | ||||
|           "pow": { | ||||
|             "label": "Power" | ||||
|           }, | ||||
|           "con": { | ||||
|             "label": "Constitution" | ||||
|           }, | ||||
|           "char": { | ||||
|             "label": "Charisma" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "Insanity": { | ||||
|       "None": "None", | ||||
|       "Flee": "Flee", | ||||
| @@ -186,6 +266,12 @@ | ||||
|         "riflecarabine": "Rifle/Carabine" | ||||
|       }, | ||||
|       "FIELDS": { | ||||
|         "hasDirectSkill": { | ||||
|           "label": "Has direct skill" | ||||
|         }, | ||||
|         "directSkillValue": { | ||||
|           "label": "Direct skill value" | ||||
|         }, | ||||
|         "state": { | ||||
|           "label": "State" | ||||
|         }, | ||||
| @@ -327,7 +413,80 @@ | ||||
|       "harsh": "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", | ||||
|       "Difficult": "Difficult", | ||||
|       "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": { | ||||
|       "creature": "Creature", | ||||
|       "Rituals": "Rituals", | ||||
|       "Tomes": "Tomes", | ||||
|       "otherBenefits": "Other Benefits", | ||||
|       "Unarmed": "Unarmed", | ||||
|       "Cured": "Cured", | ||||
|       "Uncured": "Uncured", | ||||
| @@ -433,7 +592,9 @@ | ||||
|       "newGear": "New Gear", | ||||
|       "newArcane": "New Arcane", | ||||
|       "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." | ||||
|   | ||||
| @@ -9,4 +9,7 @@ export { default as CthulhuEternalMentalDisorderSheet } from "./sheets/mentaldis | ||||
| export { default as CthulhuEternalGearSheet } from "./sheets/gear-sheet.mjs" | ||||
| export { default as CthulhuEternalMotivationSheet } from "./sheets/motivation-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 CthulhuEternalCreatureSheet } from "./sheets/creature-sheet.mjs" | ||||
| export { default as CthulhuEternalTomeSheet } from "./sheets/tome-sheet.mjs" | ||||
|   | ||||
							
								
								
									
										294
									
								
								module/applications/hud/action-handler.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										294
									
								
								module/applications/hud/action-handler.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,294 @@ | ||||
| // System Module Imports | ||||
| import { Utils } from './utils.js' | ||||
| import { SYSTEM } from "../../config/system.mjs" | ||||
| export let ActionHandler = null | ||||
|  | ||||
| Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { | ||||
|   /** | ||||
|    * Extends Token Action HUD Core's ActionHandler class and builds system-defined actions for the HUD | ||||
|    */ | ||||
|   ActionHandler = class ActionHandler extends coreModule.api.ActionHandler { | ||||
|     /** | ||||
|      * Build system actions | ||||
|      * Called by Token Action HUD Core | ||||
|      * @override | ||||
|      * @param {array} groupIds | ||||
|      */ | ||||
|     async buildSystemActions(groupIds) { | ||||
|       // Set actor and token variables | ||||
|       this.actors = (!this.actor) ? this._getActors() : [this.actor] | ||||
|       this.actorType = this.actor?.type | ||||
|  | ||||
|       // Set items variable | ||||
|       if (this.actor) { | ||||
|         let items = this.actor.items | ||||
|         items = coreModule.api.Utils.sortItemsByName(items) | ||||
|         this.items = items | ||||
|       } | ||||
|  | ||||
|       if (this.actorType !== 'vehicle') { | ||||
|         this.#buildCharacterActions() | ||||
|       } else if (!this.actor) { | ||||
|         this.#buildMultipleTokenActions() | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Build character actions | ||||
|      * @private | ||||
|      */ | ||||
|     #buildCharacterActions() { | ||||
|       this.buildAttributes() | ||||
|       this.buildOther() | ||||
|       this.buildLuck() | ||||
|       this.buildSkills() | ||||
|       this.buildEquipment() | ||||
|     } | ||||
|  | ||||
|     #showValue() { | ||||
|       return game.settings.get('token-action-hud-core', 'tooltips') === 'none' | ||||
|     } | ||||
|  | ||||
|     async buildAttributes() { | ||||
|       const actions = [] | ||||
|       for (const key in this.actor.system.characteristics) { | ||||
|         const encodedValue = [coreModule.api.Utils.i18n('attributes'), key].join(this.delimiter) | ||||
|         const tooltip = { | ||||
|           content: String(this.actor.system.characteristics[key].value * 5), | ||||
|           class: 'tah-system-tooltip', | ||||
|           direction: 'LEFT' | ||||
|         } | ||||
|         actions.push({ | ||||
|           name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.' + key), | ||||
|           id: key, | ||||
|           info1: this.#showValue() ? { text: tooltip.content } : null, | ||||
|           tooltip, | ||||
|           encodedValue | ||||
|         }) | ||||
|       } | ||||
|       await this.addActions(actions, { | ||||
|         id: 'attributes', | ||||
|         type: 'system' | ||||
|       }) | ||||
|     } | ||||
|  | ||||
|     async buildLuck() { | ||||
|       const actions = [] | ||||
|       const tooltip = { | ||||
|         content: '50', | ||||
|         class: 'tah-system-tooltip', | ||||
|         direction: 'LEFT' | ||||
|       } | ||||
|       actions.push({ | ||||
|         name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Luck'), | ||||
|         id: 'luck', | ||||
|         info1: this.#showValue() ? { text: '50' } : null, | ||||
|         tooltip, | ||||
|         encodedValue: ['attributes', 'luck'].join(this.delimiter) | ||||
|       }) | ||||
|       await this.addActions(actions, { id: 'luck', type: 'system' }) | ||||
|     } | ||||
|  | ||||
|     async buildOther() { | ||||
|       if (typeof this.actor.system.sanity.value !== 'undefined') { | ||||
|         const actions = [] | ||||
|         const groupData = { | ||||
|           id: 'other_sanity', | ||||
|           name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.SAN'), | ||||
|           type: 'system' | ||||
|         } | ||||
|         this.addGroup(groupData, { id: 'other', type: 'system' }, true) | ||||
|         const tooltip = { | ||||
|           content: String(this.actor.system.san.value + '/' + this.actor.system.san.max), | ||||
|           class: 'tah-system-tooltip', | ||||
|           direction: 'LEFT' | ||||
|         } | ||||
|         actions.push({ | ||||
|           name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.SAN'), | ||||
|           id: 'sanity', | ||||
|           info1: this.#showValue() ? { text: tooltip.content } : null, | ||||
|           tooltip, | ||||
|           encodedValue: ['attributes', 'sanity'].join(this.delimiter) | ||||
|         }, | ||||
|           { | ||||
|             name: '+', | ||||
|             id: 'sanity_add', | ||||
|             encodedValue: ['attributes', 'sanity_add'].join(this.delimiter) | ||||
|           }, | ||||
|           { | ||||
|             name: '-', | ||||
|             id: 'sanity_subtract', | ||||
|             encodedValue: ['attributes', 'sanity_subtract'].join(this.delimiter) | ||||
|           }) | ||||
|         await this.addActions(actions, { id: 'other_sanity', type: 'system' }) | ||||
|       } | ||||
|       if (typeof this.actor.system.hp.value !== 'undefined') { | ||||
|         const actions = [] | ||||
|         const groupData = { | ||||
|           id: 'other_health', | ||||
|           name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.HP'), | ||||
|           type: 'system' | ||||
|         } | ||||
|         this.addGroup(groupData, { id: 'other', type: 'system' }, true) | ||||
|         const tooltip = { | ||||
|           content: String(this.actor.system.hp.value + '/' + this.actor.system.hp.max), | ||||
|           class: 'tah-system-tooltip', | ||||
|           direction: 'LEFT' | ||||
|         } | ||||
|         actions.push({ | ||||
|           name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.HP'), | ||||
|           id: 'health', | ||||
|           info1: this.#showValue() ? { text: tooltip.content } : null, | ||||
|           tooltip, | ||||
|           encodedValue: ['attributes', 'health'].join(this.delimiter) | ||||
|         }, | ||||
|           { | ||||
|             name: '+', | ||||
|             id: 'health_add', | ||||
|             encodedValue: ['attributes', 'health_add'].join(this.delimiter) | ||||
|           }, | ||||
|           { | ||||
|             name: '-', | ||||
|             id: 'health_subtract', | ||||
|             encodedValue: ['attributes', 'health_subtract'].join(this.delimiter) | ||||
|           }) | ||||
|         await this.addActions(actions, { id: 'other_health', type: 'system' }) | ||||
|       } | ||||
|       if (typeof this.actor.system.wp.value !== 'undefined') { | ||||
|         const actions = [] | ||||
|         const groupData = { | ||||
|           id: 'other_wp', | ||||
|           name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.WP'), | ||||
|           type: 'system' | ||||
|         } | ||||
|         this.addGroup(groupData, { id: 'other', type: 'system' }, true) | ||||
|         const tooltip = { | ||||
|           content: String(this.actor.system.wp.value + '/' + this.actor.system.wp.max), | ||||
|           class: 'tah-system-tooltip', | ||||
|           direction: 'LEFT' | ||||
|         } | ||||
|         actions.push({ | ||||
|           name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.WP'), | ||||
|           id: 'wp', | ||||
|           info1: this.#showValue() ? { text: tooltip.content } : null, | ||||
|           tooltip, | ||||
|           encodedValue: ['attributes', 'wp'].join(this.delimiter) | ||||
|         }, | ||||
|           { | ||||
|             name: '+', | ||||
|             id: 'wp_add', | ||||
|             encodedValue: ['attributes', 'wp_add'].join(this.delimiter) | ||||
|           }, | ||||
|           { | ||||
|             name: '-', | ||||
|             id: 'wp_subtract', | ||||
|             encodedValue: ['attributes', 'wp_subtract'].join(this.delimiter) | ||||
|           }) | ||||
|         await this.addActions(actions, { id: 'other_wp', type: 'system' }) | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     async buildSkills() { | ||||
|       const actions = [] | ||||
|       let actorSkills = this.actor.items.filter(item => item.type === 'skill') | ||||
|       for (const skill in actorSkills) { | ||||
|         if (skill.system.computeScore() > 0) { | ||||
|           const tooltip = { | ||||
|             content: String(skill.skill.system.computeScore()), | ||||
|             direction: 'LEFT' | ||||
|           } | ||||
|           actions.push({ | ||||
|             name: skill.name, | ||||
|             id: skill.id, | ||||
|             info1: this.#showValue() ? { text: tooltip.content } : null, | ||||
|             tooltip, | ||||
|             encodedValue: ['skills', s].join(this.delimiter) | ||||
|           }) | ||||
|         } | ||||
|       } | ||||
|       await this.addActions(actions, { id: 'skills', type: 'system' }) | ||||
|     } | ||||
|  | ||||
|     async buildEquipment() { | ||||
|       let weapons = this.actor.items.filter(item => item.type === 'weapon') | ||||
|       let skills = this.actor.items.filter(item => item.type === 'skill') | ||||
|       for (const item of weapons) { | ||||
|         // Push the weapon name as a new group | ||||
|         const groupData = { | ||||
|           id: 'weapons_' + item._id, | ||||
|           name: item.name, | ||||
|           type: 'system' | ||||
|         } | ||||
|         if (!SYSTEM.WEAPON_SKILL_MAPPING[era] || !SYSTEM.WEAPON_SKILL_MAPPING[era][options.rollItem.system.weaponType]) { | ||||
|           continue | ||||
|         } | ||||
|         let skillName = game.i18n.localize(SYSTEM.WEAPON_SKILL_MAPPING[era][options.rollItem.system.weaponType]) | ||||
|         let skill = skills.find(skill => skill.name.toLowerCase() === skillName.toLowerCase()) | ||||
|         this.addGroup(groupData, { id: 'weapons', type: 'system' }, true) | ||||
|         if (item.type === 'weapon') { | ||||
|           const weapons = [] | ||||
|           const tooltip = { | ||||
|             content: String(skill.system.computeScore()), | ||||
|             direction: 'LEFT' | ||||
|           } | ||||
|           weapons.push({ | ||||
|             name: skill.name, | ||||
|             id: skill._id, | ||||
|             info1: this.#showValue() ? { text: tooltip.content } : null, | ||||
|             encodedValue: ['weapons', item._id].join(this.delimiter), | ||||
|             tooltip | ||||
|           }) | ||||
|           const damageTooltip = { | ||||
|             content: String(item.system.damage), | ||||
|             direction: 'LEFT' | ||||
|           } | ||||
|           if (item.system.damage !== '') { | ||||
|             weapons.push({ | ||||
|               name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Damage'), | ||||
|               id: item._id, | ||||
|               info1: this.#showValue() ? { text: damageTooltip.content } : null, | ||||
|               encodedValue: ['damage', item._id].join(this.delimiter), | ||||
|               tooltip: damageTooltip | ||||
|             }) | ||||
|           } | ||||
|           if (item.system.isLethal) { | ||||
|             const lethalityTooltip = { | ||||
|               content: String(item.system.lethality), | ||||
|               direction: 'LEFT' | ||||
|             } | ||||
|             weapons.push({ | ||||
|               name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Lethality'), | ||||
|               id: item._id, | ||||
|               info1: this.#showValue() ? { text: lethalityTooltip.content } : null, | ||||
|               encodedValue: ['lethality', item._id].join(this.delimiter), | ||||
|               tooltip: lethalityTooltip | ||||
|             }) | ||||
|           } | ||||
|           await this.addActions(weapons, { | ||||
|             id: 'weapons_' + item._id, | ||||
|             type: 'system' | ||||
|           }) | ||||
|         }/* else if (item.type === 'ritual') { | ||||
|                     rituals.push({ | ||||
|                         name: item.name, | ||||
|                         id: item._id, | ||||
|                         encodedValue: ['rituals', item.name].join(this.delimiter) | ||||
|                     }) | ||||
|                 } */ | ||||
|  | ||||
|         /* await this.addActions(rituals, { | ||||
|             id: 'rituals', | ||||
|             type: 'system' | ||||
|         }) */ | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Build multiple token actions | ||||
|      * @private | ||||
|      * @returns {object} | ||||
|      */ | ||||
|     #buildMultipleTokenActions() { | ||||
|     } | ||||
|   } | ||||
| }) | ||||
							
								
								
									
										38
									
								
								module/applications/hud/constants.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								module/applications/hud/constants.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| /** | ||||
|  * Module-based constants | ||||
|  */ | ||||
| export const SYSTEM = { | ||||
|     ID: 'fvtt-cthulhu-eternal' | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Core module | ||||
|  */ | ||||
| export const CORE_MODULE = { | ||||
|     ID: 'token-action-hud-core' | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Core module version required by the system module | ||||
|  */ | ||||
| export const REQUIRED_CORE_MODULE_VERSION = '2.0' | ||||
|  | ||||
| /** | ||||
|  * Action types | ||||
|  */ | ||||
| export const ACTION_TYPE = { | ||||
|     attributes: 'CTHULHUETERNAL.Label.Characteristics', | ||||
|     skills: 'CTHULHUETERNAL.Label.Skill', | ||||
|     equipment: 'CTHULHUETERNAL.Label.Gear' | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Groups | ||||
|  */ | ||||
| export const GROUP = { | ||||
|     attributes: { id: 'attributes', name: 'CTHULHUETERNAL.Label.Characteristics', type: 'system' }, | ||||
|     luck: { id: 'luck', name: 'CTHULHUETERNAL.Label.Luck', type: 'system'}, | ||||
|     skills: { id: 'skills', name: 'CTHULHUETERNAL.Label.Skills', type: 'system' }, | ||||
|     weapons: { id: 'weapons', name: 'CTHULHUETERNAL.Label.Weapons', type: 'system' }, | ||||
|     rituals: { id: 'rituals', name: 'CTHULHUETERNAL.Label.Rituals', type: 'system' } | ||||
| } | ||||
							
								
								
									
										49
									
								
								module/applications/hud/defaults.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								module/applications/hud/defaults.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| import { GROUP } from './constants.js' | ||||
|  | ||||
| /** | ||||
|  * Default layout and groups | ||||
|  */ | ||||
| export let DEFAULTS = null | ||||
|  | ||||
| Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { | ||||
|     const groups = GROUP | ||||
|     Object.values(groups).forEach(group => { | ||||
|         group.name = coreModule.api.Utils.i18n(group.name) | ||||
|         group.listName = `Group: ${coreModule.api.Utils.i18n(group.listName ?? group.name)}` | ||||
|     }) | ||||
|     const groupsArray = Object.values(groups) | ||||
|     DEFAULTS = { | ||||
|         layout: [ | ||||
|             { | ||||
|                 nestId: 'statistics', | ||||
|                 id: 'statistics', | ||||
|                 name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Characteristics'), | ||||
|                 groups: [ | ||||
|                     { ...groups.attributes, nestId: 'statistics_attributes' }, | ||||
|                     { ...groups.other, nestId: 'statistics_other' }, | ||||
|                     { ...groups.luck, nestId: 'statistics_luck' } | ||||
|                 ] | ||||
|             }, | ||||
|             { | ||||
|                 nestId: 'skills', | ||||
|                 id: 'skills', | ||||
|                 name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Skills'), | ||||
|                 groups: [ | ||||
|                     { ...groups.skills, nestId: 'skills_skills' }, | ||||
|                     { ...groups.typedSkills, nestId: 'skills_typed' }, | ||||
|                     { ...groups.specialTraining, nestId: 'skills_special' } | ||||
|                 ] | ||||
|             }, | ||||
|             { | ||||
|                 nestId: 'equipment', | ||||
|                 id: 'equipment', | ||||
|                 name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Gear'), | ||||
|                 groups: [ | ||||
|                     { ...groups.weapons, nestId: 'equipment_weapons' }, | ||||
|                     { ...groups.rituals, nestId: 'equipment_rituals' } | ||||
|                 ] | ||||
|             } | ||||
|         ], | ||||
|         groups: groupsArray | ||||
|     } | ||||
| }) | ||||
							
								
								
									
										304
									
								
								module/applications/hud/roll-handler.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								module/applications/hud/roll-handler.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,304 @@ | ||||
| import { SYSTEM } from "../../config/system.mjs" | ||||
| import CthulhuEternalRoll  from '../../documents/roll.mjs' | ||||
|  | ||||
| export let RollHandler = null | ||||
|  | ||||
| Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { | ||||
|     /** | ||||
|      * Extends Token Action HUD Core's RollHandler class and handles action events triggered when an action is clicked | ||||
|      */ | ||||
|     RollHandler = class RollHandler extends coreModule.api.RollHandler { | ||||
|         /** | ||||
|          * Handle action click | ||||
|          * Called by Token Action HUD Core when an action is left or right-clicked | ||||
|          * @override | ||||
|          * @param {object} event        The event | ||||
|          * @param {string} encodedValue The encoded value | ||||
|          */ | ||||
|         async handleActionClick (event, encodedValue) { | ||||
|             const [actionTypeId, actionId] = encodedValue.split('|') | ||||
|  | ||||
|             const knownCharacters = ['character'] | ||||
|  | ||||
|             // If single actor is selected | ||||
|             if (this.actor) { | ||||
|                 await this.#handleAction(event, this.actor, this.token, actionTypeId, actionId) | ||||
|                 return | ||||
|             } | ||||
|  | ||||
|             const controlledTokens = canvas.tokens.controlled | ||||
|                 .filter((token) => knownCharacters.includes(token.actor?.type)) | ||||
|  | ||||
|             // If multiple actors are selected | ||||
|             for (const token of controlledTokens) { | ||||
|                 const actor = token.actor | ||||
|                 await this.#handleAction(event, actor, token, actionTypeId, actionId) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Handle action hover | ||||
|          * Called by Token Action HUD Core when an action is hovered on or off | ||||
|          * @override | ||||
|          * @param {object} event        The event | ||||
|          * @param {string} encodedValue The encoded value | ||||
|          */ | ||||
|         async handleActionHover (event, encodedValue) { | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Handle group click | ||||
|          * Called by Token Action HUD Core when a group is right-clicked while the HUD is locked | ||||
|          * @override | ||||
|          * @param {object} event The event | ||||
|          * @param {object} group The group | ||||
|          */ | ||||
|         async handleGroupClick (event, group) { | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Handle action | ||||
|          * @private | ||||
|          * @param {object} event        The event | ||||
|          * @param {object} actor        The actor | ||||
|          * @param {object} token        The token | ||||
|          * @param {string} actionTypeId The action type id | ||||
|          * @param {string} actionId     The actionId | ||||
|          */ | ||||
|         async #handleAction (event, actor, token, actionTypeId, actionId) { | ||||
|             switch (actionTypeId) { | ||||
|             case 'attributes': | ||||
|                 await this.#handleAttributesAction(event, actor, actionId) | ||||
|                 break | ||||
|             case 'skills': | ||||
|                 await this.#handleSkillsAction(event, actor, actionId) | ||||
|                 break | ||||
|             case 'weapons': | ||||
|                 await this.#handleWeaponsAction(event, actor, actionId) | ||||
|                 break | ||||
|             case 'damage': | ||||
|                 await this.#handleDamageAction(event, actor, actionId) | ||||
|                 break | ||||
|             case 'lethality': | ||||
|                 await this.#handleLethalityAction(event, actor, actionId) | ||||
|                 break | ||||
|             case 'specialTraining': | ||||
|                 await this.#handleSpecialTrainingAction(event, actor, actionId) | ||||
|                 break | ||||
|             case 'typedSkills': | ||||
|                 await this.#handleCustomTypedAction(event, actor, actionId) | ||||
|                 break | ||||
|                 /* case 'rituals': | ||||
|                 await this.#handleRitualsAction(event, actor, actionId) | ||||
|                 break */ | ||||
|             case 'utility': | ||||
|                 await this.#handleUtilityAction(token, actionId) | ||||
|                 break | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Handle Attribute action | ||||
|          * @private | ||||
|          * @param {object} event    The event | ||||
|          * @param {object} actor    The actor | ||||
|          * @param {string} actionId The action id | ||||
|          */ | ||||
|         async #handleAttributesAction (event, actor, actionId) { | ||||
|             let rollType | ||||
|             if (actionId === 'wp' || actionId === 'health') return | ||||
|             if (actionId.includes('_add') || actionId.includes('_subtract')) { | ||||
|                 const attr = actionId.split('_')[0] | ||||
|                 const action = actionId.split('_')[1] | ||||
|                 const update = {} | ||||
|                 update.system = {} | ||||
|                 update.system[attr] = {} | ||||
|                 update.system[attr].value = action === 'add' ? this.actor.system[attr].value + 1 : this.actor.system[attr].value - 1 | ||||
|                 if (update.system[attr].value > this.actor.system[attr].max || update.system[attr].value < this.actor.system[attr].min) return | ||||
|                 return await this.actor.update(update) | ||||
|             } | ||||
|             if (actionId === 'sanity') { | ||||
|                 rollType = actionId | ||||
|             } else if (actionId === 'luck') { | ||||
|                 rollType = actionId | ||||
|             } else { | ||||
|                 rollType = 'stat' | ||||
|             } | ||||
|             const options = { | ||||
|                 actor: this.actor, | ||||
|                 rollType, | ||||
|                 key: actionId | ||||
|             } | ||||
|  | ||||
|             const roll = new DGPercentileRoll('1D100', {}, options) | ||||
|             return await this.actor.sheet.processRoll(event, roll) | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Handle Skill action | ||||
|          * @private | ||||
|          * @param {object} event    The event | ||||
|          * @param {object} actor    The actor | ||||
|          * @param {string} actionId The action id | ||||
|          */ | ||||
|         async #handleSkillsAction (event, actor, actionId) { | ||||
|             const options = { | ||||
|                 actor: this.actor, | ||||
|                 rollType: 'skill', | ||||
|                 key: actionId | ||||
|             } | ||||
|  | ||||
|             const skill = this.actor.system.skills[actionId] | ||||
|             if (!skill) return ui.notifications.warn('Bad skill name in HUD.') | ||||
|  | ||||
|             const roll = new DGPercentileRoll('1D100', {}, options) | ||||
|             await this.actor.sheet.processRoll(event, roll) | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Handle Typed/Custom skills action | ||||
|          * @private | ||||
|          * @param {object} event    The event | ||||
|          * @param {object} actor    The actor | ||||
|          * @param {string} actionId The action id | ||||
|          */ | ||||
|         async #handleCustomTypedAction (event, actor, actionId) { | ||||
|             const options = { | ||||
|                 actor: this.actor, | ||||
|                 rollType: 'skill', | ||||
|                 key: actionId | ||||
|             } | ||||
|             const roll = new DGPercentileRoll('1D100', {}, options) | ||||
|             await this.actor.sheet.processRoll(event, roll) | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Handle SoecialTraining action | ||||
|          * @private | ||||
|          * @param {object} event    The event | ||||
|          * @param {object} actor    The actor | ||||
|          * @param {string} actionId The action id | ||||
|          */ | ||||
|         async #handleSpecialTrainingAction (event, actor, actionId) { | ||||
|             const attr = this.actor.system.specialTraining.find(a => a.name === actionId).attribute | ||||
|             let target = 0 | ||||
|             if (DG.statistics.includes(attr)) { | ||||
|                 target = this.actor.system.statistics[attr].x5 | ||||
|             } else if (DG.skills.includes(attr)) { | ||||
|                 target = this.actor.system.skills[attr].proficiency | ||||
|             } else { | ||||
|                 target = this.actor.system.typedSkills[attr].proficiency | ||||
|             } | ||||
|             const options = { | ||||
|                 actor: this.actor, | ||||
|                 rollType: 'special-training', | ||||
|                 key: attr, | ||||
|                 specialTrainingName: actionId, | ||||
|                 target | ||||
|             } | ||||
|             const roll = new DGPercentileRoll('1D100', {}, options) | ||||
|             await this.actor.sheet.processRoll(event, roll) | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Handle Weapon action | ||||
|          * @private | ||||
|          * @param {object} event    The event | ||||
|          * @param {object} actor    The actor | ||||
|          * @param {string} actionId The action id | ||||
|          */ | ||||
|         async #handleWeaponsAction (event, actor, actionId) { | ||||
|             const item = this.actor.items.get(actionId) | ||||
|             const options = { | ||||
|                 actor: this.actor, | ||||
|                 rollType: 'weapon', | ||||
|                 key: item.system.skill, | ||||
|                 item | ||||
|             } | ||||
|             const roll = new DGPercentileRoll('1D100', {}, options) | ||||
|             await this.actor.sheet.processRoll(event, roll) | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Handle Damage action | ||||
|          * @private | ||||
|          * @param {object} event    The event | ||||
|          * @param {object} actor    The actor | ||||
|          * @param {string} actionId The action id | ||||
|          */ | ||||
|         async #handleDamageAction (event, actor, actionId) { | ||||
|             const item = this.actor.items.get(actionId) | ||||
|             if (item.system.lethality > 0 && event.ctrlKey) { | ||||
|                 // Toggle on/off lethality | ||||
|                 const isLethal = !item.system.isLethal | ||||
|                 await item.update({ 'system.isLethal': isLethal }) | ||||
|             } else { | ||||
|                 const options = { | ||||
|                     actor: this.actor, | ||||
|                     rollType: 'damage', | ||||
|                     key: item.system.damage, | ||||
|                     item | ||||
|                 } | ||||
|                 const roll = new DGDamageRoll(item.system.damage, {}, options) | ||||
|                 await this.actor.sheet.processRoll(event, roll) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Handle Lethality action | ||||
|          * @private | ||||
|          * @param {object} event    The event | ||||
|          * @param {object} actor    The actor | ||||
|          * @param {string} actionId The action id | ||||
|          */ | ||||
|         async #handleLethalityAction (event, actor, actionId) { | ||||
|             const item = await this.actor.items.get(actionId) | ||||
|             if (item.system.damage !== '' && event.ctrlKey) { | ||||
|                 const isLethal = !item.system.isLethal | ||||
|                 await item.update({ 'system.isLethal': isLethal }) | ||||
|             } else { | ||||
|                 const options = { | ||||
|                     actor: this.actor, | ||||
|                     rollType: 'lethality', | ||||
|                     key: item.system.lethality, | ||||
|                     item | ||||
|                 } | ||||
|                 const roll = new DGLethalityRoll(item.system.damage, {}, options) | ||||
|                 await this.actor.sheet.processRoll(event, roll) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Handle Ritual action | ||||
|          * @private | ||||
|          * @param {object} event    The event | ||||
|          * @param {object} actor    The actor | ||||
|          * @param {string} actionId The action id | ||||
|          */ | ||||
|         async #handleRitualsAction (event, actor, actionId) { | ||||
|             const options = { | ||||
|                 actor: this.actor, | ||||
|                 rollType: 'ritual', | ||||
|                 key: actionId | ||||
|             } | ||||
|             const roll = new DGPercentileRoll('1D100', {}, options) | ||||
|             await this.actor.sheet.processRoll(event, roll) | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Handle utility action | ||||
|          * @private | ||||
|          * @param {object} token    The token | ||||
|          * @param {string} actionId The action id | ||||
|          */ | ||||
|         async #handleUtilityAction (token, actionId) { | ||||
|             switch (actionId) { | ||||
|             case 'endTurn': | ||||
|                 if (game.combat?.current?.tokenId === token.id) { | ||||
|                     await game.combat?.nextTurn() | ||||
|                 } | ||||
|                 break | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }) | ||||
							
								
								
									
										91
									
								
								module/applications/hud/system-manager.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								module/applications/hud/system-manager.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| // System Module Imports | ||||
| import { ActionHandler } from './action-handler.js' | ||||
| import { RollHandler as Core } from './roll-handler.js' | ||||
| import { SYSTEM } from './constants.js' | ||||
| import { DEFAULTS } from './defaults.js' | ||||
|  | ||||
| export let SystemManager = null | ||||
|  | ||||
| Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { | ||||
|     /** | ||||
|      * Extends Token Action HUD Core's SystemManager class | ||||
|      */ | ||||
|     SystemManager = class SystemManager extends coreModule.api.SystemManager { | ||||
|         /** | ||||
|          * Returns an instance of the ActionHandler to Token Action HUD Core | ||||
|          * Called by Token Action HUD Core | ||||
|          * @override | ||||
|          * @returns {class} The ActionHandler instance | ||||
|          */ | ||||
|         getActionHandler () { | ||||
|             return new ActionHandler() | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Returns a list of roll handlers to Token Action HUD Core | ||||
|          * Used to populate the Roll Handler module setting choices | ||||
|          * Called by Token Action HUD Core | ||||
|          * @override | ||||
|          * @returns {object} The available roll handlers | ||||
|          */ | ||||
|         getAvailableRollHandlers () { | ||||
|             const coreTitle = 'Core Template' | ||||
|             const choices = { core: coreTitle } | ||||
|             return choices | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Returns an instance of the RollHandler to Token Action HUD Core | ||||
|          * Called by Token Action HUD Core | ||||
|          * @override | ||||
|          * @param {string} rollHandlerId The roll handler ID | ||||
|          * @returns {class}              The RollHandler instance | ||||
|          */ | ||||
|         getRollHandler (rollHandlerId) { | ||||
|             let rollHandler | ||||
|             switch (rollHandlerId) { | ||||
|             case 'core': | ||||
|             default: | ||||
|                 rollHandler = new Core() | ||||
|                 break | ||||
|             } | ||||
|             return rollHandler | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Returns the default layout and groups to Token Action HUD Core | ||||
|          * Called by Token Action HUD Core | ||||
|          * @returns {object} The default layout and groups | ||||
|          */ | ||||
|         async registerDefaults () { | ||||
|             return DEFAULTS | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Register Token Action HUD system module settings | ||||
|          * Called by Token Action HUD Core | ||||
|          * @override | ||||
|          * @param {function} coreUpdate The Token Action HUD Core update function | ||||
|          */ | ||||
|         registerSettings (coreUpdate) { | ||||
|             /*systemSettings.register(coreUpdate)*/ | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Returns styles to Token Action HUD Core | ||||
|          * Called by Token Action HUD Core | ||||
|          * @override | ||||
|          * @returns {object} The TAH system styles | ||||
|          */ | ||||
|         registerStyles () { | ||||
|             return { | ||||
|                 template: { | ||||
|                     class: 'tah-style-template-style', // The class to add to first DIV element | ||||
|                     file: 'tah-template-style', // The file without the css extension | ||||
|                     moduleId: SYSTEM.ID, // The module ID | ||||
|                     name: 'Template Style' // The name to display in the Token Action HUD Core 'Style' module setting | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }) | ||||
							
								
								
									
										55
									
								
								module/applications/hud/utils.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								module/applications/hud/utils.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| import { SYSTEM } from './constants.js' | ||||
|  | ||||
| export let Utils = null | ||||
|  | ||||
| function registerHUD() { | ||||
|   Hooks.on('tokenActionHudCoreApiReady', async () => { | ||||
|     /** | ||||
|      * Return the SystemManager and requiredCoreModuleVersion to Token Action HUD Core | ||||
|      */ | ||||
|     const module = game.system | ||||
|     module.api = { | ||||
|       requiredCoreModuleVersion: "2.0", | ||||
|       SystemManager | ||||
|     } | ||||
|     Hooks.call('tokenActionHudSystemReady', module) | ||||
|   }) | ||||
|  | ||||
| } | ||||
|  | ||||
| Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { | ||||
|   /** | ||||
|    * Utility functions | ||||
|    */ | ||||
|   Utils = class Utils { | ||||
|     /** | ||||
|      * Get setting | ||||
|      * @param {string} key               The key | ||||
|      * @param {string=null} defaultValue The default value | ||||
|      * @returns {string}                 The setting value | ||||
|      */ | ||||
|     static getSetting(key, defaultValue = null) { | ||||
|       let value = defaultValue ?? null | ||||
|       try { | ||||
|         value = game.settings.get(SYSTEM.ID, key) | ||||
|       } catch { | ||||
|         coreModule.api.Logger.debug(`Setting '${key}' not found`) | ||||
|       } | ||||
|       return value | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set setting | ||||
|      * @param {string} key   The key | ||||
|      * @param {string} value The value | ||||
|      */ | ||||
|     static async setSetting(key, value) { | ||||
|       try { | ||||
|         value = await game.settings.set(MODULE.ID, key, value) | ||||
|         coreModule.api.Logger.debug(`Setting '${key}' set to '${value}'`) | ||||
|       } catch { | ||||
|         coreModule.api.Logger.debug(`Setting '${key}' not found`) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| }) | ||||
| @@ -96,7 +96,6 @@ export default class CthulhuEternalActorSheet extends HandlebarsApplicationMixin | ||||
|         drop: this._canDragDrop.bind(this), | ||||
|       } | ||||
|       d.callbacks = { | ||||
|         dragstart: this._onDragStart.bind(this), | ||||
|         dragover: this._onDragOver.bind(this), | ||||
|         drop: this._onDrop.bind(this), | ||||
|       } | ||||
| @@ -133,70 +132,6 @@ export default class CthulhuEternalActorSheet extends HandlebarsApplicationMixin | ||||
|     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. | ||||
|    * @param {DragEvent} event       The originating DragEvent | ||||
|   | ||||
							
								
								
									
										175
									
								
								module/applications/sheets/creature-sheet.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								module/applications/sheets/creature-sheet.mjs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | ||||
| import CthulhuEternalActorSheet from "./base-actor-sheet.mjs" | ||||
|  | ||||
| export default class CthulhuEternalCreatureSheet extends CthulhuEternalActorSheet { | ||||
|   /** @override */ | ||||
|   static DEFAULT_OPTIONS = { | ||||
|     classes: ["creature"], | ||||
|     position: { | ||||
|       width: 860, | ||||
|       height: 620, | ||||
|     }, | ||||
|     window: { | ||||
|       contentClasses: ["creature-content"], | ||||
|     }, | ||||
|     actions: { | ||||
|       createArmor: CthulhuEternalCreatureSheet.#onCreateArmor, | ||||
|       createWeapon: CthulhuEternalCreatureSheet.#onCreateWeapon, | ||||
|       createSkill: CthulhuEternalCreatureSheet.#onCreateSkill, | ||||
|  | ||||
|     }, | ||||
|   } | ||||
|  | ||||
|   /** @override */ | ||||
|   static PARTS = { | ||||
|     main: { | ||||
|       template: "systems/fvtt-cthulhu-eternal/templates/creature-main.hbs", | ||||
|     }, | ||||
|     tabs: { | ||||
|       template: "templates/generic/tab-navigation.hbs", | ||||
|     }, | ||||
|     skills: { | ||||
|       template: "systems/fvtt-cthulhu-eternal/templates/creature-skills.hbs", | ||||
|     }, | ||||
|     biography: { | ||||
|       template: "systems/fvtt-cthulhu-eternal/templates/creature-biography.hbs", | ||||
|     }, | ||||
|   } | ||||
|  | ||||
|   /** @override */ | ||||
|   tabGroups = { | ||||
|     sheet: "skills", | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Prepare an array of form header tabs. | ||||
|    * @returns {Record<string, Partial<ApplicationTab>>} | ||||
|    */ | ||||
|   #getTabs() { | ||||
|     const tabs = { | ||||
|       skills: { id: "skills", group: "sheet", icon: "fa-solid fa-shapes", label: "CTHULHUETERNAL.Label.skills" }, | ||||
|       biography: { id: "biography", group: "sheet", icon: "fa-solid fa-book", label: "CTHULHUETERNAL.Label.biography" }, | ||||
|     } | ||||
|     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 }) | ||||
|      | ||||
|     context.tooltipsCharacteristic = { | ||||
|       str: game.i18n.localize("CTHULHUETERNAL.Characteristic.Str"), | ||||
|       dex: game.i18n.localize("CTHULHUETERNAL.Characteristic.Dex"), | ||||
|       con: game.i18n.localize("CTHULHUETERNAL.Characteristic.Con"), | ||||
|       int: game.i18n.localize("CTHULHUETERNAL.Characteristic.Int"), | ||||
|       pow: game.i18n.localize("CTHULHUETERNAL.Characteristic.Pow"), | ||||
|       cha: game.i18n.localize("CTHULHUETERNAL.Characteristic.Cha") | ||||
|     } | ||||
|  | ||||
|     return context | ||||
|   } | ||||
|  | ||||
|   /** @override */ | ||||
|   async _preparePartContext(partId, context) { | ||||
|     const doc = this.document | ||||
|     switch (partId) { | ||||
|       case "main": | ||||
|         break | ||||
|       case "skills": | ||||
|         context.tab = context.tabs.skills | ||||
|         context.skills = doc.itemTypes.skill | ||||
|         context.skills.sort((a, b) => a.name.localeCompare(b.name)) | ||||
|         context.weapons = doc.itemTypes.weapon | ||||
|         context.weapons.sort((a, b) => a.name.localeCompare(b.name)) | ||||
|         context.armors = doc.itemTypes.armor | ||||
|         context.armors.sort((a, b) => a.name.localeCompare(b.name)) | ||||
|         break | ||||
|       case "biography": | ||||
|         context.tab = context.tabs.biography | ||||
|         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 #onCreateWeapon(event, target) { | ||||
|     this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newWeapon"), type: "weapon" }]) | ||||
|   } | ||||
|  | ||||
|   static #onCreateArmor(event, target) { | ||||
|     this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newArmor"), type: "armor" }]) | ||||
|   } | ||||
|  | ||||
|   static #onCreateSkill(event, target) { | ||||
|     this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newSkill"), type: "skill" }]) | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Handles the roll action triggered by user interaction. | ||||
|    * | ||||
|    * @param {PointerEvent} event The event object representing the user interaction. | ||||
|    * @param {HTMLElement} target The target element that triggered the roll. | ||||
|    * | ||||
|    * @returns {Promise<void>} A promise that resolves when the roll action is complete. | ||||
|    * | ||||
|    * @throws {Error} Throws an error if the roll type is not recognized. | ||||
|    * | ||||
|    * @description This method checks the current mode (edit or not) and determines the type of roll | ||||
|    * (save, resource, or damage) based on the target element's data attributes. It retrieves the | ||||
|    * corresponding value from the document's system and performs the roll. | ||||
|    */ | ||||
|   async _onRoll(event, target) { | ||||
|     const rollType = $(event.currentTarget).data("roll-type") | ||||
|     let item | ||||
|     let li | ||||
|     // Debug : console.log(">>>>", event, target, rollType) | ||||
|     // Deprecated : if (this.isEditMode) return | ||||
|     switch (rollType) { | ||||
|       case "char": | ||||
|         let charId = $(event.currentTarget).data("char-id") | ||||
|         item = foundry.utils.duplicate(this.actor.system.characteristics[charId]) | ||||
|         item.name = game.i18n.localize(`CTHULHUETERNAL.Label.${charId}Long`) | ||||
|         item.targetScore = item.value * 5 | ||||
|         break | ||||
|       case "skill": | ||||
|         li = $(event.currentTarget).parents(".item"); | ||||
|         item = this.actor.items.get(li.data("item-id")); | ||||
|         break | ||||
|       case "weapon": | ||||
|       case "damage": | ||||
|         li = $(event.currentTarget).parents(".item"); | ||||
|         item = this.actor.items.get(li.data("item-id")); | ||||
|         item.damageBonus = this.actor.system.damageBonus | ||||
|         break | ||||
|       default: | ||||
|         throw new Error(`Unknown roll type ${rollType}`) | ||||
|     } | ||||
|     await this.document.system.roll(rollType, item) | ||||
|   } | ||||
|  | ||||
|   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) | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -20,7 +20,9 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS | ||||
|       createInjury: CthulhuEternalProtagonistSheet.#onCreateInjury, | ||||
|       createMentalDisorder: CthulhuEternalProtagonistSheet.#onCreateMentalDisorder, | ||||
|       createMotivation: CthulhuEternalProtagonistSheet.#onCreateMotivation, | ||||
|       createSkill: CthulhuEternalProtagonistSheet.#onCreateSkill | ||||
|       createSkill: CthulhuEternalProtagonistSheet.#onCreateSkill, | ||||
|       createRitual: CthulhuEternalProtagonistSheet.#onCreateRitual, | ||||
|       createTome: CthulhuEternalProtagonistSheet.#onCreateTome, | ||||
|     }, | ||||
|   } | ||||
|  | ||||
| @@ -108,6 +110,10 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS | ||||
|         context.armors.sort((a, b) => a.name.localeCompare(b.name)) | ||||
|         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 | ||||
|       case "status": | ||||
|         context.tab = context.tabs.status | ||||
| @@ -170,6 +176,14 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS | ||||
|     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. | ||||
|    * | ||||
|   | ||||
							
								
								
									
										28
									
								
								module/applications/sheets/ritual-sheet.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								module/applications/sheets/ritual-sheet.mjs
									
									
									
									
									
										Normal 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 | ||||
|   } | ||||
| } | ||||
							
								
								
									
										28
									
								
								module/applications/sheets/tome-sheet.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								module/applications/sheets/tome-sheet.mjs
									
									
									
									
									
										Normal 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 | ||||
|   } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| import LethalFantasyItemSheet from "./base-item-sheet.mjs" | ||||
| import CthulhuEternalItemSheet from "./base-item-sheet.mjs" | ||||
|  | ||||
| export default class LethalFantasyWeaponSheet extends LethalFantasyItemSheet { | ||||
| export default class CthulhuEternalWeaponSheet extends CthulhuEternalItemSheet { | ||||
|   /** @override */ | ||||
|   static DEFAULT_OPTIONS = { | ||||
|     classes: ["weapon"], | ||||
|   | ||||
| @@ -42,7 +42,7 @@ export const INSANITY = { | ||||
| } | ||||
|  | ||||
| export const ERA_CSS = { | ||||
|   jazz: { primaryFont: "RozhaOne", secondaryFont: "RozhaOne", titleFont: "Broadway", baseFontSize: "1.0rem", titleFontSize: "1.2rem", 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", 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: "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", baseFontSize: "1.0rem", titleFontSize: "1.2rem",imgFilter: "brightness(0) saturate(100%) invert(100%) sepia(59%) saturate(1894%) hue-rotate(337deg) brightness(88%) contrast(98%)" }, | ||||
| @@ -53,7 +53,7 @@ export const ERA_CSS = { | ||||
|   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: "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: "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", baseFontSize: "1.25rem",titleFontSize: "1.5rem",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.35rem",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 = { | ||||
| @@ -238,6 +238,13 @@ export const MULTIPLIER_CHOICES = { | ||||
|   "5": "5" | ||||
| } | ||||
|  | ||||
| export const RITUAL_TYPES = { | ||||
|   "simple": "CTHULHUETERNAL.Ritual.Simple", | ||||
|   "difficult": "CTHULHUETERNAL.Ritual.Difficult", | ||||
|   "complex": "CTHULHUETERNAL.Ritual.Complex", | ||||
|   "elaborate": "CTHULHUETERNAL.Ritual.Elaborate" | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Include all constant definitions within the SYSTEM global export | ||||
|  * @type {Object} | ||||
| @@ -261,5 +268,6 @@ export const SYSTEM = { | ||||
|   MODIFIER_CHOICES, | ||||
|   MULTIPLIER_CHOICES, | ||||
|   ASCII, | ||||
|   DAMAGE_BONUS | ||||
|   DAMAGE_BONUS, | ||||
|   RITUAL_TYPES | ||||
| } | ||||
|   | ||||
| @@ -9,6 +9,8 @@ export const defaultItemImg = { | ||||
|   arcane: "systems/fvtt-cthulhu-eternal/assets/icons/icon_arcane.svg", | ||||
|   injury: "systems/fvtt-cthulhu-eternal/assets/icons/icon_injury.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 { | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
|  | ||||
| import { SYSTEM } from "../config/system.mjs" | ||||
|  | ||||
| export default class CthulhuEternalRoll extends Roll { | ||||
|   /** | ||||
|    * The HTML template path used to render dice checks of this type | ||||
| @@ -146,6 +147,24 @@ export default class CthulhuEternalRoll extends Roll { | ||||
|         options.isNudge = false | ||||
|         break | ||||
|       case "damage": | ||||
|         let isLethal = false | ||||
|         options.isNudge = false | ||||
|         if (options.rollItem.system.lethality > 0) { | ||||
|           let lethalityRoll = new Roll("1d100") | ||||
|           await lethalityRoll.evaluate() | ||||
|           isLethal = (lethalityRoll.total <= options.rollItem.system.lethality) | ||||
|           let flavor = `${options.rollItem.name} - <strong>Lethality Roll</strong> : ${lethalityRoll.total} <= ${options.rollItem.system.lethality} => ${isLethal}` | ||||
|           if ( isLethal) { | ||||
|             flavor += `<br>The target is lethally wounded => HP = 0` | ||||
|           } else { | ||||
|             let wounds = Math.floor(lethalityRoll.total/10) + (lethalityRoll.total % 10) | ||||
|             flavor += `<br>The target is not lethally wounded => HP loss = ${wounds}` | ||||
|           } | ||||
|           await lethalityRoll.toMessage({ | ||||
|             flavor:flavor | ||||
|           }); | ||||
|           return | ||||
|         } | ||||
|         let formula = options.rollItem.system.damage | ||||
|         if ( options.rollItem.system.weaponType === "melee" || options.rollItem.system.weaponType === "unarmed") { | ||||
|           formula += ` + ${options.rollItem.damageBonus}` | ||||
| @@ -155,16 +174,6 @@ export default class CthulhuEternalRoll extends Roll { | ||||
|         await damageRoll.toMessage({ | ||||
|           flavor: `${options.rollItem.name} - Damage Roll` | ||||
|         }); | ||||
|         let isLethal = false | ||||
|         options.isNudge = false | ||||
|         if (options.rollItem.system.lethality > 0) { | ||||
|           let lethalityRoll = new Roll("1d100") | ||||
|           await lethalityRoll.evaluate() | ||||
|           isLethal = (lethalityRoll.total <= options.rollItem.system.lethality) | ||||
|           await lethalityRoll.toMessage({ | ||||
|             flavor: `${options.rollItem.name} - Lethality Roll : ${lethalityRoll.total} <= ${options.rollItem.system.lethality} => ${isLethal}` | ||||
|           }); | ||||
|         } | ||||
|         return | ||||
|       case "weapon": | ||||
|         let era = game.settings.get("fvtt-cthulhu-eternal", "settings-era") | ||||
| @@ -178,9 +187,14 @@ export default class CthulhuEternalRoll extends Roll { | ||||
|           console.log("WP Not found", era, options.rollItem.system.weaponType) | ||||
|           return | ||||
|         } | ||||
|         options.weapon = options.rollItem | ||||
|         if (options.rollItem.system.hasDirectSkill) { | ||||
|           let skillName = options.rollItem.name | ||||
|           options.rollItem = {type: "skill", name: skillName, system: {base: 0, bonus:  options.weapon.system.directSkillValue} } | ||||
|           options.initialScore = options.weapon.system.directSkillValue | ||||
|         } else { | ||||
|           let skillName = game.i18n.localize(SYSTEM.WEAPON_SKILL_MAPPING[era][options.rollItem.system.weaponType]) | ||||
|           let actor = game.actors.get(options.actorId) | ||||
|         options.weapon = options.rollItem | ||||
|           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")) | ||||
| @@ -188,6 +202,7 @@ export default class CthulhuEternalRoll extends Roll { | ||||
|           } | ||||
|           options.initialScore = options.rollItem.system.computeScore() | ||||
|           console.log("WEAPON", skillName, era, options.rollItem) | ||||
|         } | ||||
|         break | ||||
|       default: | ||||
|         options.initialScore = 50 | ||||
|   | ||||
| @@ -9,5 +9,8 @@ export { default as CthulhuEternalBond } from "./bond.mjs" | ||||
| export { default as CthulhuEternalGear } from "./gear.mjs" | ||||
| export { default as CthulhuEternalMotivation } from "./motivation.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 CthulhuEternalCreature } from "./creature.mjs" | ||||
| export { default as CthulhuEternalTome } from "./tome.mjs" | ||||
|  | ||||
|   | ||||
							
								
								
									
										80
									
								
								module/models/creature.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								module/models/creature.mjs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| import { SYSTEM } from "../config/system.mjs" | ||||
| import CthulhuEternalRoll from "../documents/roll.mjs" | ||||
|  | ||||
| export default class CthulhuEternalCreature extends foundry.abstract.TypeDataModel { | ||||
|   static defineSchema() { | ||||
|     const fields = foundry.data.fields | ||||
|     const requiredInteger = { required: true, nullable: false, integer: true } | ||||
|     const schema = {} | ||||
|  | ||||
|     // Carac | ||||
|     const characteristicField = (label) => { | ||||
|       const schema = { | ||||
|         value: new fields.NumberField({ ...requiredInteger, initial: 3, min: 0 }), | ||||
|         feature: new fields.StringField({ required: true, nullable: false, initial: "" }) | ||||
|       } | ||||
|       return new fields.SchemaField(schema, { label }) | ||||
|     } | ||||
|  | ||||
|     schema.characteristics = new fields.SchemaField( | ||||
|       Object.values(SYSTEM.CHARACTERISTICS).reduce((obj, characteristic) => { | ||||
|         obj[characteristic.id] = characteristicField(characteristic.label) | ||||
|         return obj | ||||
|       }, {}), | ||||
|     ) | ||||
|  | ||||
|     schema.wp = new fields.SchemaField({ | ||||
|       value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), | ||||
|       max: new fields.NumberField({ ...requiredInteger, initial: 3, min: 0 }), | ||||
|       exhausted: new fields.BooleanField({ required: true, initial: false }) | ||||
|     }) | ||||
|  | ||||
|     schema.hp = new fields.SchemaField({ | ||||
|       value: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }), | ||||
|       max: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }) | ||||
|     }) | ||||
|     schema.movement = new fields.StringField({ required: true, initial: "" }) | ||||
|     schema.sanLoss = new fields.StringField({ required: true, initial: "1/1D6" }) | ||||
|  | ||||
|     schema.armor = new fields.StringField({ required: true, initial: "" }) | ||||
|     schema.size = new fields.StringField({ required: true, initial: "medium", choices: SYSTEM.CREATURE_SIZE }) | ||||
|     schema.damageBonus = new fields.NumberField({ ...requiredInteger, 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.Creature"] | ||||
|  | ||||
|     /** */ | ||||
|     /** | ||||
|      * Rolls a dice for a character. | ||||
|      * @param {("save"|"resource|damage")} rollType The type of the roll. | ||||
|      * @param {number} rollItem The target value for the roll. Which caracteristic or resource. If the roll is a damage roll, this is the id of the item. | ||||
|      * @returns {Promise<null>} - A promise that resolves to null if the roll is cancelled. | ||||
|      */ | ||||
|     async roll(rollType, rollItem) { | ||||
|       let opponentTarget | ||||
|       const hasTarget = opponentTarget !== undefined | ||||
|    | ||||
|       let roll = await CthulhuEternalRoll.prompt({ | ||||
|         rollType, | ||||
|         rollItem, | ||||
|         isLowWP: false, | ||||
|         isZeroWP: false, | ||||
|         isExhausted: false, | ||||
|         actorId: this.parent.id, | ||||
|         actorName: this.parent.name, | ||||
|         actorImage: this.parent.img, | ||||
|         hasTarget, | ||||
|         target: opponentTarget | ||||
|       }) | ||||
|       if (!roll) return null | ||||
|    | ||||
|       await roll.toMessage({}, { rollMode: roll.options.rollMode }) | ||||
|     } | ||||
|    | ||||
| } | ||||
							
								
								
									
										24
									
								
								module/models/ritual.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								module/models/ritual.mjs
									
									
									
									
									
										Normal 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"] | ||||
|  | ||||
| } | ||||
							
								
								
									
										64
									
								
								module/models/tome.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								module/models/tome.mjs
									
									
									
									
									
										Normal 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"]; | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { SYSTEM } from "../config/system.mjs" | ||||
|  | ||||
| export default class LethalFantasySkill extends foundry.abstract.TypeDataModel { | ||||
| export default class CthulhuEternalWeapon extends foundry.abstract.TypeDataModel { | ||||
|   static defineSchema() { | ||||
|     const fields = foundry.data.fields | ||||
|     const schema = {} | ||||
| @@ -12,6 +12,9 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel { | ||||
|     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.hasDirectSkill = new fields.BooleanField({ required: true, initial: false }) | ||||
|     schema.directSkillValue = new fields.NumberField({ required: true, initial: 0, min: 0, max:99 }) | ||||
|      | ||||
|     schema.damage = new fields.StringField({required: true, initial: "1d6"})   | ||||
|     schema.baseRange = new fields.StringField({required: true, initial: ""}) | ||||
|     schema.rangeUnit = new fields.StringField({ required: true, initial: "yard", choices: SYSTEM.WEAPON_RANGE_UNIT }) | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
|  | ||||
| import CthulhuEternalRoll from "./documents/roll.mjs" | ||||
| import { SystemManager } from './applications/hud/system-manager.js' | ||||
| import { SYSTEM } from "./config/system.mjs" | ||||
|  | ||||
| export default class CthulhuEternalUtils { | ||||
|  | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								packs-system/rituals/000005.ldb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packs-system/rituals/000005.ldb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1
									
								
								packs-system/rituals/CURRENT
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								packs-system/rituals/CURRENT
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| MANIFEST-000010 | ||||
							
								
								
									
										0
									
								
								packs-system/rituals/LOCK
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								packs-system/rituals/LOCK
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										8
									
								
								packs-system/rituals/LOG
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								packs-system/rituals/LOG
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| 2025/04/25-00:23:55.566074 7fd0855fa6c0 Recovering log #8 | ||||
| 2025/04/25-00:23:55.627155 7fd0855fa6c0 Delete type=3 #6 | ||||
| 2025/04/25-00:23:55.627214 7fd0855fa6c0 Delete type=0 #8 | ||||
| 2025/04/25-00:24:39.296644 7fd07effd6c0 Level-0 table #13: started | ||||
| 2025/04/25-00:24:39.296707 7fd07effd6c0 Level-0 table #13: 0 bytes OK | ||||
| 2025/04/25-00:24:39.302890 7fd07effd6c0 Delete type=0 #11 | ||||
| 2025/04/25-00:24:39.309638 7fd07effd6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end) | ||||
| 2025/04/25-00:24:39.309671 7fd07effd6c0 Manual compaction at level-1 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end) | ||||
							
								
								
									
										8
									
								
								packs-system/rituals/LOG.old
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								packs-system/rituals/LOG.old
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| 2025/04/24-23:56:15.236151 7fd0855fa6c0 Recovering log #4 | ||||
| 2025/04/24-23:56:15.247158 7fd0855fa6c0 Delete type=0 #4 | ||||
| 2025/04/24-23:56:15.247228 7fd0855fa6c0 Delete type=3 #2 | ||||
| 2025/04/25-00:23:51.709456 7fd07effd6c0 Level-0 table #9: started | ||||
| 2025/04/25-00:23:51.709498 7fd07effd6c0 Level-0 table #9: 0 bytes OK | ||||
| 2025/04/25-00:23:51.747489 7fd07effd6c0 Delete type=0 #7 | ||||
| 2025/04/25-00:23:51.747677 7fd07effd6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end) | ||||
| 2025/04/25-00:23:51.809910 7fd07effd6c0 Manual compaction at level-1 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end) | ||||
							
								
								
									
										
											BIN
										
									
								
								packs-system/rituals/MANIFEST-000010
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packs-system/rituals/MANIFEST-000010
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								packs-system/skills/000165.ldb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packs-system/skills/000165.ldb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										0
									
								
								packs-system/skills/000176.log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								packs-system/skills/000176.log
									
									
									
									
									
										Normal file
									
								
							| @@ -1 +1 @@ | ||||
| MANIFEST-000112 | ||||
| MANIFEST-000174 | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| 2025/02/06-21:12:01.561879 7ffae7fff6c0 Recovering log #110 | ||||
| 2025/02/06-21:12:01.618398 7ffae7fff6c0 Delete type=3 #108 | ||||
| 2025/02/06-21:12:01.618459 7ffae7fff6c0 Delete type=0 #110 | ||||
| 2025/02/06-22:37:39.915470 7ffae6bff6c0 Level-0 table #115: started | ||||
| 2025/02/06-22:37:39.915518 7ffae6bff6c0 Level-0 table #115: 0 bytes OK | ||||
| 2025/02/06-22:37:39.952549 7ffae6bff6c0 Delete type=0 #113 | ||||
| 2025/02/06-22:37:39.952742 7ffae6bff6c0 Manual compaction at level-0 from '!folders!DD8331Hda4rhvEf9' @ 72057594037927935 : 1 .. '!items!zplzTG30QXHURusr' @ 0 : 0; will stop at (end) | ||||
| 2025/02/06-22:37:39.952774 7ffae6bff6c0 Manual compaction at level-1 from '!folders!DD8331Hda4rhvEf9' @ 72057594037927935 : 1 .. '!items!zplzTG30QXHURusr' @ 0 : 0; will stop at (end) | ||||
| 2025/04/25-00:23:55.465639 7fd07f7fe6c0 Recovering log #172 | ||||
| 2025/04/25-00:23:55.561118 7fd07f7fe6c0 Delete type=3 #170 | ||||
| 2025/04/25-00:23:55.561198 7fd07f7fe6c0 Delete type=0 #172 | ||||
| 2025/04/25-00:24:39.302991 7fd07effd6c0 Level-0 table #177: started | ||||
| 2025/04/25-00:24:39.303023 7fd07effd6c0 Level-0 table #177: 0 bytes OK | ||||
| 2025/04/25-00:24:39.309509 7fd07effd6c0 Delete type=0 #175 | ||||
| 2025/04/25-00:24:39.309652 7fd07effd6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end) | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| 2025/02/06-21:10:37.808165 7ffae77fe6c0 Recovering log #106 | ||||
| 2025/02/06-21:10:37.818622 7ffae77fe6c0 Delete type=3 #104 | ||||
| 2025/02/06-21:10:37.818703 7ffae77fe6c0 Delete type=0 #106 | ||||
| 2025/02/06-21:11:20.037362 7ffae6bff6c0 Level-0 table #111: started | ||||
| 2025/02/06-21:11:20.037398 7ffae6bff6c0 Level-0 table #111: 0 bytes OK | ||||
| 2025/02/06-21:11:20.043269 7ffae6bff6c0 Delete type=0 #109 | ||||
| 2025/02/06-21:11:20.043465 7ffae6bff6c0 Manual compaction at level-0 from '!folders!DD8331Hda4rhvEf9' @ 72057594037927935 : 1 .. '!items!zplzTG30QXHURusr' @ 0 : 0; will stop at (end) | ||||
| 2025/02/06-21:11:20.043496 7ffae6bff6c0 Manual compaction at level-1 from '!folders!DD8331Hda4rhvEf9' @ 72057594037927935 : 1 .. '!items!zplzTG30QXHURusr' @ 0 : 0; will stop at (end) | ||||
| 2025/04/24-23:56:15.221751 7fd07f7fe6c0 Recovering log #168 | ||||
| 2025/04/24-23:56:15.231420 7fd07f7fe6c0 Delete type=0 #168 | ||||
| 2025/04/24-23:56:15.231515 7fd07f7fe6c0 Delete type=3 #166 | ||||
| 2025/04/25-00:23:51.673765 7fd07effd6c0 Level-0 table #173: started | ||||
| 2025/04/25-00:23:51.673830 7fd07effd6c0 Level-0 table #173: 0 bytes OK | ||||
| 2025/04/25-00:23:51.709271 7fd07effd6c0 Delete type=0 #171 | ||||
| 2025/04/25-00:23:51.747663 7fd07effd6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end) | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								packs-system/skills/MANIFEST-000174
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packs-system/skills/MANIFEST-000174
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										0
									
								
								packs-system/skills/lost/000159.log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								packs-system/skills/lost/000159.log
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										644
									
								
								styles/creature.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										644
									
								
								styles/creature.less
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,644 @@ | ||||
| .creature-content { | ||||
|   .sheet-common(); | ||||
|   .creature-sheet-common(); | ||||
|   overflow: scroll; | ||||
| } | ||||
|  | ||||
| .sheet-tabs { | ||||
|   background-color: var(--color-light-1); | ||||
| } | ||||
|  | ||||
| .creature-main { | ||||
|   background-color: var(--color-light-1); | ||||
|   display: flex; | ||||
|  | ||||
|   .creature-pc { | ||||
|     display: flex; | ||||
|     gap: 4px; | ||||
|     flex: 1; | ||||
|  | ||||
|     .creature-left { | ||||
|       min-width: 180px; | ||||
|       display: flex; | ||||
|       flex-direction: column; | ||||
|  | ||||
|       .creature-left-image { | ||||
|         display: flex; | ||||
|         justify-content: center; | ||||
|         align-items: center; | ||||
|         padding-bottom: 8px; | ||||
|         .creature-img { | ||||
|           height: 140px; | ||||
|           width: auto; | ||||
|           border: none; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .creature-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; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .creature-dv, | ||||
|       .creature-dmax { | ||||
|         .form-fields { | ||||
|           flex: none; | ||||
|         } | ||||
|       } | ||||
|       .creature-dmax-edit { | ||||
|         input { | ||||
|           display: flex; | ||||
|           width: 60px; | ||||
|           font-size: calc(var(--font-size-standard) * 1.4); | ||||
|           align-items: center; | ||||
|           justify-content: center; | ||||
|           padding: 0 5px 0 5px; | ||||
|           text-align: center; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .creature-right { | ||||
|       display: flex; | ||||
|       flex-direction: column; | ||||
|       gap: 5px; | ||||
|  | ||||
|       .creature-name { | ||||
|         display: flex; | ||||
|         input { | ||||
|           font-family: var(--font-title); | ||||
|           font-size: var(--font-size-title); | ||||
|           width: 400px; | ||||
|         } | ||||
|       } | ||||
|       .san { | ||||
|         align-content: flex-start; | ||||
|         input { | ||||
|           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 { | ||||
|           min-width: 1rem; | ||||
|           max-width: 1rem; | ||||
|         } | ||||
|         .label-short-field { | ||||
|           font-size: 0.9rem; | ||||
|           max-width: 3rem; | ||||
|           min-width: 3rem; | ||||
|           flex-grow: 1; | ||||
|         } | ||||
|         .label-recovery { | ||||
|           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 { | ||||
|           margin-left: 4px; | ||||
|         } | ||||
|         .d100 { | ||||
|           flex: 0; | ||||
|         } | ||||
|       } | ||||
|       .willpower { | ||||
|         input { | ||||
|           min-width: 2.4rem; | ||||
|           max-width: 2.4rem; | ||||
|         } | ||||
|         input[type="checkbox"] { | ||||
|           min-width: 1rem; | ||||
|           max-width: 1rem; | ||||
|         } | ||||
|         .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; | ||||
|           max-width: 1rem; | ||||
|         } | ||||
|       } | ||||
|       label { | ||||
|         min-width: 120px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .creature-pc-play { | ||||
|     min-width: 500px; | ||||
|   } | ||||
|  | ||||
|   .creature-pc-edit { | ||||
|     min-width: 650px; | ||||
|   } | ||||
|  | ||||
|   .creature-characteristics { | ||||
|     background-color: var(--color-light-1); | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     gap: 5px; | ||||
|     flex: 1; | ||||
|  | ||||
|     .creature-characteristic { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       .rollable:hover, | ||||
|       .rollable:focus { | ||||
|         text-shadow: 0 0 8px var(--color-shadow-primary); | ||||
|         cursor: pointer; | ||||
|       } | ||||
|       .rollable { | ||||
|         min-width: 3rem; | ||||
|         max-width: 3rem; | ||||
|       } | ||||
|       .char-text { | ||||
|         margin-left: 0.5rem; | ||||
|       } | ||||
|       .d100 { | ||||
|         flex: 0; | ||||
|         max-width: 0.6rem; | ||||
|       } | ||||
|       .form-group { | ||||
|         flex: 0; | ||||
|         padding-left: 5px; | ||||
|         .form-fields { | ||||
|           font-size: 1.1rem; | ||||
|           flex: none; | ||||
|           width: 40px; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .creature-characteristic-play { | ||||
|     min-width: 225px; | ||||
|   } | ||||
|  | ||||
|   .creature-characteristic-edit { | ||||
|     min-width: 400px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .creature-biography { | ||||
|   background-color: var(--color-light-1); | ||||
|   prose-mirror.inactive { | ||||
|     min-height: 40px; | ||||
|   } | ||||
|   prose-mirror.active { | ||||
|     min-height: 150px; | ||||
|   } | ||||
|   .field-label { | ||||
|     margin-left: 8px; | ||||
|   } | ||||
|  | ||||
|   .adapted { | ||||
|     display: grid; | ||||
|     grid-template-columns: repeat(2, 1fr); | ||||
|     gap: 8px; | ||||
|     label { | ||||
|       min-width: 20rem; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .resources { | ||||
|     display: grid; | ||||
|     grid-template-columns: repeat(3, 1fr); | ||||
|     gap: 8px; | ||||
|     label { | ||||
|       min-width: 8rem; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .features, | ||||
|   .biodata { | ||||
|     display: grid; | ||||
|     grid-template-columns: repeat(2, 1fr); | ||||
|     gap: 8px; | ||||
|     label { | ||||
|       min-width: 3rem; | ||||
|     } | ||||
|     .feature { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       gap: 4px; | ||||
|       min-width: 18rem; | ||||
|       max-width: 18rem; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .tab.creature-skills { | ||||
|   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; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .armors { | ||||
|     display: grid; | ||||
|     grid-template-columns: repeat(3, 1fr); | ||||
|     gap: 4px; | ||||
|     .armor { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       gap: 4px; | ||||
|       min-width: 13rem; | ||||
|       max-width: 13rem; | ||||
|       .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; | ||||
|       } | ||||
|       .protection { | ||||
|         min-width: 5rem; | ||||
|         max-width: 5rem; | ||||
|       } | ||||
|       .name { | ||||
|         min-width: 8rem; | ||||
|         max-width: 8rem; | ||||
|       } | ||||
|       .item-img { | ||||
|         width: 24px; | ||||
|         height: 24px; | ||||
|         margin: 4px 0 0 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .weapons { | ||||
|     display: grid; | ||||
|     grid-template-columns: repeat(2, 1fr); | ||||
|     gap: 4px; | ||||
|     .weapon { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       gap: 4px; | ||||
|       min-width: 13rem; | ||||
|       max-width: 13rem; | ||||
|       .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; | ||||
|       } | ||||
|       .damage { | ||||
|         min-width: 6rem; | ||||
|         max-width: 6rem; | ||||
|       } | ||||
|       .name { | ||||
|         min-width: 10rem; | ||||
|         max-width: 10rem; | ||||
|       } | ||||
|       .item-img { | ||||
|         width: 24px; | ||||
|         height: 24px; | ||||
|         margin: 4px 0 0 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .skills { | ||||
|     display: grid; | ||||
|     grid-template-columns: repeat(3, 1fr); | ||||
|     gap: 4px; | ||||
|     .skill { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       gap: 4px; | ||||
|       margin-left: 4px; | ||||
|       min-width: 12.3rem; | ||||
|       max-width: 12.3rem; | ||||
|       .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; | ||||
|       } | ||||
|       .score { | ||||
|         min-width: 1.2rem; | ||||
|         max-width: 1.2rem; | ||||
|       } | ||||
|       .name { | ||||
|         min-width: 10rem; | ||||
|         max-width: 10rem; | ||||
|       } | ||||
|       .item-img { | ||||
|         width: 24px; | ||||
|         height: 24px; | ||||
|         margin: 4px 0 0 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .tab.creature-status { | ||||
|   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; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .bonds { | ||||
|     display: grid; | ||||
|     grid-template-columns: repeat(2, 1fr); | ||||
|     gap: 4px; | ||||
|     .bond { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       gap: 4px; | ||||
|       min-width: 18rem; | ||||
|       max-width: 18rem; | ||||
|       .controls { | ||||
|         font-size: 0.7rem; | ||||
|         min-width: 1.8rem; | ||||
|         max-width: 1.8rem; | ||||
|       } | ||||
|       .name { | ||||
|         min-width: 12rem; | ||||
|         max-width: 12rem; | ||||
|       } | ||||
|       .type { | ||||
|         min-width: 6rem; | ||||
|         max-width: 6rem; | ||||
|       } | ||||
|       .level { | ||||
|         min-width: 2rem; | ||||
|         max-width: 2rem; | ||||
|       } | ||||
|       .item-img { | ||||
|         width: 24px; | ||||
|         height: 24px; | ||||
|         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 { | ||||
|     display: grid; | ||||
|     grid-template-columns: repeat(2, 1fr); | ||||
|     gap: 4px; | ||||
|     .mentaldisorder { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       gap: 4px; | ||||
|       min-width: 18rem; | ||||
|       max-width: 18rem; | ||||
|       .controls { | ||||
|         font-size: 0.7rem; | ||||
|         min-width: 1.8rem; | ||||
|         max-width: 1.8rem; | ||||
|       } | ||||
|       .name { | ||||
|         min-width: 14rem; | ||||
|         max-width: 14rem; | ||||
|       } | ||||
|       .cured { | ||||
|         min-width: 5rem; | ||||
|         max-width: 5rem; | ||||
|       } | ||||
|       .item-img { | ||||
|         width: 24px; | ||||
|         height: 24px; | ||||
|         margin: 4px 0 0 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .injuries { | ||||
|     display: grid; | ||||
|     grid-template-columns: repeat(2, 1fr); | ||||
|     gap: 4px; | ||||
|     .injury { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       gap: 4px; | ||||
|       min-width: 16rem; | ||||
|       max-width: 16rem; | ||||
|       .controls { | ||||
|         font-size: 0.7rem; | ||||
|         min-width: 1.8rem; | ||||
|         max-width: 1.8rem; | ||||
|       } | ||||
|       .name { | ||||
|         min-width: 14rem; | ||||
|         max-width: 14rem; | ||||
|       } | ||||
|       .item-img { | ||||
|         width: 24px; | ||||
|         height: 24px; | ||||
|         margin: 4px 0 0 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .tab.creature-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; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .gears { | ||||
|     display: grid; | ||||
|     grid-template-columns: repeat(3, 1fr); | ||||
|     gap: 4px; | ||||
|     .gear { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       gap: 4px; | ||||
|       min-width: 13rem; | ||||
|       max-width: 13rem; | ||||
|       .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: 10rem; | ||||
|         max-width: 10rem; | ||||
|       } | ||||
|       .item-img { | ||||
|         width: 24px; | ||||
|         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; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   prose-mirror.inactive { | ||||
|     min-height: 40px; | ||||
|   } | ||||
|   prose-mirror.active { | ||||
|     min-height: 150px; | ||||
|   } | ||||
| } | ||||
| @@ -5,6 +5,7 @@ | ||||
|   @import "mixins.less"; | ||||
|   @import "protagonist.less"; | ||||
|   @import "vehicle.less"; | ||||
|   @import "creature.less"; | ||||
|   @import "skill.less"; | ||||
|   @import "injury.less"; | ||||
|   @import "weapon.less"; | ||||
| @@ -16,6 +17,8 @@ | ||||
|   @import "gear.less"; | ||||
|   @import "arcane.less"; | ||||
|   @import "archetype.less"; | ||||
|   @import "ritual.less"; | ||||
|   @import "tome.less"; | ||||
| } | ||||
|  | ||||
| @import "roll.less"; | ||||
| @@ -68,6 +68,13 @@ | ||||
|   } | ||||
| } | ||||
|  | ||||
| .creature-sheet-common { | ||||
|   label { | ||||
|     font-family: var(--font-secondary); | ||||
|     font-size: calc(var(--font-size-standard) * 1.0); | ||||
|   } | ||||
| } | ||||
|  | ||||
| .item-sheet-common { | ||||
|   .form-fields { | ||||
|     padding-top: 4px; | ||||
|   | ||||
| @@ -294,20 +294,25 @@ | ||||
|       align-items: center; | ||||
|       gap: 4px; | ||||
|       margin-left: 4px; | ||||
|       min-width: 12rem; | ||||
|       max-width: 12rem; | ||||
|       min-width: 12.3rem; | ||||
|       max-width: 12.3rem; | ||||
|       .rollable:hover, | ||||
|       .rollable:focus { | ||||
|         text-shadow: 0 0 8px var(--color-shadow-primary); | ||||
|         cursor: pointer; | ||||
|       } | ||||
|       .controls { | ||||
|         min-width: 2rem; | ||||
|         max-width: 2rem; | ||||
|         font-size: 0.7rem; | ||||
|         min-width: 1.8rem; | ||||
|         max-width: 1.8rem; | ||||
|       } | ||||
|       .score { | ||||
|         min-width: 1.2rem; | ||||
|         max-width: 1.2rem; | ||||
|       } | ||||
|       .name { | ||||
|         min-width: 11rem; | ||||
|         max-width: 11rem; | ||||
|         min-width: 10rem; | ||||
|         max-width: 10rem; | ||||
|       } | ||||
|       .item-img { | ||||
|         width: 24px; | ||||
| @@ -340,8 +345,9 @@ | ||||
|       min-width: 18rem; | ||||
|       max-width: 18rem; | ||||
|       .controls { | ||||
|         min-width: 2rem; | ||||
|         max-width: 2rem; | ||||
|         font-size: 0.7rem; | ||||
|         min-width: 1.8rem; | ||||
|         max-width: 1.8rem; | ||||
|       } | ||||
|       .name { | ||||
|         min-width: 12rem; | ||||
| @@ -374,8 +380,9 @@ | ||||
|       min-width: 14rem; | ||||
|       max-width: 14rem; | ||||
|       .controls { | ||||
|         min-width: 2rem; | ||||
|         max-width: 2rem; | ||||
|         font-size: 0.7rem; | ||||
|         min-width: 1.8rem; | ||||
|         max-width: 1.8rem; | ||||
|       } | ||||
|       .name { | ||||
|         min-width: 12rem; | ||||
| @@ -400,8 +407,9 @@ | ||||
|       min-width: 18rem; | ||||
|       max-width: 18rem; | ||||
|       .controls { | ||||
|         min-width: 2rem; | ||||
|         max-width: 2rem; | ||||
|         font-size: 0.7rem; | ||||
|         min-width: 1.8rem; | ||||
|         max-width: 1.8rem; | ||||
|       } | ||||
|       .name { | ||||
|         min-width: 14rem; | ||||
| @@ -430,8 +438,9 @@ | ||||
|       min-width: 16rem; | ||||
|       max-width: 16rem; | ||||
|       .controls { | ||||
|         min-width: 2rem; | ||||
|         max-width: 2rem; | ||||
|         font-size: 0.7rem; | ||||
|         min-width: 1.8rem; | ||||
|         max-width: 1.8rem; | ||||
|       } | ||||
|       .name { | ||||
|         min-width: 14rem; | ||||
| @@ -472,8 +481,9 @@ | ||||
|         cursor: pointer; | ||||
|       } | ||||
|       .controls { | ||||
|         min-width: 2rem; | ||||
|         max-width: 2rem; | ||||
|         font-size: 0.7rem; | ||||
|         min-width: 1.8rem; | ||||
|         max-width: 1.8rem; | ||||
|       } | ||||
|       .damage { | ||||
|         min-width: 6rem; | ||||
| @@ -499,15 +509,16 @@ | ||||
|       align-items: center; | ||||
|       gap: 4px; | ||||
|       min-width: 13rem; | ||||
|       max-width: 13srem; | ||||
|       max-width: 13rem; | ||||
|       .rollable:hover, | ||||
|       .rollable:focus { | ||||
|         text-shadow: 0 0 8px var(--color-shadow-primary); | ||||
|         cursor: pointer; | ||||
|       } | ||||
|       .controls { | ||||
|         min-width: 2rem; | ||||
|         max-width: 2rem; | ||||
|         font-size: 0.7rem; | ||||
|         min-width: 1.8rem; | ||||
|         max-width: 1.8rem; | ||||
|       } | ||||
|       .protection { | ||||
|         min-width: 5rem; | ||||
| @@ -524,6 +535,7 @@ | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .gears { | ||||
|     display: grid; | ||||
|     grid-template-columns: repeat(3, 1fr); | ||||
| @@ -533,23 +545,84 @@ | ||||
|       align-items: center; | ||||
|       gap: 4px; | ||||
|       min-width: 13rem; | ||||
|       max-width: 13srem; | ||||
|       max-width: 13rem; | ||||
|       .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; | ||||
|         font-size: 0.7rem; | ||||
|         min-width: 1.8rem; | ||||
|         max-width: 1.8rem; | ||||
|       } | ||||
|       .name { | ||||
|         min-width: 8rem; | ||||
|         max-width: 8rem; | ||||
|         min-width: 10rem; | ||||
|         max-width: 10rem; | ||||
|       } | ||||
|       .item-img { | ||||
|         width: 24px; | ||||
|         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; | ||||
|   | ||||
							
								
								
									
										30
									
								
								styles/ritual.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								styles/ritual.less
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| .ritual-content { | ||||
|   .sheet-common(); | ||||
|   .item-sheet-common(); | ||||
|  | ||||
|   fieldset { | ||||
|     margin-top: 8px; | ||||
|     background-color: var(--color-light-1); | ||||
|     .editor-content { | ||||
|       max-height: 400px; | ||||
|       overflow-y: auto; | ||||
|     } | ||||
|     .editor-container { | ||||
|       max-height: 400px; | ||||
|       overflow-y: auto; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .header { | ||||
|     background-color: var(--color-light-1); | ||||
|     display: flex; | ||||
|     img { | ||||
|       width: 50px; | ||||
|       height: 50px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   label { | ||||
|     flex: 10%; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										22
									
								
								styles/tome.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								styles/tome.less
									
									
									
									
									
										Normal 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%; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										17
									
								
								system.json
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								system.json
									
									
									
									
									
								
							| @@ -6,7 +6,7 @@ | ||||
|   "download": "#{DOWNLOAD}#", | ||||
|   "url": "https://www.uberwald.me/gitea/public/fvtt-cthulhu-eternal", | ||||
|   "license": "LICENSE", | ||||
|   "version": "12.0.5", | ||||
|   "version": "12.0.6", | ||||
|   "authors": [ | ||||
|     { | ||||
|       "name": "Uberwald", | ||||
| @@ -35,7 +35,8 @@ | ||||
|   "documentTypes": { | ||||
|     "Actor": { | ||||
|       "protagonist": { "htmlFields": ["description", "notes"] }, | ||||
|       "vehicle": { "htmlFields": ["description", "notes"] } | ||||
|       "vehicle": { "htmlFields": ["description", "notes"] }, | ||||
|       "creature": { "htmlFields": ["description", "notes"] } | ||||
|     }, | ||||
|     "Item": { | ||||
|       "skill": { "htmlFields": ["description"] }, | ||||
| @@ -47,7 +48,9 @@ | ||||
|       "motivation": { "htmlFields": ["description"] }, | ||||
|       "arcane": { "htmlFields": ["description"] }, | ||||
|       "gear": { "htmlFields": ["description"] }, | ||||
|       "archetype": { "htmlFields": ["description"] } | ||||
|       "archetype": { "htmlFields": ["description"] }, | ||||
|       "ritual": { "htmlFields": ["description"] }, | ||||
|       "tome": { "htmlFields": ["description"] } | ||||
|     } | ||||
|   }, | ||||
|   "packs": [ | ||||
| @@ -58,6 +61,14 @@ | ||||
|       "system": "fvtt-cthulhu-eternal", | ||||
|       "path": "packs-system/skills", | ||||
|       "type": "Item" | ||||
|     }, | ||||
|     { | ||||
|       "name": "rituals", | ||||
|       "banner": "", | ||||
|       "label": "Rituals", | ||||
|       "system": "fvtt-cthulhu-eternal", | ||||
|       "path": "packs-system/rituals", | ||||
|       "type": "Item" | ||||
|     } | ||||
|   ], | ||||
|   "grid": { | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
|  | ||||
|   <fieldset> | ||||
|     <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> | ||||
|  | ||||
| </section> | ||||
| @@ -10,7 +10,7 @@ | ||||
|  | ||||
|   <fieldset> | ||||
|     <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> | ||||
|  | ||||
| </section>h | ||||
|   | ||||
| @@ -15,7 +15,7 @@ | ||||
|     <legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend> | ||||
|     {{formInput | ||||
|     systemFields.description | ||||
|     enriched=description | ||||
|     enriched=enrichedDescription | ||||
|     value=system.description | ||||
|     name="system.description" | ||||
|     toggled="false" | ||||
|   | ||||
							
								
								
									
										12
									
								
								templates/creature-biography.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								templates/creature-biography.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| <section class="tab creature-{{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> | ||||
							
								
								
									
										95
									
								
								templates/creature-main.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								templates/creature-main.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| <section class="creature-main creature-main-{{ifThen isPlayMode 'play' 'edit'}}"> | ||||
|   <fieldset> | ||||
|     <legend>{{localize "CTHULHUETERNAL.Label.creature"}}</legend> | ||||
|     <div class="creature-pc creature-pc-{{ifThen isPlayMode 'play' 'edit'}}"> | ||||
|       <div class="creature-left"> | ||||
|         <div class="creature-left-image"> | ||||
|           <img class="creature-img" src="{{actor.img}}" data-edit="img" data-action="editImage" | ||||
|             data-tooltip="{{actor.name}}" /> | ||||
|         </div> | ||||
|  | ||||
|       </div> | ||||
|       <div class="creature-right"> | ||||
|         <div class="creature-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="creature-hp">  | ||||
|           <legend>{{localize "CTHULHUETERNAL.Label.HP"}}</legend> | ||||
|           <div class="flexrow"> | ||||
|             {{formField systemFields.hp.fields.value value=system.hp.value}} | ||||
|             <span class="hp-separator">/</span> | ||||
|             {{formField systemFields.hp.fields.max value=system.hp.max }} | ||||
|           </div> | ||||
|           <div class="flexrow "> | ||||
|             {{formField systemFields.damageBonus value=system.damageBonus classes="damage-bonus"}} | ||||
|           </div> | ||||
|         </fieldset> | ||||
|  | ||||
|         <fieldset class="willpower"> | ||||
|           <legend>{{localize "CTHULHUETERNAL.Label.willpower"}}</legend> | ||||
|           <div class="flexrow"> | ||||
|             <label class="label-field">{{localize "CTHULHUETERNAL.Label.current"}}</label> | ||||
|             {{formInput systemFields.wp.fields.value value=system.wp.value}} | ||||
|             <label class="label-field">{{localize "CTHULHUETERNAL.Label.max"}}</label> | ||||
|             {{formInput systemFields.wp.fields.max value=system.wp.max rootId=partId }} | ||||
|             <label class="label-field">{{localize "CTHULHUETERNAL.Label.exhausted"}}</label> | ||||
|             {{formInput systemFields.wp.fields.exhausted value=system.wp.exhausted classes="checkbox"}} | ||||
|           </div> | ||||
|         </fieldset> | ||||
|  | ||||
|       </div> | ||||
|  | ||||
|        | ||||
|     </div> | ||||
|   </fieldset> | ||||
|  | ||||
|   <fieldset class="creature-characteristics creature-characteristics-{{ifThen isPlayMode 'play' 'edit'}}"> | ||||
|     <legend>{{localize "CTHULHUETERNAL.Label.characteristics"}}</legend> | ||||
|     <div class="creature-characteristic" > | ||||
|       <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> | ||||
|       {{formField systemFields.characteristics.fields.str.fields.value value=system.characteristics.str.value | ||||
|       rootId=partId disabled=isPlayMode }} | ||||
|       <label class="char-text">{{mul system.characteristics.str.value 5}}</label> | ||||
|     </div> | ||||
|     <div class="creature-characteristic"> | ||||
|       <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> | ||||
|       {{formField systemFields.characteristics.fields.dex.fields.value value=system.characteristics.dex.value | ||||
|       rootId=partId disabled=isPlayMode }} | ||||
|       <label class="char-text">{{mul system.characteristics.dex.value 5}}</label> | ||||
|     </div> | ||||
|     <div class="creature-characteristic" > | ||||
|       <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> | ||||
|       {{formField systemFields.characteristics.fields.con.fields.value value=system.characteristics.con.value | ||||
|       rootId=partId disabled=isPlayMode }} | ||||
|        <label class="char-text">{{mul system.characteristics.con.value 5}}</label> | ||||
|     </div> | ||||
|     <div class="creature-characteristic" > | ||||
|       <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> | ||||
|       {{formField systemFields.characteristics.fields.int.fields.value value=system.characteristics.int.value | ||||
|       rootId=partId disabled=isPlayMode }} | ||||
|        <label class="char-text">{{mul system.characteristics.int.value 5}}</label> | ||||
|     </div> | ||||
|     <div class="creature-characteristic" > | ||||
|       <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> | ||||
|       {{formField systemFields.characteristics.fields.pow.fields.value value=system.characteristics.pow.value | ||||
|       rootId=partId disabled=isPlayMode }} | ||||
|        <label class="char-text">{{mul system.characteristics.pow.value 5}}</label> | ||||
|     </div> | ||||
|  | ||||
|   </fieldset> | ||||
|  | ||||
| </section> | ||||
							
								
								
									
										57
									
								
								templates/creature-skills.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								templates/creature-skills.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| <section class="tab creature-{{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}}" /> | ||||
|         <img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" /> | ||||
|         <div class="name rollable" data-roll-type="weapon" data-tooltip="{{{item.system.description}}}"> | ||||
|           {{item.name}} | ||||
|         </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}} | ||||
|     </div> | ||||
|   </fieldset> | ||||
|  | ||||
|   <fieldset> | ||||
|     <legend data-tooltip="{{localize "CTHULHUETERNAL.Tooltip.skills"}}" data-tooltip-direction="UP">{{localize "CTHULHUETERNAL.Label.skills"}}</legend> | ||||
|     <div class="skills"> | ||||
|         {{#each skills as |item|}} | ||||
|           <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 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> | ||||
|             <div class="score" > | ||||
|               {{item.system.skillTotal}} | ||||
|             </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> | ||||
| @@ -12,7 +12,7 @@ | ||||
|  | ||||
|   <fieldset> | ||||
|     <legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend> | ||||
|     {{formInput systemFields.description enriched=description value=system.description name="system.description" | ||||
|     {{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" | ||||
|     toggled=true}} | ||||
|   </fieldset> | ||||
|  | ||||
|   | ||||
| @@ -12,7 +12,7 @@ | ||||
|     <legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend> | ||||
|     {{formInput | ||||
|       systemFields.description | ||||
|       enriched=description | ||||
|       enriched=enrichedDescription | ||||
|       value=system.description | ||||
|       name="system.description" | ||||
|       toggled="false" | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
|  | ||||
|   <fieldset> | ||||
|     <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> | ||||
|  | ||||
| </section> | ||||
| @@ -81,4 +81,55 @@ | ||||
|     </div> | ||||
|   </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> | ||||
							
								
								
									
										24
									
								
								templates/ritual.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								templates/ritual.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| <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=enrichedDescription value=system.description name="system.description" toggled=true}} | ||||
|  | ||||
|   </fieldset> | ||||
|  | ||||
| </section> | ||||
							
								
								
									
										42
									
								
								templates/tome.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								templates/tome.hbs
									
									
									
									
									
										Normal 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=enrichedDescription value=system.description name="system.description" toggled=true}} | ||||
|   </fieldset> | ||||
|  | ||||
| </section> | ||||
| @@ -13,6 +13,11 @@ | ||||
|  | ||||
|     {{formField systemFields.state value=system.state localize=true}} | ||||
|  | ||||
|     {{formField systemFields.hasDirectSkill value=system.hasDirectSkill }} | ||||
|     {{#if system.hasDirectSkill}} | ||||
|       {{formField systemFields.directSkillValue value=system.directSkillValue }} | ||||
|     {{/if}} | ||||
|  | ||||
|     {{formField systemFields.damage value=system.damage}} | ||||
|     {{formField systemFields.baseRange value=system.baseRange}} | ||||
|     {{formField systemFields.rangeUnit value=system.rangeUnit localize=true}} | ||||
| @@ -28,7 +33,7 @@ | ||||
|     <legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend> | ||||
|     {{formInput | ||||
|     systemFields.description | ||||
|     enriched=description | ||||
|     enriched=enrichedDescription | ||||
|     value=system.description | ||||
|     name="system.description" | ||||
|     toggled=true | ||||
|   | ||||
		Reference in New Issue
	
	Block a user