diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..dfa1d18 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,163 @@ +{ + "env": { + "browser": true, + "es2022": true, + "node": true, + "jquery": true + }, + "ignorePatterns": ["**/*compiled.mjs"], + "parserOptions": { + "requireConfigFile": false, + "sourceType": "module", + "ecmaVersion": 2022 + }, + "rules": { + "array-bracket-spacing": ["warn", "never"], + "array-callback-return": "warn", + "arrow-spacing": "warn", + "brace-style": ["error", "stroustrup"], + "comma-dangle": ["warn", { + "arrays": "always-multiline", + "objects": "always-multiline", + "imports": "always-multiline", + "exports": "always-multiline", + "functions": "never" + }], + "comma-style": "warn", + "computed-property-spacing": "warn", + "constructor-super": "error", + "default-param-last": "warn", + "disallowTabs": 0, + "dot-location": ["warn", "property"], + "eol-last": ["error", "always"], + "eqeqeq": ["warn", "smart"], + "func-call-spacing": "warn", + "func-names": ["warn", "never"], + "getter-return": "warn", + "linebreak-style": ["warn", "unix"], + "lines-between-class-members": "warn", + "new-parens": ["warn", "always"], + "no-alert": "warn", + "no-array-constructor": "warn", + "no-class-assign": "warn", + "no-compare-neg-zero": "warn", + "no-cond-assign": "warn", + "no-const-assign": "error", + "no-constant-condition": "warn", + "no-constructor-return": "warn", + "no-delete-var": "warn", + "no-dupe-args": "warn", + "no-dupe-class-members": "warn", + "no-dupe-keys": "warn", + "no-duplicate-case": "warn", + "no-duplicate-imports": ["warn", {"includeExports": true}], + "no-empty": ["warn", {"allowEmptyCatch": true}], + "no-empty-character-class": "warn", + "no-empty-pattern": "warn", + "no-func-assign": "warn", + "no-global-assign": "warn", + "no-implicit-coercion": ["warn", {"allow": ["!!"]}], + "no-implied-eval": "warn", + "no-import-assign": "warn", + "no-invalid-regexp": "warn", + "no-irregular-whitespace": "warn", + "no-iterator": "warn", + "no-lone-blocks": "warn", + "no-lonely-if": "warn", + "no-loop-func": "warn", + "no-misleading-character-class": "warn", + "no-mixed-operators": "warn", + "no-multi-str": "warn", + "no-multiple-empty-lines": "warn", + "no-new-func": "warn", + "no-new-object": "warn", + "no-new-symbol": "warn", + "no-new-wrappers": "warn", + "no-nonoctal-decimal-escape": "warn", + "no-obj-calls": "warn", + "no-octal": "warn", + "no-octal-escape": "warn", + "no-promise-executor-return": "warn", + "no-proto": "warn", + "no-regex-spaces": "warn", + "no-script-url": "warn", + "no-self-assign": "warn", + "no-self-compare": "warn", + "no-setter-return": "warn", + "no-sequences": "warn", + "no-template-curly-in-string": "warn", + "no-this-before-super": "error", + "no-unexpected-multiline": "warn", + "no-unmodified-loop-condition": "warn", + "no-unneeded-ternary": "off", + "no-unreachable": "warn", + "no-unreachable-loop": "warn", + "no-unsafe-negation": ["warn", {"enforceForOrderingRelations": true}], + "no-unsafe-optional-chaining": ["warn", {"disallowArithmeticOperators": true}], + "no-unused-expressions": "warn", + "no-useless-backreference": "warn", + "no-useless-call": "warn", + "no-useless-catch": "warn", + "no-useless-computed-key": ["warn", {"enforceForClassMembers": true}], + "no-useless-concat": "warn", + "no-useless-constructor": "warn", + "no-useless-rename": "warn", + "no-useless-return": "warn", + "no-var": "warn", + "no-void": "warn", + "no-whitespace-before-property": "warn", + "prefer-numeric-literals": "warn", + "prefer-object-spread": "warn", + "prefer-regex-literals": "warn", + "prefer-spread": "warn", + "rest-spread-spacing": ["warn", "never"], + "semi-spacing": "warn", + "semi-style": ["warn", "last"], + "space-unary-ops": ["warn", {"words": true, "nonwords": false}], + "switch-colon-spacing": "warn", + "symbol-description": "warn", + "template-curly-spacing": ["warn", "never"], + "unicode-bom": ["warn", "never"], + "use-isnan": ["warn", {"enforceForSwitchCase": true, "enforceForIndexOf": true}], + "valid-typeof": ["warn", {"requireStringLiterals": true}], + "wrap-iife": ["warn", "inside"], + "arrow-parens": ["warn", "as-needed", {"requireForBlockBody": false}], + "capitalized-comments": "off", + "comma-spacing": "warn", + "dot-notation": "warn", + "indent": ["error", "tab", {"SwitchCase": 1}], + "key-spacing": "warn", + "keyword-spacing": ["warn", {"overrides": {"catch": {"before": true, "after": false}}}], + "max-len": ["warn", { + "code": 100, + "ignoreTrailingComments": false, + "ignoreUrls": true, + "ignoreStrings": true, + "ignoreTemplateLiterals": true + }], + "no-extra-boolean-cast": ["warn", {"enforceForLogicalOperands": true}], + "no-extra-semi": "warn", + "no-multi-spaces": "off", + "no-tabs": "off", + "no-throw-literal": "error", + "no-trailing-spaces": "error", + "no-useless-escape": "warn", + "no-unused-vars": ["warn", {"args": "none"}], + "nonblock-statement-body-position": ["warn", "beside"], + "one-var": ["warn", "never"], + "operator-linebreak": ["warn", "before", { + "overrides": {"=": "after", "+=": "after", "-=": "after"} + }], + "prefer-template": "warn", + "quote-props": ["warn", "consistent-as-needed", {"keywords": false}], + "quotes": ["warn", "double", {"avoidEscape": true, "allowTemplateLiterals": false}], + "semi": "warn", + "space-before-blocks": ["warn", "always"], + "space-before-function-paren": ["warn", { + "anonymous": "never", + "named": "never", + "asyncArrow": "always" + }], + "spaced-comment": "warn" + } +} diff --git a/.github/workflows/npm-gulp.yml b/.github/workflows/npm-gulp.yml index ac73e46..aef65ff 100644 --- a/.github/workflows/npm-gulp.yml +++ b/.github/workflows/npm-gulp.yml @@ -1,10 +1,12 @@ -name: NodeJS with Gulp +name: Build CI on: push: branches: [ "develop" ] pull_request: branches: [ "develop" ] + workflow_dispatch: + branches: [ "develop" ] jobs: build: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6a5e760..6884702 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,9 +1,8 @@ name: Create Release on: - push: - tags: - - 'release-*' + workflow_dispatch: + branches: [main] jobs: build: @@ -16,46 +15,6 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up variables - id: get_vars - run: | - TAG=${GITHUB_REF/refs\/tags\//} - echo ::set-output name=TAG_NAME::$TAG - echo ::set-output name=ZIP_NAME::ac2d20.zip - echo ::set-output name=RELEASE_DOWNLOAD_URL::https://github.com/${{github.repository}}/releases/latest/download/ac2d20.zip - echo ::set-output name=RELEASE_INSTALL_URL::https://github.com/${{github.repository}}/releases/download/$TAG/system.json - JSON=$(cat ./system/system.json) - echo ::set-output name=SYSTEM_JSON::${JSON//'%'/'%25'} - - # Run some tests to make sure our `system.json` is correct - # Exit before setting up node if not - - name: Verify Naming - env: - TAG_NAME: ${{ steps.get_vars.outputs.TAG_NAME }} - RELEASE_DOWNLOAD: ${{steps.get_vars.outputs.RELEASE_DOWNLOAD_URL}} - # Extract version and download url from system.json - # https://docs.github.com/en/actions/learn-github-actions/expressions#fromjson - PACKAGE_VERSION: ${{fromJSON(steps.get_vars.outputs.SYSTEM_JSON).version}} - PACKAGE_DOWNLOAD: ${{fromJSON(steps.get_vars.outputs.SYSTEM_JSON).download}} - run: | - # Validate that the tag being released matches the package version. - if [[ ! $TAG_NAME == release-$PACKAGE_VERSION ]]; then - echo "The system.json version does not match tag name." - echo "system.json: $PACKAGE_VERSION" - echo "tag name: $TAG_NAME" - echo "Please fix this and push the tag again." - exit 1 - fi - - # Validate that the package download url matches the release asset that will be created. - if [[ ! $RELEASE_DOWNLOAD == $PACKAGE_DOWNLOAD ]]; then - echo "The system.json download url does not match the created release asset url." - echo "system.json: $PACKAGE_DOWNLOAD" - echo "release asset url: $RELEASE_DOWNLOAD" - echo "Please fix this and push the tag again." - exit 1 - fi - - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: @@ -70,19 +29,20 @@ jobs: npm run build cp --force LICENSE.txt system/. cp --force README.md system/. + SYSTEM_VERSION=$(grep -oP '(?<="version": ")[^"]+' system/system.json | tr -d '\n') + perl -pi -E "s|latest/download/ac2d20\\.zip|download/$SYSTEM_VERSION/ac2d20.zip|" system/system.json + echo "systemVersion=$SYSTEM_VERSION" >> $GITHUB_ENV - - run: cd system && zip ../${{steps.get_vars.outputs.ZIP_NAME}} -r assets css fonts lang packs src templates ac2d20.mjs ac2d20-compiled.mjs ac2d20-compiled.mjs.map LICENSE.txt README.md system.json template.json + - run: cd system && zip -r ../ac2d20.zip ./* - # Create a release for this specific version - - name: Update Release with Files + - name: Create Version Release id: create_version_release uses: ncipollo/release-action@v1 with: - allowUpdates: true # Set this to false if you want to prevent updating existing releases - name: ${{steps.get_vars.outputs.TAG_NAME}} + allowUpdates: false + name: ${{ env.systemVersion }} draft: false prerelease: false token: ${{ secrets.GITHUB_TOKEN }} - artifacts: './system/system.json, ./${{steps.get_vars.outputs.ZIP_NAME}}' - tag: ${{steps.get_vars.outputs.TAG_NAME}} - body: '**Installation:** To manually install this release, please use the following manifest URL: ${{steps.get_vars.outputs.RELEASE_INSTALL_URL}}' + artifacts: './system/system.json, ./ac2d20.zip' + tag: ${{ env.systemVersion }} diff --git a/.vscode/launch.json b/.vscode/launch.json index 2cb0dba..43bf413 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,8 +7,8 @@ { "type": "chrome", "request": "launch", - "name": "Achtung! Cthulhu 2d20 System", - "url": "http://localhost:30000", + "name": "Achtung! Cthulhu 2d20", + "url": "http://localhost:31000", "webRoot": "${workspaceFolder}/system" } ] diff --git a/CHANGELOG.md b/CHANGELOG.md index 3833684..5552a79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## v11.1.2 + +### Bugfix +- [#8] Weapon sizes not correctly displayed on Gear tab of character sheet +- [#9] Gear category labels for Skill Kits and Equipment not translated +- [#10] Spellcasting type always shows as Traditional when posted to chat +- [#11] Don't show brackets on spell display unless it has a Focus set + +## v11.1.1 + +### Bugfix +- [#3] Actor skills being overwritten when an Actor is duplicated + +### Chore +- Translation updates are now all handled via Crowdin to simplify the process of contributing translations. See here for more details: https://github.com/Muttley/foundryvtt-ac2d20/wiki/Other-ways-to-contribute#translation + ## v11.1.0 - System migrated to new home and build process diff --git a/README.md b/README.md index 51a6c54..1856ccf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ ![GitHub Release](https://img.shields.io/github/release-date/Muttley/foundryvtt-ac2d20) ![All Versions](https://img.shields.io/github/downloads/Muttley/foundryvtt-ac2d20/total) -![Latest Version](https://img.shields.io/github/downloads/Muttley/foundryvtt-ac2d20/latest/total) +![Latest Version](https://img.shields.io/github/downloads/Muttley/foundryvtt-ac2d20/latest/ac2d20.zip) +[![Crowdin](https://badges.crowdin.net/foundryvtt-ac2d20/localized.svg)](https://crowdin.com/project/foundryvtt-ac2d20) ![Forge Installs](https://img.shields.io/badge/dynamic/json?label=Forge%20Installs&query=package.installs&suffix=%25&url=https%3A%2F%2Fforge-vtt.com%2Fapi%2Fbazaar%2Fpackage%2Fac2d20) # Achtung! Cthulhu 2d20 System for Foundry VTT @@ -19,5 +20,5 @@ This is the unofficial Achtung Cthulhu 2d20 system for Foundry VTT. ## Featuring -- The system supports Dice-So-Nice module and introduces its own stress dice shortcut ("s") that you can use in chat or in journals (example: "`/r 1ds`", "`[[/r 1ds]]`", "`[[1ds]]`" +- The system supports Dice-So-Nice module and introduces its own stress dice shortcut ("s") that you can use in chat or in journals (example: "`/r 1ds`", "`[[/r 1ds]]`", "`[[1ds]]`") - IMPORTANT: The system doesn't provide any pre-populated content. diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 0000000..f342c93 --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,3 @@ +files: + - source: i18n/en.yaml + translation: /i18n/%two_letters_code%.yaml diff --git a/gulpfile.mjs b/gulpfile.mjs index c1d3477..0ba9e01 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -1,29 +1,29 @@ import gulp from "gulp"; import * as css from "./utils/css.mjs"; -// import * as lang from "./utils/lang.mjs"; +import * as lang from "./utils/lang.mjs"; import * as javascript from "./utils/javascript.mjs"; import * as packs from "./utils/packs.mjs"; export default gulp.series( gulp.parallel( css.compile, - // lang.compile, - // javascript.lint, + lang.compile, + javascript.lint, javascript.compile ), gulp.parallel( css.watchUpdates, - // lang.watchUpdates, + lang.watchUpdates, javascript.watchUpdates ) ); export const build = gulp.parallel( css.compile, - // lang.compile, - // javascript.lint, + lang.compile, + javascript.lint, javascript.compile, packs.compile ); @@ -31,6 +31,6 @@ export const build = gulp.parallel( // export const clean = gulp.parallel(css.clean, lang.clean, packs.clean); export const clean = gulp.parallel(css.clean, packs.clean); export const compileCss = gulp.series(css.compile); -// export const compileLang = gulp.series(lang.compile); +export const compileLang = gulp.series(lang.compile); export const compilePacks = gulp.series(packs.compile); export const lintJs = gulp.series(javascript.lint); diff --git a/i18n/en.yaml b/i18n/en.yaml new file mode 100644 index 0000000..cbb87e7 --- /dev/null +++ b/i18n/en.yaml @@ -0,0 +1,326 @@ + +"AC2D20.VEHICLES.QUALITIES.singleSeat:": Single Seat +AC2D20.Ability.agi: Agility +AC2D20.Ability.bra: Brawn +AC2D20.Ability.coo: Coordination +AC2D20.Ability.ins: Insight +AC2D20.Ability.rea: Reason +AC2D20.Ability.wil: Will +AC2D20.AbilityAbbr.agi: agi +AC2D20.AbilityAbbr.bra: bra +AC2D20.AbilityAbbr.coo: coo +AC2D20.AbilityAbbr.ins: ins +AC2D20.AbilityAbbr.rea: rea +AC2D20.AbilityAbbr.wil: wil +AC2D20.ARMOR.qualities.heavy: Heavy +AC2D20.ARMOR.qualities.shield: Shield +AC2D20.ARMOR.qualities.uncomfortable: Uncomfortable +AC2D20.Combat.CombatantsTurnDone: Turn Completed +AC2D20.Combat.CombatantsTurnNotDone: Turn Not Completed +AC2D20.Combat.CombatEndMomentumPoolDecremented: Momentum Pool Decremented at End of Combat +AC2D20.Combat.CombatHasNotStarted: Combat Has Not Started +AC2D20.Combat.CombatRoundMomentumPoolDecremented: Momentum Pool Decremented at Start of New Round +AC2D20.Combat.ToggleCombatantsTurnDone: Toggle Turn Completed +AC2D20.EffectCreate: Create Effect +AC2D20.EffectDelete: Delete Effect +AC2D20.EffectEdit: Edit Effect +AC2D20.EffectToggle: Toggle Effect +AC2D20.equipped: Equipped +AC2D20.FOCUS.Air Force: Air Force +AC2D20.FOCUS.Aircraft: Aircraft +AC2D20.FOCUS.Animal Handling: Animal Handling +AC2D20.FOCUS.Architecture: Architecture +AC2D20.FOCUS.Army: Army +AC2D20.FOCUS.Art: Art +AC2D20.FOCUS.Camouflage: Camouflage +AC2D20.FOCUS.Cars: Cars +AC2D20.FOCUS.Charm: Charm +AC2D20.FOCUS.Climbing: Climbing +AC2D20.FOCUS.Close Quarters: Close Quarters +AC2D20.FOCUS.Combat Engineering: Combat Engineering +AC2D20.FOCUS.Covert Operations: Covert Operations +AC2D20.FOCUS.Cryptography: Cryptography +AC2D20.FOCUS.Deceive: Deceive +AC2D20.FOCUS.Discipline: Discipline +AC2D20.FOCUS.Disguise: Disguise +AC2D20.FOCUS.Electronics: Electronics +AC2D20.FOCUS.Exotic: Exotic +AC2D20.FOCUS.Explosives: Explosives +AC2D20.FOCUS.Finance: Finance +AC2D20.FOCUS.First Aid: First Aid +AC2D20.FOCUS.Foraging: Foraging +AC2D20.FOCUS.Fortitude: Fortitude +AC2D20.FOCUS.Hand-to-Hand: Hand-to-Hand +AC2D20.FOCUS.Handguns: Handguns +AC2D20.FOCUS.Hearing: Hearing +AC2D20.FOCUS.Heavy Vehicles: Heavy Vehicles +AC2D20.FOCUS.Heavy Weapons: Heavy Weapons +AC2D20.FOCUS.History: History +AC2D20.FOCUS.Hunting: Hunting +AC2D20.FOCUS.Immunity: Immunity +AC2D20.FOCUS.Infectious Diseases: Infectious Diseases +AC2D20.FOCUS.Innuendo: Innuendo +AC2D20.FOCUS.Instincts: Instincts +AC2D20.FOCUS.Intimidation: Intimidation +AC2D20.FOCUS.Invocation: Invocation +AC2D20.FOCUS.Leadership: Leadership +AC2D20.FOCUS.Lifting: Lifting +AC2D20.FOCUS.Linguistics: Linguistics +AC2D20.FOCUS.Mechanical Engineering: Mechanical Engineering +AC2D20.FOCUS.Melee Weapons: Melee Weapons +AC2D20.FOCUS.Motorcycles: Motorcycles +AC2D20.FOCUS.Mysticism: Mysticism +AC2D20.FOCUS.Navy: Navy +AC2D20.FOCUS.Negotiation: Negotiation +AC2D20.FOCUS.Occultism: Occultism +AC2D20.FOCUS.Orienteering: Orienteering +AC2D20.FOCUS.Pharmacology: Pharmacology +AC2D20.FOCUS.Physical Training: Physical Training +AC2D20.FOCUS.Psychiatry: Psychiatry +AC2D20.FOCUS.Rhetoric: Rhetoric +AC2D20.FOCUS.Rifles: Rifles +AC2D20.FOCUS.Running: Running +AC2D20.FOCUS.Rural Stealth: Rural Stealth +AC2D20.FOCUS.Science: Science +AC2D20.FOCUS.Sight: Sight +AC2D20.FOCUS.Smell and Taste: Smell and Taste +AC2D20.FOCUS.Surgery: Surgery +AC2D20.FOCUS.Swimming: Swimming +AC2D20.FOCUS.Tanks: Tanks +AC2D20.FOCUS.Technical Projects: Technical Projects +AC2D20.FOCUS.Threat Awareness: Threat Awareness +AC2D20.FOCUS.Throwing: Throwing +AC2D20.FOCUS.Toxicology: Toxicology +AC2D20.FOCUS.Tracking: Tracking +AC2D20.FOCUS.Urban Stealth: Urban Stealth +AC2D20.FOCUS.Watercraft: Watercraft +AC2D20.OTHER: Other +AC2D20.RANGE.close: Close +AC2D20.RANGE.extreme: Extreme +AC2D20.RANGE.long: Long +AC2D20.RANGE.medium: Medium +AC2D20.RANGE.reach: Reach +AC2D20.RESISTANCE.armor: Armor +AC2D20.RESISTANCE.courage: Courage +AC2D20.RESISTANCE.fatigue: Fatigue +AC2D20.RESISTANCE.resistance: Resistance +AC2D20.SKILL.ACADEMIA: Academia +AC2D20.SKILL.ATHLETICS: Athletics +AC2D20.SKILL.ENGINEERING: Engineering +AC2D20.SKILL.FIGHTING: Fighting +AC2D20.SKILL.MEDICINE: Medicine +AC2D20.SKILL.OBSERVATION: Observation +AC2D20.SKILL.PERSUASION: Persuasion +AC2D20.SKILL.RESILIENCE: Resilience +AC2D20.SKILL.STEALTH: Stealth +AC2D20.SKILL.SURVIVAL: Survival +AC2D20.SKILL.TACTICS: Tactics +AC2D20.SKILL.VEHICLES: Vehicles +AC2D20.SPELL.SpellTypes.ins: Traditional +AC2D20.SPELL.SpellTypes.rea: Researcher +AC2D20.SPELL.SpellTypes.wil: Dabbler +AC2D20.Spellcasting.dabbler: dabbler +AC2D20.Spellcasting.researcher: researcher +AC2D20.Spellcasting.SpellcastingType: Spellcasting Type +AC2D20.Spellcasting.traditional: traditional +AC2D20.STRESS.current: Current Stress +AC2D20.STRESS.max: Max Stress +AC2D20.STRESS.stress: Stress +AC2D20.TEMPLATES.Abilities: Abilities +AC2D20.TEMPLATES.AddFocus: Add Focus +AC2D20.TEMPLATES.Ammo: Ammo +AC2D20.TEMPLATES.Attacks: ATTACKS +AC2D20.TEMPLATES.Attr: Attr. +AC2D20.TEMPLATES.Attribute: Attribute +AC2D20.TEMPLATES.Attributes: Attributes +AC2D20.TEMPLATES.bonus: Bonus +AC2D20.TEMPLATES.Compl: Compl. +AC2D20.TEMPLATES.Complications: Complications +AC2D20.TEMPLATES.Conditions: Conditions +AC2D20.TEMPLATES.Cost: Cost +AC2D20.TEMPLATES.CostEffects: Cost Effects +AC2D20.TEMPLATES.Create_Ammo: Create Ammo +AC2D20.TEMPLATES.Create_Special_Rule: Create Special Rule +AC2D20.TEMPLATES.Create_Weapon: Create Weapon +AC2D20.TEMPLATES.current: current +AC2D20.TEMPLATES.DAMAGE_EFFECTS: DAMAGE EFFECTS +AC2D20.TEMPLATES.DAMAGE_TYPE: DAMAGE TYPE +AC2D20.TEMPLATES.DAMAGE: DAMAGE +AC2D20.TEMPLATES.Data: Data +AC2D20.TEMPLATES.Default_Attribute: Default Attribute +AC2D20.TEMPLATES.DEFENSE: DEFENSE +AC2D20.TEMPLATES.Delete_Item: Delete Item +AC2D20.TEMPLATES.Delete: Delete +AC2D20.TEMPLATES.DERIVED: DERIVED +AC2D20.TEMPLATES.Description: Description +AC2D20.TEMPLATES.Diff: Diff +AC2D20.TEMPLATES.Difficulty: Difficulty +AC2D20.TEMPLATES.Dur: Dur +AC2D20.TEMPLATES.Duration: Duration +AC2D20.TEMPLATES.Edit_Item: Edit Item +AC2D20.TEMPLATES.Effect: Effect +AC2D20.TEMPLATES.Effects: Effects +AC2D20.TEMPLATES.Encumbered: ENCUMBERED +AC2D20.TEMPLATES.Encumbrance_Level: Encumbrance Level +AC2D20.TEMPLATES.Encumbrance: Encumbrance +AC2D20.TEMPLATES.ENG: ENG +AC2D20.TEMPLATES.equipped: equipped +AC2D20.TEMPLATES.FAVORITE_WEAPONS: FAVORITE WEAPONS +AC2D20.TEMPLATES.FIRE_RATE: FIRE RATE +AC2D20.TEMPLATES.Focus: Focus +AC2D20.TEMPLATES.fortune: Fortune +AC2D20.TEMPLATES.Gear: Gear +AC2D20.TEMPLATES.GENERAL: GENERAL +AC2D20.TEMPLATES.GM_MOMENTUM: GM Threat +AC2D20.TEMPLATES.Healthy: Healthy +AC2D20.TEMPLATES.HP_Healed: HP Healed +AC2D20.TEMPLATES.INITIATIVE: INITIATIVE +AC2D20.TEMPLATES.INJURIES: Injuries +AC2D20.TEMPLATES.Issue: Issue +AC2D20.TEMPLATES.Keywords: Keywords +AC2D20.TEMPLATES.lbs: lbs +AC2D20.TEMPLATES.Learned: Learned +AC2D20.TEMPLATES.Luck: Luck +AC2D20.TEMPLATES.MAX_PARTY_MOMENTUM: Max Momentum +AC2D20.TEMPLATES.max: max +AC2D20.TEMPLATES.MAX: MAX +AC2D20.TEMPLATES.MELEE_BONUS: MELEE BONUS +AC2D20.TEMPLATES.MELEE_DAMAGE: MELEE DAMAGE +AC2D20.TEMPLATES.Mod_Type: Mod Type +AC2D20.TEMPLATES.MODULES: MODULES +AC2D20.TEMPLATES.Name_Prefix: Name Prefix +AC2D20.TEMPLATES.PARTY_MOMENTUM: Party Momentum +AC2D20.TEMPLATES.Personal_Truth_Scars: Personal Truths & Scars +AC2D20.TEMPLATES.PHYS: PHYS +AC2D20.TEMPLATES.Points: Points +AC2D20.TEMPLATES.POISON: POISON +AC2D20.TEMPLATES.Power: Power +AC2D20.TEMPLATES.Qualities: Qualities +AC2D20.TEMPLATES.RANGE: Range +AC2D20.TEMPLATES.Rank: Rank +AC2D20.TEMPLATES.Ranks_current_maximum: Ranks [current/maximum] +AC2D20.TEMPLATES.rating: Rating +AC2D20.TEMPLATES.Re_roll: Re-roll +AC2D20.TEMPLATES.Requirements: Requirements +AC2D20.TEMPLATES.Resistance: Resistance +AC2D20.TEMPLATES.Resistances: Resistances +AC2D20.TEMPLATES.RESISTANCES: RESISTANCES +AC2D20.TEMPLATES.Resources: Resources +AC2D20.TEMPLATES.Restriction: Restriction +AC2D20.TEMPLATES.ritual_requirements: Requirements +AC2D20.TEMPLATES.ritual_resistance: Resistance +AC2D20.TEMPLATES.ritual_steps: Ritual Steps +AC2D20.TEMPLATES.ritual_stress: Ritual Stress +AC2D20.TEMPLATES.Ritual: Ritual +AC2D20.TEMPLATES.Roll_Formula: Roll Formula +AC2D20.TEMPLATES.Salvo: Salvo +AC2D20.TEMPLATES.scale: Scale +AC2D20.TEMPLATES.Size: Size +AC2D20.TEMPLATES.SizeLevels.Major: Major +AC2D20.TEMPLATES.SizeLevels.Minor: Minor +AC2D20.TEMPLATES.SizeLevels.Trivial: Trivial +AC2D20.TEMPLATES.Skill_Focus: Skill Focus +AC2D20.TEMPLATES.skill_focus: Skill/Focus +AC2D20.TEMPLATES.Skill_Value: Skill Value +AC2D20.TEMPLATES.Skill: Skill +AC2D20.TEMPLATES.SkillFocus: Skill Focus +AC2D20.TEMPLATES.Skills: Skills +AC2D20.TEMPLATES.Source: Source +AC2D20.TEMPLATES.SpecialRule: SpecialRule +AC2D20.TEMPLATES.SpecialRules: Special Rules +AC2D20.TEMPLATES.speed: Speed +AC2D20.TEMPLATES.Spells_Rituals: Spells And Rituals +AC2D20.TEMPLATES.Spells: Spells +AC2D20.TEMPLATES.Status: Status +AC2D20.TEMPLATES.Successes: Successes +AC2D20.TEMPLATES.Talents: Talents +AC2D20.TEMPLATES.TN: TN +AC2D20.TEMPLATES.Total: Total +AC2D20.TEMPLATES.Truths: Truths +AC2D20.TEMPLATES.Use_Agility: Use Agility +AC2D20.TEMPLATES.Use_Brawn: Use Brawn +AC2D20.TEMPLATES.Use_Coordination: Use Coordination +AC2D20.TEMPLATES.Use_Insight: Use Insight +AC2D20.TEMPLATES.Use_Reason: Use Reason +AC2D20.TEMPLATES.Use_Will: Use Will +AC2D20.TEMPLATES.Weapon_Qualities: WEAPON QUALITIES +AC2D20.TEMPLATES.Weapon_Type: Weapon Type +AC2D20.TEMPLATES.Weapons: Weapons +AC2D20.UI.Add: Add +AC2D20.UI.CarryWeight: Carry Weight +AC2D20.UI.Cost: Cost +AC2D20.UI.Damage: Damage +AC2D20.UI.favorite: Favorite +AC2D20.UI.INVENTORY: Inventory +AC2D20.UI.Name: Name +AC2D20.UI.ORIGIN: ORIGIN +AC2D20.UI.OTHER: Other +AC2D20.UI.Quantity: Quantity +AC2D20.UI.Rarity: Rarity +AC2D20.UI.SPECIAL_RULE: Special Rule +AC2D20.UI.stashed: Stashed +AC2D20.UI.Type: Type +AC2D20.UI.UNSORTED: Unsorted +AC2D20.UI.Weight: Weight +AC2D20.VEHICLES.QUALITIES.cargo: Cargo +AC2D20.VEHICLES.QUALITIES.cumbersome: Cumbersome +AC2D20.VEHICLES.QUALITIES.enclosed: Enclosed +AC2D20.VEHICLES.QUALITIES.exposed: Exposed +AC2D20.VEHICLES.QUALITIES.highPerformance: High Performance +AC2D20.VEHICLES.QUALITIES.singleSeat: Single Seat +AC2D20.VEHICLES.QUALITIES.tough: Tough +AC2D20.WEAPONS.damageEffect.area: Area +AC2D20.WEAPONS.damageEffect.backlash: Backlash +AC2D20.WEAPONS.damageEffect.drain: Drain +AC2D20.WEAPONS.damageEffect.intense: Intense +AC2D20.WEAPONS.damageEffect.persistent: Persistent +AC2D20.WEAPONS.damageEffect.piercing: Piercing +AC2D20.WEAPONS.damageEffect.snare: Snare +AC2D20.WEAPONS.damageEffect.stun: Stun +AC2D20.WEAPONS.damageEffect.vicious: Vicious +AC2D20.WEAPONS.damageType.energy: Energy +AC2D20.WEAPONS.damageType.physical: Physical +AC2D20.WEAPONS.damageType.poison: Poison +AC2D20.WEAPONS.damageType.radiation: Radiation +AC2D20.WEAPONS.qualities: Qualities +AC2D20.WEAPONS.type: Weapon Type +AC2D20.WEAPONS.weaponQuality.accurate: Accurate +AC2D20.WEAPONS.weaponQuality.bane: Bane +AC2D20.WEAPONS.weaponQuality.closeQuarters: Close Quarters +AC2D20.WEAPONS.weaponQuality.cumbersome: Cumbersome +AC2D20.WEAPONS.weaponQuality.debilitating: Debilitating +AC2D20.WEAPONS.weaponQuality.escalation: Escalation +AC2D20.WEAPONS.weaponQuality.giant-killer: Giant-Killer +AC2D20.WEAPONS.weaponQuality.heavy: Heavy +AC2D20.WEAPONS.weaponQuality.hidden: Hidden +AC2D20.WEAPONS.weaponQuality.hunger: Hunger +AC2D20.WEAPONS.weaponQuality.inaccurate: Inaccurate +AC2D20.WEAPONS.weaponQuality.indirect: Indirect +AC2D20.WEAPONS.weaponQuality.munition: Munition +AC2D20.WEAPONS.weaponQuality.parrying: Parrying +AC2D20.WEAPONS.weaponQuality.reliable: Reliable +AC2D20.WEAPONS.weaponQuality.subtle: Subtle +AC2D20.WEAPONS.weaponQuality.unreliable: Unreliable +AC2D20.WEAPONS.weaponTypes.agi: Melee +AC2D20.WEAPONS.weaponTypes.coo: Ranged +AC2D20.WEAPONS.weaponTypes.Melee: Melee +AC2D20.WEAPONS.weaponTypes.Mental: Mental +AC2D20.WEAPONS.weaponTypes.Ranged: Ranged +AC2D20.WEAPONS.weaponTypes.wil: Mental +ACTOR.NpcType.Lieutenant: Lieutenant +ACTOR.NpcType.Nemesis: Nemesis +ACTOR.NpcType.Trooper: Trooper +ACTOR.Vehicle.Cover: Cover +ACTOR.Vehicle.Impact: Impact +ACTOR.Vehicle.Passengers: Passengers +TYPES.Actor.character: Character +TYPES.Actor.npc: NPC +TYPES.Actor.vehicle: Vehicle +TYPES.Item.armor: Armor +TYPES.Item.equipment: Equipment +TYPES.Item.skill: Skill +TYPES.Item.skillkit: Skill Kit +TYPES.Item.special_rule: Special Rule +TYPES.Item.spell: Spell +TYPES.Item.talent: Talent +TYPES.Item.weapon: Weapon diff --git a/i18n/es.yaml b/i18n/es.yaml new file mode 100644 index 0000000..1c23371 --- /dev/null +++ b/i18n/es.yaml @@ -0,0 +1,325 @@ +"AC2D20.VEHICLES.QUALITIES.singleSeat:": Asiento único +AC2D20.Ability.agi: Agilidad +AC2D20.Ability.bra: Músculo +AC2D20.Ability.coo: Coordinación +AC2D20.Ability.ins: Perspicacia +AC2D20.Ability.rea: Razón +AC2D20.Ability.wil: Voluntad +AC2D20.AbilityAbbr.agi: agi +AC2D20.AbilityAbbr.bra: mus +AC2D20.AbilityAbbr.coo: coo +AC2D20.AbilityAbbr.ins: pers +AC2D20.AbilityAbbr.rea: raz +AC2D20.AbilityAbbr.wil: vol +AC2D20.ARMOR.qualities.heavy: Pesada +AC2D20.ARMOR.qualities.shield: Escudo +AC2D20.ARMOR.qualities.uncomfortable: Incómoda +AC2D20.Combat.CombatantsTurnDone: Turn Completed +AC2D20.Combat.CombatantsTurnNotDone: Turn Not Completed +AC2D20.Combat.CombatEndMomentumPoolDecremented: Momentum Pool Decremented at End of Combat +AC2D20.Combat.CombatHasNotStarted: Combat Has Not Started +AC2D20.Combat.CombatRoundMomentumPoolDecremented: Momentum Pool Decremented at Start of New Round +AC2D20.Combat.ToggleCombatantsTurnDone: Toggle Turn Completed +AC2D20.EffectCreate: Crear Efecto +AC2D20.EffectDelete: Borrar Efecto +AC2D20.EffectEdit: Editar Efecto +AC2D20.EffectToggle: Alternar Efecto +AC2D20.equipped: Equipado +AC2D20.FOCUS.Air Force: Fuerza Aérea +AC2D20.FOCUS.Aircraft: Vehículos Aéreos +AC2D20.FOCUS.Animal Handling: Manejo de Animales +AC2D20.FOCUS.Architecture: Arquitectura +AC2D20.FOCUS.Army: Ejército +AC2D20.FOCUS.Art: Arte +AC2D20.FOCUS.Camouflage: Camuflaje +AC2D20.FOCUS.Cars: Coches +AC2D20.FOCUS.Charm: Encanto +AC2D20.FOCUS.Climbing: Escalar +AC2D20.FOCUS.Close Quarters: Cercana +AC2D20.FOCUS.Combat Engineering: Ingeniería de Combate +AC2D20.FOCUS.Covert Operations: Operaciones Encubiertas +AC2D20.FOCUS.Cryptography: Criptografía +AC2D20.FOCUS.Deceive: Engaño +AC2D20.FOCUS.Discipline: Disciplina +AC2D20.FOCUS.Disguise: Disfraz +AC2D20.FOCUS.Electronics: Electrónica +AC2D20.FOCUS.Exotic: Exoticas +AC2D20.FOCUS.Explosives: Explosivos +AC2D20.FOCUS.Finance: Finanzas +AC2D20.FOCUS.First Aid: Primeros Auxilios +AC2D20.FOCUS.Foraging: Forrajeo +AC2D20.FOCUS.Fortitude: Fortaleza Interior +AC2D20.FOCUS.Hand-to-Hand: Mano a mano +AC2D20.FOCUS.Handguns: Pístolas +AC2D20.FOCUS.Hearing: Escuchar +AC2D20.FOCUS.Heavy Vehicles: Vehículos Pesados +AC2D20.FOCUS.Heavy Weapons: Armas Pesadas +AC2D20.FOCUS.History: Historia +AC2D20.FOCUS.Hunting: Caza +AC2D20.FOCUS.Immunity: Inmunidad +AC2D20.FOCUS.Infectious Diseases: Enfermedades Infecciosas +AC2D20.FOCUS.Innuendo: Seducción +AC2D20.FOCUS.Instincts: Instintos +AC2D20.FOCUS.Intimidation: Intimidación +AC2D20.FOCUS.Invocation: Invocación +AC2D20.FOCUS.Leadership: Liderazgo +AC2D20.FOCUS.Lifting: Levantar +AC2D20.FOCUS.Linguistics: Lingüística +AC2D20.FOCUS.Mechanical Engineering: Ingeniería Mecánica +AC2D20.FOCUS.Melee Weapons: Armas de Melé +AC2D20.FOCUS.Motorcycles: Motocicletas +AC2D20.FOCUS.Mysticism: Misticismo +AC2D20.FOCUS.Navy: Armada +AC2D20.FOCUS.Negotiation: Negociación +AC2D20.FOCUS.Occultism: Ocultismo +AC2D20.FOCUS.Orienteering: Orientación +AC2D20.FOCUS.Pharmacology: Farmacología +AC2D20.FOCUS.Physical Training: Entrenamiento Físico +AC2D20.FOCUS.Psychiatry: Psiquiatría +AC2D20.FOCUS.Rhetoric: Retórica +AC2D20.FOCUS.Rifles: Rifles +AC2D20.FOCUS.Running: Correr +AC2D20.FOCUS.Rural Stealth: Sigilo a campo abierto +AC2D20.FOCUS.Science: Ciencia +AC2D20.FOCUS.Sight: Ver +AC2D20.FOCUS.Smell and Taste: Oler y Saborear +AC2D20.FOCUS.Surgery: Cirugía +AC2D20.FOCUS.Swimming: Nadar +AC2D20.FOCUS.Tanks: Tanques +AC2D20.FOCUS.Technical Projects: Proyectos Técnicos +AC2D20.FOCUS.Threat Awareness: Sentir el Peligro +AC2D20.FOCUS.Throwing: Lanzar +AC2D20.FOCUS.Toxicology: Toxicología +AC2D20.FOCUS.Tracking: Rastrear +AC2D20.FOCUS.Urban Stealth: Sigilo Urbano +AC2D20.FOCUS.Watercraft: Vehículos Acuáticos +AC2D20.OTHER: Otro +AC2D20.RANGE.close: Corto +AC2D20.RANGE.extreme: Extremo +AC2D20.RANGE.long: Largo +AC2D20.RANGE.medium: Medio +AC2D20.RANGE.reach: Alcance +AC2D20.RESISTANCE.armor: Armadura +AC2D20.RESISTANCE.courage: Coraje +AC2D20.RESISTANCE.fatigue: Fatiga +AC2D20.RESISTANCE.resistance: Resistencia +AC2D20.SKILL.ACADEMIA: Académicas +AC2D20.SKILL.ATHLETICS: Atletismo +AC2D20.SKILL.ENGINEERING: Ingeniería +AC2D20.SKILL.FIGHTING: Combate +AC2D20.SKILL.MEDICINE: Medicina +AC2D20.SKILL.OBSERVATION: Observación +AC2D20.SKILL.PERSUASION: Persuasión +AC2D20.SKILL.RESILIENCE: Resiliencia +AC2D20.SKILL.STEALTH: Sigilo +AC2D20.SKILL.SURVIVAL: Supervivencia +AC2D20.SKILL.TACTICS: Tácticas +AC2D20.SKILL.VEHICLES: Vehículos +AC2D20.SPELL.SpellTypes.ins: Tradicional +AC2D20.SPELL.SpellTypes.rea: Investigador +AC2D20.SPELL.SpellTypes.wil: Aficionado +AC2D20.Spellcasting.dabbler: dabbler +AC2D20.Spellcasting.researcher: researcher +AC2D20.Spellcasting.SpellcastingType: Spellcasting Type +AC2D20.Spellcasting.traditional: traditional +AC2D20.STRESS.current: Estrés actual +AC2D20.STRESS.max: Estrés Máximo +AC2D20.STRESS.stress: Estrés +AC2D20.TEMPLATES.Abilities: Habilidades +AC2D20.TEMPLATES.AddFocus: Añadir Especialidad +AC2D20.TEMPLATES.Ammo: Munición +AC2D20.TEMPLATES.Attacks: ATAQUES +AC2D20.TEMPLATES.Attr: Atri. +AC2D20.TEMPLATES.Attribute: Atributo +AC2D20.TEMPLATES.Attributes: Atributos +AC2D20.TEMPLATES.bonus: Bono +AC2D20.TEMPLATES.Compl: Compl. +AC2D20.TEMPLATES.Complications: Complicaciones +AC2D20.TEMPLATES.Conditions: Condiciones +AC2D20.TEMPLATES.Cost: Coste +AC2D20.TEMPLATES.CostEffects: Coste de Efectos +AC2D20.TEMPLATES.Create_Ammo: Crear Munición +AC2D20.TEMPLATES.Create_Special_Rule: Crear Regla Especial +AC2D20.TEMPLATES.Create_Weapon: Crear Arma +AC2D20.TEMPLATES.current: actual +AC2D20.TEMPLATES.DAMAGE_EFFECTS: EFECTOS DE DAÑO +AC2D20.TEMPLATES.DAMAGE_TYPE: TIPO DE DAÑO +AC2D20.TEMPLATES.DAMAGE: DAÑO +AC2D20.TEMPLATES.Data: Datos +AC2D20.TEMPLATES.Default_Attribute: Atributo por Defecto +AC2D20.TEMPLATES.DEFENSE: DEFENSA +AC2D20.TEMPLATES.Delete_Item: Borrar Objeto +AC2D20.TEMPLATES.Delete: Borrar +AC2D20.TEMPLATES.DERIVED: DERIVADO +AC2D20.TEMPLATES.Description: Descripción +AC2D20.TEMPLATES.Diff: Dif +AC2D20.TEMPLATES.Difficulty: Dificultad +AC2D20.TEMPLATES.Dur: Dur +AC2D20.TEMPLATES.Duration: Duración +AC2D20.TEMPLATES.Edit_Item: Editar Objeto +AC2D20.TEMPLATES.Effect: Efecto +AC2D20.TEMPLATES.Effects: Efectos +AC2D20.TEMPLATES.Encumbered: SOBRECARGADO +AC2D20.TEMPLATES.Encumbrance_Level: Nivel de Carga +AC2D20.TEMPLATES.Encumbrance: Carga +AC2D20.TEMPLATES.ENG: ENG +AC2D20.TEMPLATES.equipped: Equipado +AC2D20.TEMPLATES.FAVORITE_WEAPONS: ARMAS FAVORITAS +AC2D20.TEMPLATES.FIRE_RATE: CADENCIA DE FUEG +AC2D20.TEMPLATES.Focus: Especialización +AC2D20.TEMPLATES.fortune: Fortuna +AC2D20.TEMPLATES.Gear: Equipo +AC2D20.TEMPLATES.GENERAL: GENERAL +AC2D20.TEMPLATES.GM_MOMENTUM: Amenaza DJ +AC2D20.TEMPLATES.Healthy: Saludable +AC2D20.TEMPLATES.HP_Healed: PV Curados +AC2D20.TEMPLATES.INITIATIVE: INICIATIVA +AC2D20.TEMPLATES.INJURIES: Heridas +AC2D20.TEMPLATES.Issue: Problema +AC2D20.TEMPLATES.Keywords: Palabras Clave +AC2D20.TEMPLATES.lbs: lbs +AC2D20.TEMPLATES.Learned: Aprendida +AC2D20.TEMPLATES.Luck: Suerte +AC2D20.TEMPLATES.MAX_PARTY_MOMENTUM: Inercia Máxima +AC2D20.TEMPLATES.max: max +AC2D20.TEMPLATES.MAX: MAX +AC2D20.TEMPLATES.MELEE_BONUS: BONO MELÉ +AC2D20.TEMPLATES.MELEE_DAMAGE: DAÑO MELÉ +AC2D20.TEMPLATES.Mod_Type: Tipo Mod +AC2D20.TEMPLATES.MODULES: MODULOS +AC2D20.TEMPLATES.Name_Prefix: Prefijo del Nombre +AC2D20.TEMPLATES.PARTY_MOMENTUM: Inercia Grupo +AC2D20.TEMPLATES.Personal_Truth_Scars: Verdades Personales & Cicatrices +AC2D20.TEMPLATES.PHYS: FIS +AC2D20.TEMPLATES.Points: Puntos +AC2D20.TEMPLATES.POISON: VENENO +AC2D20.TEMPLATES.Power: Poder +AC2D20.TEMPLATES.Qualities: Cualidades +AC2D20.TEMPLATES.RANGE: Alcance +AC2D20.TEMPLATES.Rank: Rango +AC2D20.TEMPLATES.Ranks_current_maximum: Rangos [actual/máximo] +AC2D20.TEMPLATES.rating: Valor +AC2D20.TEMPLATES.Re_roll: Tirar de Nuevo +AC2D20.TEMPLATES.Requirements: Requerimientos +AC2D20.TEMPLATES.Resistance: Resistencia +AC2D20.TEMPLATES.Resistances: Resistencias +AC2D20.TEMPLATES.RESISTANCES: RESISTENCIAS +AC2D20.TEMPLATES.Resources: Recursos +AC2D20.TEMPLATES.Restriction: Restricción +AC2D20.TEMPLATES.ritual_requirements: Requerimientos +AC2D20.TEMPLATES.ritual_resistance: Resistencia +AC2D20.TEMPLATES.ritual_steps: Fases del Ritual +AC2D20.TEMPLATES.ritual_stress: Estrés Ritual +AC2D20.TEMPLATES.Ritual: Ritual +AC2D20.TEMPLATES.Roll_Formula: Fórmula de Tirada +AC2D20.TEMPLATES.Salvo: Salva +AC2D20.TEMPLATES.scale: Escala +AC2D20.TEMPLATES.Size: Tamaño +AC2D20.TEMPLATES.SizeLevels.Major: Mayor +AC2D20.TEMPLATES.SizeLevels.Minor: Menor +AC2D20.TEMPLATES.SizeLevels.Trivial: Trivial +AC2D20.TEMPLATES.Skill_Focus: Especialidad de Habilidad +AC2D20.TEMPLATES.skill_focus: Habilidad/Especialidad +AC2D20.TEMPLATES.Skill_Value: Valor de Habilidad +AC2D20.TEMPLATES.Skill: Habilidad +AC2D20.TEMPLATES.SkillFocus: Especialidad de Habilidad +AC2D20.TEMPLATES.Skills: Habilidades +AC2D20.TEMPLATES.Source: Origen +AC2D20.TEMPLATES.SpecialRule: Regla Especial +AC2D20.TEMPLATES.SpecialRules: Reglas Especiales +AC2D20.TEMPLATES.speed: Velocidad +AC2D20.TEMPLATES.Spells_Rituals: Conjuros y Rituales +AC2D20.TEMPLATES.Spells: Conjuros +AC2D20.TEMPLATES.Status: Estatus +AC2D20.TEMPLATES.Successes: Éxitos +AC2D20.TEMPLATES.Talents: Talentos +AC2D20.TEMPLATES.TN: TN +AC2D20.TEMPLATES.Total: Total +AC2D20.TEMPLATES.Truths: Verdades +AC2D20.TEMPLATES.Use_Agility: Usa Agilidad +AC2D20.TEMPLATES.Use_Brawn: Usa Músculo +AC2D20.TEMPLATES.Use_Coordination: Usa Coordinación +AC2D20.TEMPLATES.Use_Insight: Usa Perspicacia +AC2D20.TEMPLATES.Use_Reason: Usa Razón +AC2D20.TEMPLATES.Use_Will: Usa Voluntad +AC2D20.TEMPLATES.Weapon_Qualities: CUALIDADES DE ARMA +AC2D20.TEMPLATES.Weapon_Type: Tipo de Arma +AC2D20.TEMPLATES.Weapons: Armas +AC2D20.UI.Add: Añadir +AC2D20.UI.CarryWeight: Peso Acarreado +AC2D20.UI.Cost: Coste +AC2D20.UI.Damage: Daño +AC2D20.UI.favorite: Favorito +AC2D20.UI.INVENTORY: Inventario +AC2D20.UI.Name: Nombre +AC2D20.UI.ORIGIN: ORIGEN +AC2D20.UI.OTHER: Otro +AC2D20.UI.Quantity: Cantidad +AC2D20.UI.Rarity: Rareza +AC2D20.UI.SPECIAL_RULE: Regla Especial +AC2D20.UI.stashed: Reservado +AC2D20.UI.Type: Tipo +AC2D20.UI.UNSORTED: Desordenado +AC2D20.UI.Weight: Peso +AC2D20.VEHICLES.QUALITIES.cargo: Carga +AC2D20.VEHICLES.QUALITIES.cumbersome: Incómodo +AC2D20.VEHICLES.QUALITIES.enclosed: Cerrado +AC2D20.VEHICLES.QUALITIES.exposed: Expuesto +AC2D20.VEHICLES.QUALITIES.highPerformance: Alta Eficacia +AC2D20.VEHICLES.QUALITIES.singleSeat: Asiento único +AC2D20.VEHICLES.QUALITIES.tough: Duro +AC2D20.WEAPONS.damageEffect.area: Área +AC2D20.WEAPONS.damageEffect.backlash: Retroceso +AC2D20.WEAPONS.damageEffect.drain: Drenar +AC2D20.WEAPONS.damageEffect.intense: Intensa +AC2D20.WEAPONS.damageEffect.persistent: Persistente +AC2D20.WEAPONS.damageEffect.piercing: Perforante +AC2D20.WEAPONS.damageEffect.snare: Trampa +AC2D20.WEAPONS.damageEffect.stun: Aturdidora +AC2D20.WEAPONS.damageEffect.vicious: Feroz +AC2D20.WEAPONS.damageType.energy: Enegía +AC2D20.WEAPONS.damageType.physical: Física +AC2D20.WEAPONS.damageType.poison: Veneno +AC2D20.WEAPONS.damageType.radiation: Radiación +AC2D20.WEAPONS.qualities: Cualidades +AC2D20.WEAPONS.type: Tipo de Arma +AC2D20.WEAPONS.weaponQuality.accurate: Precisa +AC2D20.WEAPONS.weaponQuality.bane: Flagelo +AC2D20.WEAPONS.weaponQuality.closeQuarters: Cercana +AC2D20.WEAPONS.weaponQuality.cumbersome: Incómoda +AC2D20.WEAPONS.weaponQuality.debilitating: Debilitante +AC2D20.WEAPONS.weaponQuality.escalation: Recrudecimiento +AC2D20.WEAPONS.weaponQuality.giant-killer: Mata-Gigantes +AC2D20.WEAPONS.weaponQuality.heavy: Pesada +AC2D20.WEAPONS.weaponQuality.hidden: Oculta +AC2D20.WEAPONS.weaponQuality.hunger: Hambrienta +AC2D20.WEAPONS.weaponQuality.inaccurate: Imprecisa +AC2D20.WEAPONS.weaponQuality.indirect: Indirecta +AC2D20.WEAPONS.weaponQuality.munition: Munición +AC2D20.WEAPONS.weaponQuality.parrying: Parada +AC2D20.WEAPONS.weaponQuality.reliable: Fiable +AC2D20.WEAPONS.weaponQuality.subtle: Sutil +AC2D20.WEAPONS.weaponQuality.unreliable: No fiable +AC2D20.WEAPONS.weaponTypes.agi: Melé +AC2D20.WEAPONS.weaponTypes.coo: Distancia +AC2D20.WEAPONS.weaponTypes.Melee: Melé +AC2D20.WEAPONS.weaponTypes.Mental: Mental +AC2D20.WEAPONS.weaponTypes.Ranged: Distancia +AC2D20.WEAPONS.weaponTypes.wil: Mental +ACTOR.NpcType.Lieutenant: Teniente +ACTOR.NpcType.Nemesis: Némesis +ACTOR.NpcType.Trooper: Tropa +ACTOR.Vehicle.Cover: Cobertura +ACTOR.Vehicle.Impact: Impacto +ACTOR.Vehicle.Passengers: Pasajeros +TYPES.Actor.character: Personaje +TYPES.Actor.npc: PNJ +TYPES.Actor.vehicle: Vehículo +TYPES.Item.armor: Armor +TYPES.Item.equipment: Equipment +TYPES.Item.skill: Skill +TYPES.Item.skillkit: Skill Kit +TYPES.Item.special_rule: Special Rule +TYPES.Item.spell: Spell +TYPES.Item.talent: Talent +TYPES.Item.weapon: Weapon diff --git a/package-lock.json b/package-lock.json index 2070cfa..d63185d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ "gulp": "^4.0.2", "gulp-eslint-new": "^1.8.0", "gulp-if": "^3.0.0", - "gulp-livereload": "^4.0.2", "gulp-sass": "^5.1.0", "gulp-yaml": "^2.0.4", "jest": "^29.5.0", @@ -22,7 +21,7 @@ "nedb-promises": "^6.2.1", "rollup": "^3.25.1", "sass": "^1.63.4", - "yaml": "^2.3.1", + "yaml": "^2.3.4", "yargs": "^17.7.2" } }, @@ -2701,18 +2700,6 @@ "node": ">= 6" } }, - "node_modules/body": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", - "integrity": "sha512-chUsBxGRtuElD6fmw1gHLpvnKdVLK302peeFa9ZqAEk8TyzZ3fygLyUEDDPTJvL9+Bor0dIwn6ePOsRM2y0zQQ==", - "dev": true, - "dependencies": { - "continuable-cache": "^0.3.1", - "error": "^7.0.0", - "raw-body": "~1.1.0", - "safe-json-parse": "~1.0.1" - } - }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -2850,12 +2837,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha512-/x68VkHLeTl3/Ll8IvxdwzhrT+IyKc52e/oyHhA2RwqPqswSnjVbSddfPRwAsJtbilMAPSRWwAlpxdYsSWOTKQ==", - "dev": true - }, "node_modules/cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -3305,12 +3286,6 @@ "typedarray": "^0.0.6" } }, - "node_modules/continuable-cache": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", - "integrity": "sha512-TF30kpKhTH8AGCG3dut0rdd/19B7Z+qCnrMoBLpyQu/2drZdNrrpcjPEoJeSVsQM+8KmWG5O56oPDjSSUsuTyA==", - "dev": true - }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -3724,15 +3699,6 @@ "once": "^1.4.0" } }, - "node_modules/error": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", - "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", - "dev": true, - "dependencies": { - "string-template": "~0.2.1" - } - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -4304,18 +4270,6 @@ "reusify": "^1.0.4" } }, - "node_modules/faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha512-Xhj93RXbMSq8urNCUq4p9l0P6hnySJ/7YNRhYNug0bLOuii7pKO7xQFb5mx9xZXWCar88pLPb805PvUkwrLZpQ==", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -5370,103 +5324,6 @@ "through2": "^3.0.1" } }, - "node_modules/gulp-livereload": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp-livereload/-/gulp-livereload-4.0.2.tgz", - "integrity": "sha512-InmaR50Xl1xB1WdEk4mrUgGHv3VhhlRLrx7u60iY5AAer90FlK95KXitPcGGQoi28zrUJM189d/h6+V470Ncgg==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "debug": "^3.1.0", - "fancy-log": "^1.3.2", - "lodash.assign": "^4.2.0", - "readable-stream": "^3.0.6", - "tiny-lr": "^1.1.1", - "vinyl": "^2.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/gulp-livereload/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-livereload/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-livereload/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/gulp-livereload/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/gulp-livereload/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-livereload/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/gulp-livereload/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/gulp-match": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.1.0.tgz", @@ -5820,12 +5677,6 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -8104,12 +7955,6 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "node_modules/livereload-js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", - "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", - "dev": true - }, "node_modules/load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -8174,12 +8019,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw==", - "dev": true - }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -8827,15 +8666,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -9460,21 +9290,6 @@ } ] }, - "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -9501,25 +9316,6 @@ "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", "dev": true }, - "node_modules/raw-body": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", - "integrity": "sha512-WmJJU2e9Y6M5UzTOkHaM7xJGAPQD8PNzx3bAd2+uhZAim6wDk6dAZxPVYLF67XhbR4hmKGh33Lpmh4XWrCH5Mg==", - "dev": true, - "dependencies": { - "bytes": "1", - "string_decoder": "0.10" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/raw-body/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "dev": true - }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", @@ -10107,12 +9903,6 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "node_modules/safe-json-parse": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", - "integrity": "sha512-o0JmTu17WGUaUOHa1l0FPGXKBfijbxK6qoHzlkihsDXxzBHvJcA7zgviKR92Xs841rX9pK16unfphLq0/KqX7A==", - "dev": true - }, "node_modules/safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", @@ -10391,20 +10181,6 @@ "node": ">=8" } }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -10788,12 +10564,6 @@ "node": ">=10" } }, - "node_modules/string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==", - "dev": true - }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -11070,29 +10840,6 @@ "node": ">=0.10.0" } }, - "node_modules/tiny-lr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", - "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", - "dev": true, - "dependencies": { - "body": "^5.1.0", - "debug": "^3.1.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.3.0", - "object-assign": "^4.1.0", - "qs": "^6.4.0" - } - }, - "node_modules/tiny-lr/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -11718,29 +11465,6 @@ "makeerror": "1.0.12" } }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 519bd2b..445ad23 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,6 @@ "gulp": "^4.0.2", "gulp-eslint-new": "^1.8.0", "gulp-if": "^3.0.0", - "gulp-livereload": "^4.0.2", "gulp-sass": "^5.1.0", "gulp-yaml": "^2.0.4", "jest": "^29.5.0", @@ -28,7 +27,7 @@ "nedb-promises": "^6.2.1", "rollup": "^3.25.1", "sass": "^1.63.4", - "yaml": "^2.3.1", + "yaml": "^2.3.4", "yargs": "^17.7.2" } } diff --git a/scss/ac2d20.scss b/scss/ac2d20.scss index 2308c6b..3b28ba2 100644 --- a/scss/ac2d20.scss +++ b/scss/ac2d20.scss @@ -2,10 +2,11 @@ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap'); .cth-ico-cth:before { - content: "\e900"; + content: "\e900"; } + .cth-ico-cth-cross:before { - content: "\e901"; + content: "\e901"; } // Import utilities. @@ -22,10 +23,8 @@ /* Styles limited to ac2d20 sheets */ .ac2d20 { - @import 'components/forms'; - @import 'components/resource'; - @import 'components/items'; - @import 'components/effects'; + @import 'components/forms'; + @import 'components/resource'; + @import 'components/items'; + @import 'components/effects'; } - - diff --git a/scss/components/_effects.scss b/scss/components/_effects.scss index 4c3b2c7..e9406c0 100644 --- a/scss/components/_effects.scss +++ b/scss/components/_effects.scss @@ -1,14 +1,15 @@ .effects .item { - .effect-source, - .effect-duration, - .effect-controls { - text-align: center; - border-left: 1px solid #c9c7b8; - border-right: 1px solid #c9c7b8; - font-size: 12px; - } - .effect-controls { - border: none; - } + .effect-source, + .effect-duration, + .effect-controls { + text-align: center; + border-left: 1px solid #c9c7b8; + border-right: 1px solid #c9c7b8; + font-size: 12px; + } + + .effect-controls { + border: none; + } } diff --git a/scss/components/_forms.scss b/scss/components/_forms.scss index 1229327..5061a91 100644 --- a/scss/components/_forms.scss +++ b/scss/components/_forms.scss @@ -1,495 +1,566 @@ .item-form { - font-family: $font-primary; + font-family: $font-primary; } .sheet-header { - flex: 0 auto; - overflow: hidden; - display: flex; - flex-direction: row; - flex-wrap: wrap; - justify-content: flex-start; - margin-bottom: 10px; - - .profile-img { - flex: 0 0 100px; - height: 100px; - margin-right: 10px; - margin-bottom: 5px; - box-shadow: 0px 1px 5px black; - border: 5px solid $c-white; - background-color: $c-light; - } - - .paperclip{ - position: absolute; - height: 60px; - margin-right: 10px; - border: none; - top:23px; - } - - .header-fields { - flex: 1; - .post-item{ - padding-top: 2rem; - cursor: pointer; - color: $c-green-olive; - } - } - - h1.sheet-name { - font-family: $font-germania; - padding: 0; - margin: 0; - border-bottom: 0; - flex: 2; - input { - width: 100%; - height: 100%; - margin: 0; - } - } + flex: 0 auto; + overflow: hidden; + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: flex-start; + margin-bottom: 10px; + + .profile-img { + flex: 0 0 100px; + height: 100px; + margin-right: 10px; + margin-bottom: 5px; + box-shadow: 0px 1px 5px black; + border: 5px solid $c-white; + background-color: $c-light; + } + + .paperclip { + position: absolute; + height: 60px; + margin-right: 10px; + border: none; + top: 23px; + } + + .header-fields { + flex: 1; + + .post-item { + padding-top: 2rem; + cursor: pointer; + color: $c-green-olive; + } + } + + h1.sheet-name { + font-family: $font-germania; + padding: 0; + margin: 0; + border-bottom: 0; + flex: 2; + + input { + width: 100%; + height: 100%; + margin: 0; + } + } } -nav{ - &.sheet-tabs{ - z-index: 1; - position: absolute; - display: flex; - top: 30px; - right: 0; - border: none; - line-height: unset; - margin: 0; - .buttons{ - padding: 0 5px; - background-color: $c-green-olive; - display: flex; - &.blue{ - background-color: $c-blue-dark; - } - .item{ - margin-top: 5px; - position: relative; - padding: 5px 10px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - font-family: $font-germania; - color: $c-black; - background-color: $c-light; - border: 1px solid $c-green-olive; - text-shadow: none; - &.active{ - color: $c-light; - background-color: $c-green-light; - text-shadow: none; - margin-top: 2px; - } - &.active.blue{ - background-color: $c-blue-light; - } - &.blue{border: 1px solid $c-blue-dark;} - } - } - img{ - border: none; - border-radius: unset; - } - } +nav { + &.sheet-tabs { + z-index: 1; + position: absolute; + display: flex; + top: 30px; + right: 0; + border: none; + line-height: unset; + margin: 0; + + .buttons { + padding: 0 5px; + background-color: $c-green-olive; + display: flex; + + &.blue { + background-color: $c-blue-dark; + } + + .item { + margin-top: 5px; + position: relative; + padding: 5px 10px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + font-family: $font-germania; + color: $c-black; + background-color: $c-light; + border: 1px solid $c-green-olive; + text-shadow: none; + + &.active { + color: $c-light; + background-color: $c-green-light; + text-shadow: none; + margin-top: 2px; + } + + &.active.blue { + background-color: $c-blue-light; + } + + &.blue { + border: 1px solid $c-blue-dark; + } + } + } + + img { + border: none; + border-radius: unset; + } + } } .sheet-body, .sheet-body .tab, .sheet-body .tab .editor { - height: 100%; + height: 100%; } -.sheet-body .tab .editor{ - border: 1px solid $c-green-light; - padding: 5px; + +.sheet-body .tab .editor { + border: 1px solid $c-green-light; + padding: 5px; } + .sheet-body .tab { - &.flex-tab{ - display: flex; - flex-direction: column; - } + &.flex-tab { + display: flex; + flex-direction: column; + } } .tox { - .tox-editor-container { - background: $c-white; - } + .tox-editor-container { + background: $c-white; + } - .tox-edit-area { - padding: 0 8px; - } + .tox-edit-area { + padding: 0 8px; + } } -.section-title{ - display: flex; - flex-direction: row; - - h3{ - display: flex; - align-items: center; - font-family: Germania One; - color: $c-light; - background-color: $c-green-olive; - padding: 2px 5px; - margin-bottom: 0; - width: fit-content; - &.blue{ - background-color: $c-blue-dark; - } - } - .right-slope{ - min-width: 22px; - background-repeat: no-repeat; - &.olive{ - background-image: url(../assets/right-slope-olive.webp); - } - &.blue{ - background-image: url(../assets/right-slope-blue.webp); - } - } +.section-title { + display: flex; + flex-direction: row; + + h3 { + display: flex; + align-items: center; + font-family: Germania One; + color: $c-light; + background-color: $c-green-olive; + padding: 2px 5px; + margin-bottom: 0; + width: fit-content; + + &.blue { + background-color: $c-blue-dark; + } + } + + .right-slope { + min-width: 22px; + background-repeat: no-repeat; + + &.olive { + background-image: url(../assets/right-slope-olive.webp); + } + + &.blue { + background-image: url(../assets/right-slope-blue.webp); + } + } } -.attribute-grid{ - display: grid; - grid-template-columns: repeat(7, 1fr); - color:$c-light; - - .attribute-cell { - display: flex; - align-items: center; - padding: 1px; - justify-content: center; - border: 1px solid $c-green-light; - margin:0 -1px -1px 0; - &.green{ - background-color: $c-green-light; - } - &.olive{ - font-family: $font-germania; - background-color: $c-green-olive; - } - input[type="number"] { - text-align: center; - } - } +.attribute-grid { + display: grid; + grid-template-columns: repeat(7, 1fr); + color: $c-light; + + .attribute-cell { + display: flex; + align-items: center; + padding: 1px; + justify-content: center; + border: 1px solid $c-green-light; + margin: 0 -1px -1px 0; + + &.green { + background-color: $c-green-light; + } + + &.olive { + font-family: $font-germania; + background-color: $c-green-olive; + } + + input[type="number"] { + text-align: center; + } + } } -.stress-derived-box{ - display: flex; - justify-content: space-between; - margin-bottom: 10px; +.stress-derived-box { + display: flex; + justify-content: space-between; + margin-bottom: 10px; } -.derived-box{ - display:flex; - //justify-content: flex-end; - align-items: center; - input[type="number"]{ - font-size: 1.2rem; - line-height: 1.2rem; - height: 30px; - font-family: 'Germania One'; - } - h3{ - padding: 2px 5px; - margin: 0; - color: $c-light; - background-color: $c-green-olive; - font-family: Germania One; - &.minmax{ - padding-right: 5px; - background-color: $c-green-olive; - } - } +.derived-box { + display: flex; + //justify-content: flex-end; + align-items: center; + + input[type="number"] { + font-size: 1.2rem; + line-height: 1.2rem; + height: 30px; + font-family: 'Germania One'; + } + + h3 { + padding: 2px 5px; + margin: 0; + color: $c-light; + background-color: $c-green-olive; + font-family: Germania One; + + &.minmax { + padding-right: 5px; + background-color: $c-green-olive; + } + } } -.injuries-grid{ - display: grid; - grid-template-columns: repeat(3, 1fr); - //margin-bottom: 10px; - .injury-cell { - .controls{ - display: flex; - justify-content: space-between; - input[type="checkbox"] { - -webkit-appearance: none; - -moz-appearance: none; - filter: none; - box-sizing: borer-box; - width: 20px; - height: 20px; - cursor: pointer; - margin: 0; - &.treated{ - background: url(../assets/injury-not-treated.webp); - } - &.injury-type{ - background: url(../assets/injury-p.webp); - } - } - input[type="checkbox"]:checked { - margin: 0; - filter: none; - &.treated{background: url(../assets/injury-treated.webp);} - &.injury-type{ - background: url(../assets/injury-m.webp); - } - - } - } - - padding: 2px; - border: 1px solid $c-green-light; - margin:0 -1px -1px 0; - .injury-text{ - padding: 0; - resize: none; - border: none; - background-color: unset; - white-space: normal; - min-height: 6rem; - } - } +.injuries-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + + //margin-bottom: 10px; + .injury-cell { + .controls { + display: flex; + justify-content: space-between; + + input[type="checkbox"] { + -webkit-appearance: none; + -moz-appearance: none; + filter: none; + box-sizing: borer-box; + width: 20px; + height: 20px; + cursor: pointer; + margin: 0; + + &.treated { + background: url(../assets/injury-not-treated.webp); + } + + &.injury-type { + background: url(../assets/injury-p.webp); + } + } + + input[type="checkbox"]:checked { + margin: 0; + filter: none; + + &.treated { + background: url(../assets/injury-treated.webp); + } + + &.injury-type { + background: url(../assets/injury-m.webp); + } + + } + } + + padding: 2px; + border: 1px solid $c-green-light; + margin:0 -1px -1px 0; + + .injury-text { + padding: 0; + resize: none; + border: none; + background-color: unset; + white-space: normal; + min-height: 6rem; + } + } } -.truths-grid{ - display: grid; - grid-template-columns: repeat(5, 1fr); - margin-bottom: 10px; - .truth-cell { - padding: 2px; - border: 1px solid $c-green-light; - margin:0 -1px -1px 0; - textarea{ - resize: none; - border: none; - background-color: unset; - } - } +.truths-grid { + display: grid; + grid-template-columns: repeat(5, 1fr); + margin-bottom: 10px; + + .truth-cell { + padding: 2px; + border: 1px solid $c-green-light; + margin: 0 -1px -1px 0; + + textarea { + resize: none; + border: none; + background-color: unset; + } + } } -.skills{ - display: flex; - flex-direction: column; - border: 1px solid $c-green-light; - - .skill{ - display: flex; - flex-direction: row; - flex: 0; - border-bottom: 1px solid $c-green-light; - align-items: stretch; - .skill-name{ - display: flex; - flex: 1; - align-items: center; - padding: 5px; - color: $c-light; - background-color: $c-green-light; - font-weight: 900; - cursor: pointer; - } - .skill-value{ - display: flex; - align-items: center; - padding: 0 5px; - border-left: 1px solid $c-green-light; - border-right: 1px solid $c-green-light; - } - .skill-focuses{ - display: flex; - align-items: center; - flex-direction: row; - flex-wrap: wrap; - flex: 5; - padding: 5px; - .skill-focus{ - color:rgb(150, 150, 150); - &.focused{ - cursor: pointer; - color:beige; - background-color: $c-green-light; - border-radius: 3px; - padding: 0 2px; - } - } - } - } - .skill:last-child{ - border-bottom: none; - } +.skills { + display: flex; + flex-direction: column; + border: 1px solid $c-green-light; + + .skill { + display: flex; + flex-direction: row; + flex: 0; + border-bottom: 1px solid $c-green-light; + align-items: stretch; + + .skill-name { + display: flex; + flex: 1; + align-items: center; + padding: 5px; + color: $c-light; + background-color: $c-green-light; + font-weight: 900; + cursor: pointer; + } + + .skill-value { + display: flex; + align-items: center; + padding: 0 5px; + border-left: 1px solid $c-green-light; + border-right: 1px solid $c-green-light; + } + + .skill-focuses { + display: flex; + align-items: center; + flex-direction: row; + flex-wrap: wrap; + flex: 5; + padding: 5px; + color: rgb(150, 150, 150); + + .skill-focus { + + &.focused { + cursor: pointer; + color: beige; + background-color: $c-green-light; + border-radius: 3px; + padding: 0 2px; + margin: 0 1px; + } + } + } + } + + .skill:last-child { + border-bottom: none; + } } -.ac-grid{ - display: flex; - flex-direction: column; - border: 1px solid $c-green-light; - .item{ - border-bottom: 1px solid $c-green-light; - &:last-child{ - border-bottom: none; - } - .row{ - display: flex; - flex-direction: row; - flex: 0; - - align-items: stretch; - &:last-child{ - border-bottom: none; - } - .cell{ - display: flex; - padding: 5px; - border-right: 1px solid $c-green-light; - //text-align: center; - //justify-content: center; - &.align-center{ - align-items: center; - } - &.align-left{ - justify-content: start; - text-align: left; - } - &.cell-name{ - img{ - max-width: 1.563rem; - max-height: 1.563rem; - margin-right: 0.313rem; - } - } - &.column{ - flex-direction: column; - } - &:last-child{ - border-right: none; - } - &.f1{ - flex: 1; - } - &.f2{ - flex: 2; - } - &.f3{ - flex: 3; - } - &.f4{ - flex: 4; - } - &.f5{ - flex: 5; - } - &.f05{ - flex: 0.5; - } - &.roll{ - cursor: pointer; - } - &.green{ - color: $c-light; - background-color: $c-green-light; - font-weight: 900; - } - } - } - .item-summary{ - padding: 5px; - border-top: 1px solid $c-green-light; - border-bottom: 1px solid $c-green-light; - } - } +.ac-grid { + display: flex; + flex-direction: column; + border: 1px solid $c-green-light; + + .item { + border-bottom: 1px solid $c-green-light; + + &:last-child { + border-bottom: none; + } + + .row { + display: flex; + flex-direction: row; + flex: 0; + + align-items: stretch; + + &:last-child { + border-bottom: none; + } + + .cell { + display: flex; + padding: 5px; + border-right: 1px solid $c-green-light; + + //text-align: center; + //justify-content: center; + &.align-center { + align-items: center; + } + + &.align-left { + justify-content: start; + text-align: left; + } + + &.cell-name { + img { + max-width: 1.563rem; + max-height: 1.563rem; + margin-right: 0.313rem; + } + } + + &.column { + flex-direction: column; + } + + &:last-child { + border-right: none; + } + + &.f1 { + flex: 1; + } + + &.f2 { + flex: 2; + } + + &.f3 { + flex: 3; + } + + &.f4 { + flex: 4; + } + + &.f5 { + flex: 5; + } + + &.f05 { + flex: 0.5; + } + + &.roll { + cursor: pointer; + } + + &.green { + color: $c-light; + background-color: $c-green-light; + font-weight: 900; + } + } + } + + .item-summary { + padding: 5px; + border-top: 1px solid $c-green-light; + border-bottom: 1px solid $c-green-light; + } + } } -.label-number-box{ - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - padding: 0.3rem; - margin-bottom: 0.3rem; - background-color: $c-green-light; - input[type="number"]{ - height: 1.1rem; - } - &.blue{ - background-color: $c-blue-light; - } - label{ - font-weight: 900; - color: $c-light; - text-transform: capitalize; - } +.label-number-box { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 0.3rem; + margin-bottom: 0.3rem; + background-color: $c-green-light; + + input[type="number"] { + height: 1.1rem; + } + + &.blue { + background-color: $c-blue-light; + } + + label { + font-weight: 900; + color: $c-light; + text-transform: capitalize; + } } -.item-sheet{ - .focus-item{ - display: flex; - flex-direction: row; - margin-bottom: 5px; - } +.item-sheet { + .focus-item { + display: flex; + flex-direction: row; + margin-bottom: 5px; + } } -.editor-small{ - display: flex; - flex-direction: column; - //height: auto; - flex:1; - overflow: hidden; - // min-height: 220px; - // height: 200px; - .editor{ - flex: 0.96; - } - .tox { - flex: 1; - .tox-editor-container { - min-height: 100px; - flex: 1; - background: $c-white; - } - - .tox-edit-area { - flex: 1; - padding: 0 8px; - } - } +.editor-small { + display: flex; + flex-direction: column; + //height: auto; + flex: 1; + overflow: hidden; + + // min-height: 220px; + // height: 200px; + .editor { + flex: 0.96; + } + + .tox { + flex: 1; + + .tox-editor-container { + min-height: 100px; + flex: 1; + background: $c-white; + } + + .tox-edit-area { + flex: 1; + padding: 0 8px; + } + } } .cell-expander, -.expandable-info{ - cursor: pointer; +.expandable-info { + cursor: pointer; } #context-menu { - left: unset; - right: 0; - min-width: unset; - width: unset; - li.context-item { - line-height: 26px; - } - .context-items { - display: flex; - } + left: unset; + right: 0; + min-width: unset; + width: unset; + + li.context-item { + line-height: 26px; + } + + .context-items { + display: flex; + } } + .expand-down { - top: 3px !important; - right: 3px !important; - bottom: 0 !important; + top: 3px !important; + right: 3px !important; + bottom: 0 !important; } + .expand-up { - top: 3px !important; - right: 3px !important; - bottom: 0 !important; -} \ No newline at end of file + top: 3px !important; + right: 3px !important; + bottom: 0 !important; +} diff --git a/scss/components/_items.scss b/scss/components/_items.scss index f4909bb..6bf00aa 100644 --- a/scss/components/_items.scss +++ b/scss/components/_items.scss @@ -1,23 +1,25 @@ // Section Header .items-header { - height: 28px; - margin: 2px 0; - padding: 0; - align-items: center; - background: rgba(0, 0, 0, 0.05); - border: $c-green-light; - font-weight: bold; - > * { - font-size: 14px; - text-align: center; - } - .item-name { - font-weight: bold; - padding-left: 5px; - text-align: left; - display: flex; - // font-size: 16px; - } + height: 28px; + margin: 2px 0; + padding: 0; + align-items: center; + background: rgba(0, 0, 0, 0.05); + border: $c-green-light; + font-weight: bold; + + > * { + font-size: 14px; + text-align: center; + } + + .item-name { + font-weight: bold; + padding-left: 5px; + text-align: left; + display: flex; + // font-size: 16px; + } } /* ----------------------------------------- */ @@ -25,96 +27,106 @@ /* ----------------------------------------- */ // Child lists .item-list { - .item{ - margin: 0; - .effect-name{ - .item-image{ - max-width: 25px; - max-height:25px; - } - } - } - .item-list { - list-style: none; - margin: 0; - padding: 0; - } + .item { + margin: 0; + + .effect-name { + .item-image { + max-width: 25px; + max-height: 25px; + } + } + } + + .item-list { + list-style: none; + margin: 0; + padding: 0; + } } -.items-list-npc{ - list-style: none; - margin: 0; - padding: 0; - overflow-y: auto; - scrollbar-width: thin; - //color: $c-dark; - - // Child lists - .item-list { - list-style: none; - margin: 0; - padding: 0; - } - - .item{ - padding: 0.313rem; - .main-row{ - display: flex; - flex-direction: row; - justify-content: space-between; - - .item-name { - font-weight: 900; - font-size: 0.875rem; - } - } - .skill-focuses{ - *{ - font-size: 0.688rem; - } - } - } - - .item:nth-child(odd) { - background: lighten($c-light, 0%) - } - .item:nth-child(even) { - background: lighten($c-light, 5%) - } +.items-list-npc { + list-style: none; + margin: 0; + padding: 0; + overflow-y: auto; + scrollbar-width: thin; + //color: $c-dark; + + // Child lists + .item-list { + list-style: none; + margin: 0; + padding: 0; + } + + .item { + padding: 0.313rem; + + .main-row { + display: flex; + flex-direction: row; + justify-content: space-between; + + .item-name { + font-weight: 900; + font-size: 0.875rem; + } + } + + .skill-focuses { + * { + font-size: 0.688rem; + } + } + } + + .item:nth-child(odd) { + background: lighten($c-light, 0%) + } + + .item:nth-child(even) { + background: lighten($c-light, 5%) + } } - // Control Buttons - .item-controls { - display: flex; - flex: 0 0 100px; - justify-content: flex-end; - align-items: center; - a { - font-size: 12px; - text-align: center; - margin: 0 6px; - color: grey; - } +// Control Buttons +.item-controls { + display: flex; + flex: 0 0 100px; + justify-content: flex-end; + align-items: center; + + a { + font-size: 12px; + text-align: center; + margin: 0 6px; + color: grey; + } } + /* Example style for Boilerplate (can be removed if not needed) */ .item-formula { - flex: 0 0 200px; - padding: 0 8px; + flex: 0 0 200px; + padding: 0 8px; } -.item-control{ - color: $c-green-olive; - &.blue{ - color: $c-blue-dark; - } - margin-right: 3px; - &.item-unequipped, - .item-unstashed, - .item-unpowered, - .favorite-start-dim { - color: rgba(73, 78, 49, 0.3); - } -} \ No newline at end of file +.item-control { + color: $c-green-olive; + + &.blue { + color: $c-blue-dark; + } + + margin-right: 3px; + + &.item-unequipped, + .item-unstashed, + .item-unpowered, + .favorite-start-dim { + color: rgba(73, 78, 49, 0.3); + } +} diff --git a/scss/components/_momentum-app.scss b/scss/components/_momentum-app.scss index 7e840f9..4def081 100644 --- a/scss/components/_momentum-app.scss +++ b/scss/components/_momentum-app.scss @@ -8,7 +8,7 @@ //background-color: $f-vault-blue; bottom: 40px !important; right: 320px !important; - max-width: 180px; + max-width: 180px; z-index: 1000; .ap-resource { @@ -16,17 +16,20 @@ padding: 10px 20px; background-size: 100% 100%; background-repeat: no-repeat; - border-radius:9px; + border-radius: 9px; font-family: $font-germania; + //color: white; &.gm { - background-color: $c-green-olive; + background-color: $c-green-olive; } + &.party { - background-color: $c-green-light; + background-color: $c-green-light; } + &.maxMomentum-box { - background-color: $c-green-olive; + background-color: $c-green-olive; } .toggle-maxAp { @@ -37,17 +40,20 @@ } margin-bottom: 10px; + &:last-child { margin-bottom: 0; } + h4 { margin: 0 0 2px 0; color: bisque; } + input[type="number"] { margin: 0 5px; font-size: 16px; - text-align: center; + text-align: center; } .ap-btn { diff --git a/scss/components/_resource.scss b/scss/components/_resource.scss index 87cde1d..f062918 100644 --- a/scss/components/_resource.scss +++ b/scss/components/_resource.scss @@ -2,17 +2,20 @@ input[type="text"], input[type="number"] { background-color: $c-light; color: $c-dark; + &.underline { background-color: unset; border: unset; border-bottom: 1px solid $c-dark; color: $c-dark; + &::placeholder { color: #999; } } - &.borderless { - border: none; + + &.borderless { + border: none; } } @@ -20,30 +23,34 @@ input[type="number"] { input[type="checkbox"] { display: none; } + label { cursor: pointer; display: flex; - align-items: center; + align-items: center; } - padding: 3px; + + padding: 3px; + &.active { color: $c-light; - background-color:$c-green-light; + background-color: $c-green-light; } } -.resource{ +.resource { margin-bottom: 5px; align-items: center; - &.green-field{ + + &.green-field { padding: 5px; background-color: $c-green-olive; color: $c-light; } } -.resource-label{ +.resource-label { text-transform: capitalize; } @@ -69,30 +76,34 @@ select { max-width: 2rem; text-align: center; } + .num-short-3 { max-width: 3rem; text-align: center; } -.num-small{ - height:1.1rem ; + +.num-small { + height: 1.1rem; } -.clickable{ +.clickable { cursor: pointer; - &:hover{ + + &:hover { //font-weight: bold; text-shadow: 0 0 0.313rem #999; } } -.textbox{ - width: 100%; - height: 100%; - padding: 0.3rem; - border:1px solid grey; - textarea{ +.textbox { + width: 100%; + height: 100%; + padding: 0.3rem; + border: 1px solid grey; + + textarea { resize: none; - padding: 0; + padding: 0; border: unset; border-radius: 0; background-color: unset; diff --git a/scss/global/_flex.scss b/scss/global/_flex.scss index a95b5a6..8280087 100644 --- a/scss/global/_flex.scss +++ b/scss/global/_flex.scss @@ -1,57 +1,59 @@ // Flexbox. -.flex{ - display: flex; +.flex { + display: flex; } .flex-group-center, .flex-group-left, .flex-group-right { - justify-content: center; - align-items: center; - text-align: center; + justify-content: center; + align-items: center; + text-align: center; } .flex-group-left { - justify-content: flex-start; - text-align: left; + justify-content: flex-start; + text-align: left; } .flex-group-right { - justify-content: flex-end; - text-align: right; + justify-content: flex-end; + text-align: right; } .flexshrink { - flex: 0; + flex: 0; } .flex-between { - justify-content: space-between; + justify-content: space-between; } .flex-1 { - flex: 1; + flex: 1; } + .flex-2 { - flex: 2; + flex: 2; } + .flex-3 { - flex: 3; + flex: 3; } // Alignment styles. .align-left { - justify-content: flex-start; - text-align: left; + justify-content: flex-start; + text-align: left; } .align-right { - justify-content: flex-end; - text-align: right; + justify-content: flex-end; + text-align: right; } .align-center { - justify-content: center; - text-align: center; - align-items: center; -} \ No newline at end of file + justify-content: center; + text-align: center; + align-items: center; +} diff --git a/scss/global/_grid.scss b/scss/global/_grid.scss index 452a7b3..ae3bf34 100644 --- a/scss/global/_grid.scss +++ b/scss/global/_grid.scss @@ -1,85 +1,149 @@ // Grid. .grid, .grid-2col { - display: grid; - grid-column: span 2 / span 2; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 10px; - margin: 0 0 0.3rem 0; - padding: 0; + display: grid; + grid-column: span 2 / span 2; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 10px; + margin: 0 0 0.3rem 0; + padding: 0; } .grid-3col { - grid-column: span 3 / span 3; - grid-template-columns: repeat(3, minmax(0, 1fr)); + grid-column: span 3 / span 3; + grid-template-columns: repeat(3, minmax(0, 1fr)); } .grid-4col { - grid-column: span 4 / span 4; - grid-template-columns: repeat(4, minmax(0, 1fr)); + grid-column: span 4 / span 4; + grid-template-columns: repeat(4, minmax(0, 1fr)); } .grid-5col { - grid-column: span 5 / span 5; - grid-template-columns: repeat(5, minmax(0, 1fr)); + grid-column: span 5 / span 5; + grid-template-columns: repeat(5, minmax(0, 1fr)); } .grid-6col { - grid-column: span 6 / span 6; - grid-template-columns: repeat(6, minmax(0, 1fr)); + grid-column: span 6 / span 6; + grid-template-columns: repeat(6, minmax(0, 1fr)); } .grid-7col { - grid-column: span 7 / span 7; - grid-template-columns: repeat(7, minmax(0, 1fr)); + grid-column: span 7 / span 7; + grid-template-columns: repeat(7, minmax(0, 1fr)); } .grid-8col { - grid-column: span 8 / span 8; - grid-template-columns: repeat(8, minmax(0, 1fr)); + grid-column: span 8 / span 8; + grid-template-columns: repeat(8, minmax(0, 1fr)); } .grid-9col { - grid-column: span 9 / span 9; - grid-template-columns: repeat(9, minmax(0, 1fr)); + grid-column: span 9 / span 9; + grid-template-columns: repeat(9, minmax(0, 1fr)); } .grid-10col { - grid-column: span 10 / span 10; - grid-template-columns: repeat(10, minmax(0, 1fr)); + grid-column: span 10 / span 10; + grid-template-columns: repeat(10, minmax(0, 1fr)); } .grid-11col { - grid-column: span 11 / span 11; - grid-template-columns: repeat(11, minmax(0, 1fr)); + grid-column: span 11 / span 11; + grid-template-columns: repeat(11, minmax(0, 1fr)); } .grid-12col { - grid-column: span 12 / span 12; - grid-template-columns: repeat(12, minmax(0, 1fr)); + grid-column: span 12 / span 12; + grid-template-columns: repeat(12, minmax(0, 1fr)); } // Grid offset. -.grid-start-2 { grid-column-start: 2 } -.grid-start-3 { grid-column-start: 3 } -.grid-start-4 { grid-column-start: 4 } -.grid-start-5 { grid-column-start: 5 } -.grid-start-6 { grid-column-start: 6 } -.grid-start-7 { grid-column-start: 7 } -.grid-start-8 { grid-column-start: 8 } -.grid-start-9 { grid-column-start: 9 } -.grid-start-10 { grid-column-start: 10 } -.grid-start-11 { grid-column-start: 11 } -.grid-start-12 { grid-column-start: 12 } - -.grid-span-2 { grid-column-end: span 2 } -.grid-span-3 { grid-column-end: span 3 } -.grid-span-4 { grid-column-end: span 4 } -.grid-span-5 { grid-column-end: span 5 } -.grid-span-6 { grid-column-end: span 6 } -.grid-span-7 { grid-column-end: span 7 } -.grid-span-8 { grid-column-end: span 8 } -.grid-span-9 { grid-column-end: span 9 } -.grid-span-10 { grid-column-end: span 10 } -.grid-span-11 { grid-column-end: span 11 } -.grid-span-12 { grid-column-end: span 12 } +.grid-start-2 { + grid-column-start: 2 +} + +.grid-start-3 { + grid-column-start: 3 +} + +.grid-start-4 { + grid-column-start: 4 +} + +.grid-start-5 { + grid-column-start: 5 +} + +.grid-start-6 { + grid-column-start: 6 +} + +.grid-start-7 { + grid-column-start: 7 +} + +.grid-start-8 { + grid-column-start: 8 +} + +.grid-start-9 { + grid-column-start: 9 +} + +.grid-start-10 { + grid-column-start: 10 +} + +.grid-start-11 { + grid-column-start: 11 +} + +.grid-start-12 { + grid-column-start: 12 +} + +.grid-span-2 { + grid-column-end: span 2 +} + +.grid-span-3 { + grid-column-end: span 3 +} + +.grid-span-4 { + grid-column-end: span 4 +} + +.grid-span-5 { + grid-column-end: span 5 +} + +.grid-span-6 { + grid-column-end: span 6 +} + +.grid-span-7 { + grid-column-end: span 7 +} + +.grid-span-8 { + grid-column-end: span 8 +} + +.grid-span-9 { + grid-column-end: span 9 +} + +.grid-span-10 { + grid-column-end: span 10 +} + +.grid-span-11 { + grid-column-end: span 11 +} + +.grid-span-12 { + grid-column-end: span 12 +} diff --git a/scss/global/_window.scss b/scss/global/_window.scss index d9d2d8a..b5c5b02 100644 --- a/scss/global/_window.scss +++ b/scss/global/_window.scss @@ -1,20 +1,22 @@ .window-app { - font-family: $font-primary; - .window-content{ - background-image: url(../assets/paper.webp); - } + font-family: $font-primary; + + .window-content { + background-image: url(../assets/paper.webp); + } } -button{ - font-family: $font-germania; - font-size: 16px; - color: $c-green-olive; - background-color: $c-beige; - &:hover { - //text-shadow: 0 0 10px $c-green-light; - box-shadow: 0 0 5px $c-green-light; - cursor: pointer; - } +button { + font-family: $font-germania; + font-size: 16px; + color: $c-green-olive; + background-color: $c-beige; + + &:hover { + //text-shadow: 0 0 10px $c-green-light; + box-shadow: 0 0 5px $c-green-light; + cursor: pointer; + } } .font-primary { @@ -33,23 +35,29 @@ button{ font-size: 12px; } -input[type="text"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="date"]:focus, input[type="time"]:focus { - box-shadow: 0 0 5px $c-green-light; +input[type="text"]:focus, +input[type="number"]:focus, +input[type="password"]:focus, +input[type="date"]:focus, +input[type="time"]:focus { + box-shadow: 0 0 5px $c-green-light; } -a{ - &:hover{ - text-shadow: 0 0 10px $c-green-olive; - cursor: pointer; - } +a { + &:hover { + text-shadow: 0 0 10px $c-green-olive; + cursor: pointer; + } } + .rollable { - &:hover, - &:focus { - color: #000; - text-shadow: 0 0 10px $c-green-light; - cursor: pointer; - } + + &:hover, + &:focus { + color: #000; + text-shadow: 0 0 10px $c-green-light; + cursor: pointer; + } } @@ -62,32 +70,37 @@ a{ text-overflow: ''; margin-left: 5px; font-family: $font-germania; - } + } .resource { margin: 0 2px 5px; padding: 0 5px 0 0; background-color: $c-green-light; - //border: 1px solid $c-green-light ; + + //border: 1px solid $c-green-light ; .title-label { padding: 5px; font-family: $font-germania; - font-size: 1rem; + font-size: 1rem; color: $c-white; } + input[type="number"] { text-align: center; - background-color:$c-beige; + background-color: $c-beige; } } + ul { list-style: none; padding: 5px 20px; margin: 0 2px 5px; + //background-color: $c-beige; li { text-decoration: none; text-align: center; + .dice-icon { cursor: pointer; width: 32px; @@ -101,6 +114,7 @@ a{ font-weight: bold; text-align: center; background-image: url(../assets/chat/d20-green-light.svg); + &.marked { color: $c-light; background-image: url(../assets/chat/d20-olive.svg); @@ -117,21 +131,25 @@ a{ .ac2d20-chat-message { .content { padding: 5px; + h2 { border: none; font-family: $font-germania; font-weight: 700; } + .dices-result { margin: 5px 0 5px 0; min-height: 32px; } + .success-plaq { margin: 0 0 5px 0; font-family: $font-germania; - color: $c-green-olive; + color: $c-green-olive; //padding: 10px; font-size: 16px; + //background-image: url(../assets/chat/green-placq.webp); //background-size: 100% 100%; //background-repeat: no-repeat; @@ -141,16 +159,18 @@ a{ font-weight: bold; } } + .complication-plaq { margin: 0 0 5px 0; font-family: $font-germania; - color: $c-red-dark; + color: $c-red-dark; //padding: 14px 10px 10px 10px; //font-size: 12px; //background-image: url(../assets/chat/red-placq.webp); //background-size: 100% 100%; //background-repeat: no-repeat; } + .damage-plaq { //color: white; margin: 0 0 5px 0; @@ -161,6 +181,7 @@ a{ //background-size: 100% 100%; //background-repeat: no-repeat; } + .dice-icon { cursor: pointer; position: relative; @@ -174,20 +195,25 @@ a{ color: rgb(0, 0, 0); font-weight: bold; text-align: center; + //-webkit-text-stroke: 1px rgb(255, 255, 255); &.d20 { background-image: url(../assets/chat/d20-white.svg); + &.complication { color: honeydew !important; background-image: url(../assets/chat/d20-complication.svg); } + &.success { background-image: url(../assets/chat/d20-success.svg); } + &.crit { color: gold !important; background-image: url(../assets/chat/d20-crit.svg); } + &.reroll { color: #1d1d1d; } @@ -198,21 +224,27 @@ a{ line-height: 32px; background-size: 32px 32px; margin: 2px; + &.face-1 { background-image: url(../assets/chat/d1.webp); } + &.face-2 { background-image: url(../assets/chat/d2.webp); } + &.face-3 { background-image: url(../assets/chat/d3.webp); } + &.face-4 { background-image: url(../assets/chat/d4.webp); } + &.face-5 { background-image: url(../assets/chat/d5.webp); } + &.face-6 { background-image: url(../assets/chat/d6.webp); } @@ -225,15 +257,17 @@ a{ } } -.chat-item{ - .item-name{ +.chat-item { + .item-name { text-align: center; - h3{ + + h3 { font-family: $font-germania; font-size: 1.5rem; } } - img{ + + img { width: 4rem; height: 4rem; } @@ -241,10 +275,11 @@ a{ .dice-tooltip .dice-rolls .roll.max { - color: unset; - filter: none; + color: unset; + filter: none; } + .dice-tooltip .dice-rolls .roll.min { - color: unset; - filter: none; -} \ No newline at end of file + color: unset; + filter: none; +} diff --git a/scss/utils/_colors.scss b/scss/utils/_colors.scss index 3270ee8..55eb92c 100644 --- a/scss/utils/_colors.scss +++ b/scss/utils/_colors.scss @@ -9,5 +9,5 @@ $c-green-olive: #494e31; $c-green-light: #759549; $c-green-neon: #b4bb5b; $c-red-dark: #6b0b0b; -$c-blue-dark:#3d485a; -$c-blue-light:#548da9; \ No newline at end of file +$c-blue-dark: #3d485a; +$c-blue-light: #548da9; diff --git a/scss/utils/_mixins.scss b/scss/utils/_mixins.scss index 69dd2ad..cd1394d 100644 --- a/scss/utils/_mixins.scss +++ b/scss/utils/_mixins.scss @@ -1,16 +1,16 @@ @mixin element-invisible { - position: absolute; + position: absolute; - width: 1px; - height: 1px; - margin: -1px; - border: 0; - padding: 0; + width: 1px; + height: 1px; + margin: -1px; + border: 0; + padding: 0; - clip: rect(0 0 0 0); - overflow: hidden; + clip: rect(0 0 0 0); + overflow: hidden; } @mixin hide { - display: none; -} \ No newline at end of file + display: none; +} diff --git a/scss/utils/_typography.scss b/scss/utils/_typography.scss index a4a4521..5926c69 100644 --- a/scss/utils/_typography.scss +++ b/scss/utils/_typography.scss @@ -6,67 +6,76 @@ $font-secondary: 'Roboto', sans-serif; $font-germania: 'Germania One', cursive; $icomoon-font-family: "cthulhu-icons" !default; -$icomoon-font-path: "../fonts" !default; +$icomoon-font-path: "../assets/fonts" !default; $cth-ico-cth: "\e900"; $cth-ico-cth-cross: "\e901"; @font-face { - font-family: '#{$icomoon-font-family}'; - src: url('#{$icomoon-font-path}/#{$icomoon-font-family}.eot?h5tze8'); - src: url('#{$icomoon-font-path}/#{$icomoon-font-family}.eot?h5tze8#iefix') format('embedded-opentype'), - url('#{$icomoon-font-path}/#{$icomoon-font-family}.ttf?h5tze8') format('truetype'), - url('#{$icomoon-font-path}/#{$icomoon-font-family}.woff?h5tze8') format('woff'), - url('#{$icomoon-font-path}/#{$icomoon-font-family}.svg?h5tze8##{$icomoon-font-family}') format('svg'); - font-weight: normal; - font-style: normal; - font-display: block; - } - - [class^="cth-"], [class*=" cth-"] { - /* use !important to prevent issues with browser extensions that change fonts */ - font-family: '#{$icomoon-font-family}' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - } - - .cth-ico-cth { - &:before { - content: $cth-ico-cth; - } - } - .cth-ico-cth-cross { - &:before { - content: $cth-ico-cth-cross; - } - } + font-family: '#{$icomoon-font-family}'; + src: url('#{$icomoon-font-path}/#{$icomoon-font-family}.eot?h5tze8'); + src: url('#{$icomoon-font-path}/#{$icomoon-font-family}.eot?h5tze8#iefix') format('embedded-opentype'), + url('#{$icomoon-font-path}/#{$icomoon-font-family}.ttf?h5tze8') format('truetype'), + url('#{$icomoon-font-path}/#{$icomoon-font-family}.woff?h5tze8') format('woff'), + url('#{$icomoon-font-path}/#{$icomoon-font-family}.svg?h5tze8##{$icomoon-font-family}') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + +[class^="cth-"], +[class*=" cth-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: '#{$icomoon-font-family}' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.cth-ico-cth { + &:before { + content: $cth-ico-cth; + } +} + +.cth-ico-cth-cross { + &:before { + content: $cth-ico-cth-cross; + } +} - /* Generated by Glyphter (http://www.glyphter.com) on Wed Sep 21 2022*/ +/* Generated by Glyphter (http://www.glyphter.com) on Wed Sep 21 2022*/ @font-face { - font-family: 'AC Cthulhu Icons'; - src: url('../fonts/AC-Cthulhu-Icons.eot'); - src: url('../fonts/AC-Cthulhu-Icons.eot?#iefix') format('embedded-opentype'), - url('../fonts/AC-Cthulhu-Icons.woff') format('woff'), - url('../fonts/AC-Cthulhu-Icons.ttf') format('truetype'), - url('../fonts/AC-Cthulhu-Icons.svg#AC-Cthulhu-Icons') format('svg'); - font-weight: normal; - font-style: normal; + font-family: 'AC Cthulhu Icons'; + src: url('../fonts/AC-Cthulhu-Icons.eot'); + src: url('../fonts/AC-Cthulhu-Icons.eot?#iefix') format('embedded-opentype'), + url('../fonts/AC-Cthulhu-Icons.woff') format('woff'), + url('../fonts/AC-Cthulhu-Icons.ttf') format('truetype'), + url('../fonts/AC-Cthulhu-Icons.svg#AC-Cthulhu-Icons') format('svg'); + font-weight: normal; + font-style: normal; +} + +[class*='cthl-']:before { + display: inline-block; + font-family: 'AC Cthulhu Icons'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale } -[class*='cthl-']:before{ -display: inline-block; - font-family: 'AC Cthulhu Icons'; - font-style: normal; - font-weight: normal; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale + +.cthl-cthulhu:before { + content: '\0041'; +} + +.cthl-cross:before { + content: '\0043'; } -.cthl-cthulhu:before{content:'\0041';} -.cthl-cross:before{content:'\0043';} \ No newline at end of file diff --git a/scss/utils/_variables.scss b/scss/utils/_variables.scss index 6d22f61..260808e 100644 --- a/scss/utils/_variables.scss +++ b/scss/utils/_variables.scss @@ -2,4 +2,4 @@ $padding-sm: 5px; $padding-md: 10px; $padding-lg: 20px; -$border-groove: 2px groove #eeede0; \ No newline at end of file +$border-groove: 2px groove #eeede0; diff --git a/system/ac2d20.mjs b/system/ac2d20.mjs index 201c47e..e3084f8 100644 --- a/system/ac2d20.mjs +++ b/system/ac2d20.mjs @@ -9,19 +9,19 @@ import { ACItemSheet } from "./src/sheets/item-sheet.mjs"; // Import helper/utility classes and constants. import { AC2D20 } from "./src/helpers/config.mjs"; import { preloadHandlebarsTemplates } from "./src/helpers/templates.mjs"; -import { registerHandlebarsHelpers } from "./src/helpers/handlebars.mjs" -//Import Roll2D20 -import { Roller2D20 } from "./src/roller/ac2d20-roller.mjs" -import { Dialog2d20 } from './src/roller/dialog2d20.js' -import { DialogD6 } from './src/roller/dialogD6.js' -import DieACChallenge from './src/roller/challengeDie.js' -//Settings -import { registerSettings } from './src/settings.js'; +import { registerHandlebarsHelpers } from "./src/helpers/handlebars.mjs"; +// Import Roll2D20 +import { Roller2D20 } from "./src/roller/ac2d20-roller.mjs"; +import { Dialog2d20 } from "./src/roller/dialog2d20.js"; +import { DialogD6 } from "./src/roller/dialogD6.js"; +import DieACChallenge from "./src/roller/challengeDie.js"; +// Settings +import { registerSettings } from "./src/settings.js"; // Text Enrichers -import { registerEnrichers } from './src/enrichers.mjs'; -//Momentum -import { MomentumTracker } from './src/app/momentum-tracker.mjs' -//Combat Tracker +import { registerEnrichers } from "./src/enrichers.mjs"; +// Momentum +import { MomentumTracker } from "./src/app/momentum-tracker.mjs"; +// Combat Tracker import Combat2d20 from "./src/combat/combat.mjs"; import CombatTracker2d20 from "./src/combat/combat-tracker.mjs"; @@ -30,187 +30,196 @@ import CombatTracker2d20 from "./src/combat/combat-tracker.mjs"; /* -------------------------------------------- */ registerHandlebarsHelpers(); +Hooks.once("init", async function() { + // Add utility classes to the global game object so that they're more easily + // accessible in global contexts. -Hooks.once('init', async function () { - // Add utility classes to the global game object so that they're more easily - // accessible in global contexts. + game.ac2d20 = { + ACActor, + ACItem, + Roller2D20, + Dialog2d20, + DialogD6, + MomentumTracker, + }; - game.ac2d20 = { - ACActor, - ACItem, - Roller2D20, - Dialog2d20, - DialogD6, - MomentumTracker, - }; + // Add custom constants for configuration. + CONFIG.AC2D20 = AC2D20; - // Add custom constants for configuration. - CONFIG.AC2D20 = AC2D20; - - /** + /** * Set an initiative formula for the system * @type {String} */ - CONFIG.Combat.initiative = { - formula: "1", - decimals: 0 - }; + CONFIG.Combat.initiative = { + formula: "1", + decimals: 0, + }; - // Define custom Document classes - CONFIG.Actor.documentClass = ACActor; - CONFIG.Item.documentClass = ACItem; - CONFIG.Dice.terms["s"] = DieACChallenge; + // Define custom Document classes + CONFIG.Actor.documentClass = ACActor; + CONFIG.Item.documentClass = ACItem; + CONFIG.Dice.terms.s = DieACChallenge; // Combat tracker stuff CONFIG.Combat.documentClass = Combat2d20; CONFIG.ui.combat = CombatTracker2d20; - // Register sheet application classes - Actors.unregisterSheet("core", ActorSheet); - Actors.registerSheet("ac2d20", ACActorSheet, { types: ["character"], makeDefault: true }); - Actors.registerSheet("ac2d20", ACNPCSheet, { types: ["npc"], makeDefault: true }); - Actors.registerSheet("ac2d20", ACVehicleSheet, { types: ["vehicle"], makeDefault: true }); - Items.unregisterSheet("core", ItemSheet); - Items.registerSheet("ac2d20", ACItemSheet, { makeDefault: true }); + // Register sheet application classes + Actors.unregisterSheet("core", ActorSheet); + Actors.registerSheet("ac2d20", ACActorSheet, { types: ["character"], makeDefault: true }); + Actors.registerSheet("ac2d20", ACNPCSheet, { types: ["npc"], makeDefault: true }); + Actors.registerSheet("ac2d20", ACVehicleSheet, { types: ["vehicle"], makeDefault: true }); + Items.unregisterSheet("core", ItemSheet); + Items.registerSheet("ac2d20", ACItemSheet, { makeDefault: true }); - // Register custom system settings - registerSettings(); + // Register custom system settings + registerSettings(); // Register text enrichers. registerEnrichers(); - return preloadHandlebarsTemplates(); + return preloadHandlebarsTemplates(); }); -Hooks.on('ready', async () => { - // set skill list - const skillPackName = game.settings.get('ac2d20', 'compendium-skills'); - let packSkills = await game.packs.get(skillPackName).getDocuments(); - let _skills = [] - packSkills.forEach(s => { - _skills.push({ - 'label': s.name.toUpperCase(), - 'key': s.name, - 'focuses': s.system.focuses.map(f=> f.title) - }); - }); - AC2D20.SKILLS = [..._skills]; - const listLocation = await game.settings.get('ac2d20', 'hoversJsonLocation') - const jsonFile = await fetch(listLocation) - const content = await jsonFile.json(); - CONFIG.AC2D20.WEAPONS.effects = content.effects; - CONFIG.AC2D20.WEAPONS.qualities = content.qualities; - - for await (const key of Object.keys(content.effects)){ - let qEnriched = await TextEditor.enrichHTML(content.effects[key], {async: true}); - content.effects[key] = qEnriched.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"').replaceAll("'", '''); - } - - for await (const key of Object.keys(content.qualities)){ - let qEnriched = await TextEditor.enrichHTML(content.qualities[key], {async: true}); - content.qualities[key] = qEnriched.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"').replaceAll("'", '''); - } - -}) - - -Hooks.on('renderChatMessage', (message, html, data) => { - let rrlBtn = html.find('.reroll-button'); - if (rrlBtn.length > 0) { - rrlBtn[0].setAttribute('data-messageId', message.id); - rrlBtn.click((el) => { - //let selectedDiceForReroll = $(el.currentTarget).parent().find('.dice-selected'); - let selectedDiceForReroll = html.find('.dice-selected'); - let rerollIndex = []; - for (let d of selectedDiceForReroll) { - rerollIndex.push($(d).data('index')); - } - if (!rerollIndex.length) { - ui.notifications.notify('Select Dice you want to Reroll'); - } - else { - let ac2d20Roll = message.flags.ac2d20roll; - if (ac2d20Roll.diceFace == "d20") { - Roller2D20.rerollD20({ - rollname: ac2d20Roll.rollname, - rerollIndexes: rerollIndex, - successTreshold: ac2d20Roll.successTreshold, - critTreshold: ac2d20Roll.critTreshold, - complicationTreshold: ac2d20Roll.complicationTreshold, - dicesRolled: ac2d20Roll.dicesRolled - }); - } else if (ac2d20Roll.diceFace == "d6") { - Roller2D20.rerollD6({ - rollname: ac2d20Roll.rollname, - rerollIndexes: rerollIndex, - dicesRolled: ac2d20Roll.dicesRolled, - itemId: message.flags.itemId, - actorId: message.flags.actorId, - }); - } else { - ui.notifications.notify('No dice face reckognized'); - } - - } - }) - } - html.find('.dice-icon').click((el) => { - //if ($(el.currentTarget).hasClass('reroll')) - //return; - if ($(el.currentTarget).hasClass('dice-selected')) { - $(el.currentTarget).removeClass('dice-selected'); - } else { - $(el.currentTarget).addClass('dice-selected') - } - }); - let addBtn = html.find('.add-button'); - if (addBtn.length > 0) { - addBtn[0].setAttribute('data-messageId', message.id); - addBtn.click((ev) => { - let ac2d20Roll = message.flags.ac2d20roll; - let itemId = message.flags.itemId; - let actorId = message.flags.actorId; - game.ac2d20.DialogD6.createDialog({ rollname: ac2d20Roll.rollname, diceNum: 1, ac2d20Roll: ac2d20Roll, itemId: itemId, actorId: actorId }) - }); - } +Hooks.on("ready", async () => { + // set skill list + const skillPackName = game.settings.get("ac2d20", "compendium-skills"); + let packSkills = await game.packs.get(skillPackName).getDocuments(); + let _skills = []; + packSkills.forEach(s => { + _skills.push({ + label: s.name.toUpperCase(), + key: s.name, + focuses: s.system.focuses.map(f => f.title), + }); + }); + + AC2D20.SKILLS = _skills.sort((a, b) => a.key.localeCompare(b.key)); + + const listLocation = await game.settings.get("ac2d20", "hoversJsonLocation"); + const jsonFile = await fetch(listLocation); + const content = await jsonFile.json(); + CONFIG.AC2D20.WEAPONS.effects = content.effects; + CONFIG.AC2D20.WEAPONS.qualities = content.qualities; + + for await (const key of Object.keys(content.effects)) { + let qEnriched = await TextEditor.enrichHTML(content.effects[key], {async: true}); + content.effects[key] = qEnriched.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'"); + } + + for await (const key of Object.keys(content.qualities)) { + let qEnriched = await TextEditor.enrichHTML(content.qualities[key], {async: true}); + content.qualities[key] = qEnriched.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'"); + } }); +Hooks.on("renderChatMessage", (message, html, data) => { + let rrlBtn = html.find(".reroll-button"); + if (rrlBtn.length > 0) { + rrlBtn[0].setAttribute("data-messageId", message.id); + rrlBtn.click(el => { + // let selectedDiceForReroll = $(el.currentTarget).parent().find('.dice-selected'); + let selectedDiceForReroll = html.find(".dice-selected"); + let rerollIndex = []; + for (let d of selectedDiceForReroll) { + rerollIndex.push($(d).data("index")); + } + if (!rerollIndex.length) { + ui.notifications.notify("Select Dice you want to Reroll"); + } + else { + let ac2d20Roll = message.flags.ac2d20roll; + if (ac2d20Roll.diceFace === "d20") { + Roller2D20.rerollD20({ + rollname: ac2d20Roll.rollname, + rerollIndexes: rerollIndex, + successTreshold: ac2d20Roll.successTreshold, + critTreshold: ac2d20Roll.critTreshold, + complicationTreshold: ac2d20Roll.complicationTreshold, + dicesRolled: ac2d20Roll.dicesRolled, + }); + } + else if (ac2d20Roll.diceFace === "d6") { + Roller2D20.rerollD6({ + rollname: ac2d20Roll.rollname, + rerollIndexes: rerollIndex, + dicesRolled: ac2d20Roll.dicesRolled, + itemId: message.flags.itemId, + actorId: message.flags.actorId, + }); + } + else { + ui.notifications.notify("No dice face reckognized"); + } + + } + }); + } + html.find(".dice-icon").click(el => { + // if ($(el.currentTarget).hasClass('reroll')) + // return; + if ($(el.currentTarget).hasClass("dice-selected")) { + $(el.currentTarget).removeClass("dice-selected"); + } + else { + $(el.currentTarget).addClass("dice-selected"); + } + }); + let addBtn = html.find(".add-button"); + if (addBtn.length > 0) { + addBtn[0].setAttribute("data-messageId", message.id); + addBtn.click(ev => { + let ac2d20Roll = message.flags.ac2d20roll; + let itemId = message.flags.itemId; + let actorId = message.flags.actorId; + game.ac2d20.DialogD6.createDialog({ + rollname: ac2d20Roll.rollname, + diceNum: 1, + ac2d20Roll: ac2d20Roll, + itemId: itemId, + actorId: actorId, + }); + }); + } + +}); + /* -------------------------------------------- */ /* DICE SO NICE */ /* -------------------------------------------- */ -Hooks.once("diceSoNiceReady", (dice3d) => { - dice3d.addSystem( - { id: "ac2d20", name: "Achtung Cthulhu 2d20" }, - true - ); - - dice3d.addColorset( - { - name: "ac2d20", - description: "Achtung Cthulhu 2d20", - category: "Colors", - foreground: "#000000", - background: "#000000", - outline: "#000000", - texture: "none", - } - ); - - dice3d.addDicePreset({ - type: "ds", - labels: [ - "systems/ac2d20/assets/dice/d1.webp", - "systems/ac2d20/assets/dice/d2.webp", - "systems/ac2d20/assets/dice/d3.webp", - "systems/ac2d20/assets/dice/d4.webp", - "systems/ac2d20/assets/dice/d5.webp", - "systems/ac2d20/assets/dice/d6.webp", - ], - system: "ac2d20", - colorset: "ac2d20" - }); +Hooks.once("diceSoNiceReady", dice3d => { + dice3d.addSystem( + { id: "ac2d20", name: "Achtung Cthulhu 2d20" }, + true + ); + + dice3d.addColorset( + { + name: "ac2d20", + description: "Achtung Cthulhu 2d20", + category: "Colors", + foreground: "#000000", + background: "#000000", + outline: "#000000", + texture: "none", + } + ); + + dice3d.addDicePreset({ + type: "ds", + labels: [ + "systems/ac2d20/assets/dice/d1.webp", + "systems/ac2d20/assets/dice/d2.webp", + "systems/ac2d20/assets/dice/d3.webp", + "systems/ac2d20/assets/dice/d4.webp", + "systems/ac2d20/assets/dice/d5.webp", + "systems/ac2d20/assets/dice/d6.webp", + ], + system: "ac2d20", + colorset: "ac2d20", + }); }); diff --git a/system/fonts/AC-Cthulhu-Icons.eot b/system/assets/fonts/AC-Cthulhu-Icons.eot similarity index 100% rename from system/fonts/AC-Cthulhu-Icons.eot rename to system/assets/fonts/AC-Cthulhu-Icons.eot diff --git a/system/fonts/AC-Cthulhu-Icons.svg b/system/assets/fonts/AC-Cthulhu-Icons.svg similarity index 100% rename from system/fonts/AC-Cthulhu-Icons.svg rename to system/assets/fonts/AC-Cthulhu-Icons.svg diff --git a/system/fonts/AC-Cthulhu-Icons.ttf b/system/assets/fonts/AC-Cthulhu-Icons.ttf similarity index 100% rename from system/fonts/AC-Cthulhu-Icons.ttf rename to system/assets/fonts/AC-Cthulhu-Icons.ttf diff --git a/system/fonts/AC-Cthulhu-Icons.woff b/system/assets/fonts/AC-Cthulhu-Icons.woff similarity index 100% rename from system/fonts/AC-Cthulhu-Icons.woff rename to system/assets/fonts/AC-Cthulhu-Icons.woff diff --git a/system/fonts/cthulhu-icons.eot b/system/assets/fonts/cthulhu-icons.eot similarity index 100% rename from system/fonts/cthulhu-icons.eot rename to system/assets/fonts/cthulhu-icons.eot diff --git a/system/fonts/cthulhu-icons.svg b/system/assets/fonts/cthulhu-icons.svg similarity index 100% rename from system/fonts/cthulhu-icons.svg rename to system/assets/fonts/cthulhu-icons.svg diff --git a/system/fonts/cthulhu-icons.ttf b/system/assets/fonts/cthulhu-icons.ttf similarity index 100% rename from system/fonts/cthulhu-icons.ttf rename to system/assets/fonts/cthulhu-icons.ttf diff --git a/system/fonts/cthulhu-icons.woff b/system/assets/fonts/cthulhu-icons.woff similarity index 100% rename from system/fonts/cthulhu-icons.woff rename to system/assets/fonts/cthulhu-icons.woff diff --git a/system/lang/en.json b/system/lang/en.json deleted file mode 100644 index d17ae05..0000000 --- a/system/lang/en.json +++ /dev/null @@ -1,371 +0,0 @@ -{ - "AC2D20.AbilityAbbr.agi": "agi", - "AC2D20.AbilityAbbr.bra": "bra", - "AC2D20.AbilityAbbr.coo": "coo", - "AC2D20.AbilityAbbr.ins": "ins", - "AC2D20.AbilityAbbr.rea": "rea", - "AC2D20.AbilityAbbr.wil": "wil", - "AC2D20.Ability.agi": "Agility", - "AC2D20.Ability.bra": "Brawn", - "AC2D20.Ability.coo": "Coordination", - "AC2D20.Ability.ins": "Insight", - "AC2D20.Ability.rea": "Reason", - "AC2D20.Ability.wil": "Will", - "AC2D20.EffectCreate": "Create Effect", - "AC2D20.EffectDelete": "Delete Effect", - "AC2D20.EffectEdit": "Edit Effect", - "AC2D20.EffectToggle": "Toggle Effect", - "AC2D20.equipped": "Equipped", - "AC2D20.STRESS": { - "current": "Current Stress", - "stress": "Stress", - "max": "Max Stress" - }, - "AC2D20.OTHER": "Other", - "AC2D20.RANGE": { - "reach": "Reach", - "close": "Close", - "medium": "Medium", - "long": "Long", - "extreme": "Extreme" - }, - "AC2D20.RESISTANCE": { - "armor": "Armor", - "courage": "Courage", - "fatigue": "Fatigue", - "resistance": "Resistance" - }, - "AC2D20.SKILL": { - "ACADEMIA": "Academia", - "ATHLETICS": "Athletics", - "ENGINEERING": "Engineering", - "FIGHTING": "Fighting", - "MEDICINE": "Medicine", - "OBSERVATION": "Observation", - "PERSUASION": "Persuasion", - "RESILIENCE": "Resilience", - "STEALTH": "Stealth", - "SURVIVAL": "Survival", - "TACTICS": "Tactics", - "VEHICLES": "Vehicles" - }, - "AC2D20.FOCUS": { - "Art": "Art", - "Cryptography": "Cryptography", - "Finance": "Finance", - "History": "History", - "Linguistics": "Linguistics", - "Occultism": "Occultism", - "Science": "Science", - "Climbing": "Climbing", - "Lifting": "Lifting", - "Physical Training": "Physical Training", - "Running": "Running", - "Swimming": "Swimming", - "Throwing": "Throwing", - "Architecture": "Architecture", - "Combat Engineering": "Combat Engineering", - "Electronics": "Electronics", - "Explosives": "Explosives", - "Mechanical Engineering": "Mechanical Engineering", - "Close Quarters": "Close Quarters", - "Handguns": "Handguns", - "Hand-to-Hand": "Hand-to-Hand", - "Heavy Weapons": "Heavy Weapons", - "Melee Weapons": "Melee Weapons", - "Threat Awareness": "Threat Awareness", - "Exotic": "Exotic", - "First Aid": "First Aid", - "Infectious Diseases": "Infectious Diseases", - "Pharmacology": "Pharmacology", - "Psychiatry": "Psychiatry", - "Rifles": "Rifles", - "Surgery": "Surgery", - "Toxicology": "Toxicology", - "Hearing": "Hearing", - "Instincts": "Instincts", - "Sight": "Sight", - "Smell and Taste": "Smell and Taste", - "Charm": "Charm", - "Innuendo": "Innuendo", - "Intimidation": "Intimidation", - "Negotiation": "Negotiation", - "Rhetoric": "Rhetoric", - "Deceive": "Deceive", - "Invocation": "Invocation", - "Fortitude": "Fortitude", - "Discipline": "Discipline", - "Immunity": "Immunity", - "Camouflage": "Camouflage", - "Disguise": "Disguise", - "Rural Stealth": "Rural Stealth", - "Urban Stealth": "Urban Stealth", - "Animal Handling": "Animal Handling", - "Foraging": "Foraging", - "Hunting": "Hunting", - "Mysticism": "Mysticism", - "Orienteering": "Orienteering", - "Tracking": "Tracking", - "Air Force": "Air Force", - "Army": "Army", - "Covert Operations": "Covert Operations", - "Leadership": "Leadership", - "Navy": "Navy", - "Technical Projects": "Technical Projects", - "Cars": "Cars", - "Motorcycles": "Motorcycles", - "Heavy Vehicles": "Heavy Vehicles", - "Tanks": "Tanks", - "Aircraft": "Aircraft", - "Watercraft": "Watercraft" - }, - "AC2D20.SPELL": { - "SpellTypes": { - "ins": "Traditional", - "rea": "Researcher", - "wil": "Dabbler" - } - }, - "AC2D20.TEMPLATES": { - "Salvo": "Salvo", - "Resistance": "Resistance", - "Qualities": "Qualities", - "SkillFocus": "Skill Focus", - "Resources": "Resources", - "Restriction": "Restriction", - "SpecialRule": "SpecialRule", - "SpecialRules": "Special Rules", - "Power": "Power", - "Size": "Size", - "speed": "Speed", - "bonus": "Bonus", - "scale": "Scale", - "equipped": "equipped", - "SizeLevels": { - "Trivial": "Trivial", - "Minor": "Minor", - "Major": "Major" - }, - "Abilities": "Abilities", - "Difficulty": "Difficulty", - "Diff": "Diff", - "Cost": "Cost", - "SpellType": "Type", - "Talents": "Talents", - "Spells": "Spells", - "Spells_Rituals": "Spells And Rituals", - "Ammo": "Ammo", - "Attacks": "ATTACKS", - "Attribute": "Attribute", - "Attributes": "Attributes", - "Attr": "Attr.", - "Compl": "Compl.", - "Complications": "Complications", - "Conditions": "Conditions", - "Create_Ammo": "Create Ammo", - "Create_Special_Rule": "Create Special Rule", - "Create_Weapon": "Create Weapon", - "current": "current", - "CostEffects": "Cost Effects", - "DAMAGE": "DAMAGE", - "DAMAGE_EFFECTS": "DAMAGE EFFECTS", - "DAMAGE_TYPE": "DAMAGE TYPE", - "Data": "Data", - "Default_Attribute": "Default Attribute", - "DEFENSE": "DEFENSE", - "Delete": "Delete", - "Delete_Item": "Delete Item", - "DERIVED": "DERIVED", - "Description": "Description", - "Duration": "Duration", - "Dur": "Dur", - "Edit_Item": "Edit Item", - "Effect": "Effect", - "Effects": "Effects", - "Encumbrance": "Encumbrance", - "Encumbrance_Level": "Encumbrance Level", - "Encumbered": "ENCUMBERED", - "ENG": "ENG", - "FAVORITE_WEAPONS": "FAVORITE WEAPONS", - "FIRE_RATE": "FIRE RATE", - "Gear": "Gear", - "GENERAL": "GENERAL", - "Healthy": "Healthy", - "HP_Healed": "HP Healed", - "INITIATIVE": "INITIATIVE", - "INJURIES": "Injuries", - "Issue": "Issue", - "Keywords": "Keywords", - "lbs": "lbs", - "Learned": "Learned", - "Luck": "Luck", - "MAX": "MAX", - "max": "max", - "MAX_PARTY_MOMENTUM": "Max Momentum", - "MELEE_BONUS": "MELEE BONUS", - "MELEE_DAMAGE": "MELEE DAMAGE", - "Mod_Type": "Mod Type", - "MODULES": "MODULES", - "Name_Prefix": "Name Prefix", - "GM_MOMENTUM": "GM Threat", - "PARTY_MOMENTUM": "Party Momentum", - "PHYS": "PHYS", - "Points": "Points", - "POISON": "POISON", - "RANGE": "Range", - "Rank": "Rank", - "Ranks_current_maximum": "Ranks [current/maximum]", - "Re_roll": "Re-roll", - "Requirements": "Requirements", - "RESISTANCES": "RESISTANCES", - "Resistances": "Resistances", - "Roll_Formula": "Roll Formula", - "Skill": "Skill", - "Skill_Focus": "Skill Focus", - "Skill_Value": "Skill Value", - "Skills": "Skills", - "Source": "Source", - "Status": "Status", - "Successes": "Successes", - "Focus": "Focus", - "TN": "TN", - "Total": "Total", - "Use_Agility": "Use Agility", - "Use_Brawn": "Use Brawn", - "Use_Coordination": "Use Coordination", - "Use_Insight": "Use Insight", - "Use_Reason": "Use Reason", - "Use_Will": "Use Will", - "Weapon_Qualities": "WEAPON QUALITIES", - "Weapon_Type": "Weapon Type", - "Weapons": "Weapons", - "Ritual": "Ritual", - "ritual_stress": "Ritual Stress", - "ritual_steps": "Ritual Steps", - "ritual_resistance": "Resistance", - "ritual_requirements": "Requirements", - "fortune": "Fortune", - "Personal_Truth_Scars": "Personal Truths & Scars", - "Truths": "Truths", - "rating": "Rating", - "skill_focus": "Skill/Focus", - "AddFocus": "Add Focus" - }, - "AC2D20.UI": { - "Add": "Add", - "CarryWeight": "Carry Weight", - "Cost": "Cost", - "Damage": "Damage", - "favorite": "Favorite", - "INVENTORY": "Inventory", - "Name": "Name", - "ORIGIN": "ORIGIN", - "OTHER": "Other", - "Quantity": "Quantity", - "Rarity": "Rarity", - "SPECIAL_RULE": "Special Rule", - "stashed": "Stashed", - "Type": "Type", - "UNSORTED": "Unsorted", - "Weight": "Weight" - }, - "AC2D20.WEAPONS": { - "qualities": "Qualities", - "type": "Weapon Type", - "damageEffect": { - "area": "Area", - "backlash": "Backlash", - "drain": "Drain", - "intense": "Intense", - "persistent": "Persistent", - "piercing": "Piercing", - "snare": "Snare", - "stun": "Stun", - "vicious": "Vicious" - }, - "damageType": { - "energy": "Energy", - "physical": "Physical", - "poison": "Poison", - "radiation": "Radiation" - }, - "weaponQuality": { - "accurate": "Accurate", - "closeQuarters": "Close Quarters", - "cumbersome": "Cumbersome", - "debilitating": "Debilitating", - "escalation": "Escalation", - "giant-killer": "Giant-Killer", - "heavy": "Heavy", - "hidden": "Hidden", - "inaccurate": "Inaccurate", - "indirect": "Indirect", - "munition": "Munition", - "parrying": "Parrying", - "reliable": "Reliable", - "subtle": "Subtle", - "unreliable": "Unreliable", - "bane": "Bane", - "hunger": "Hunger" - }, - "weaponTypes": { - "Melee": "Melee", - "Ranged": "Ranged", - "Mental": "Mental", - "agi": "Melee", - "coo": "Ranged", - "wil": "Mental" - } - }, - "AC2D20.ARMOR": { - "qualities": { - "heavy": "Heavy", - "uncomfortable": "Uncomfortable", - "shield": "Shield" - } - }, - "AC2D20.VEHICLES.QUALITIES": { - "cargo": "Cargo", - "cumbersome": "Cumbersome", - "enclosed": "Enclosed", - "exposed": "Exposed", - "highPerformance": "High Performance", - "singleSeat:": "Single Seat", - "tough": "Tough" - }, - "TYPES.Actor.character": "Character", - "TYPES.Actor.npc": "NPC", - "ACTOR.NpcType": { - "Trooper": "Trooper", - "Lieutenant": "Lieutenant", - "Nemesis": "Nemesis" - }, - "TYPES.Actor.vehicle": "Vehicle", - "ACTOR.Vehicle": { - "Passengers": "Passengers", - "Cover": "Cover", - "Impact": "Impact" - }, - "TYPES.Item.armor": "Armor", - "TYPES.Item.talent": "Talent", - "TYPES.Item.spell": "Spell", - "TYPES.Item.skill": "Skill", - "TYPES.Item.skillkit": "Skill Kit", - "TYPES.Item.equipment": "Equipment", - "TYPES.Item.special_rule": "Special Rule", - "TYPES.Item.weapon": "Weapon", - "AC2D20.Spellcasting":{ - "SpellcastingType":"Spellcasting Type", - "traditional":"traditional", - "researcher":"researcher", - "dabbler":"dabbler" - }, - "AC2D20.Combat": { - "CombatantsTurnDone": "Turn Completed", - "CombatantsTurnNotDone": "Turn Not Completed", - "CombatEndMomentumPoolDecremented": "Momentum Pool Decremented at End of Combat", - "CombatHasNotStarted": "Combat Has Not Started", - "CombatRoundMomentumPoolDecremented": "Momentum Pool Decremented at Start of New Round", - "ToggleCombatantsTurnDone": "Toggle Turn Completed" - } -} diff --git a/system/lang/es.json b/system/lang/es.json deleted file mode 100644 index bf52532..0000000 --- a/system/lang/es.json +++ /dev/null @@ -1,357 +0,0 @@ -{ - "AC2D20.AbilityAbbr.agi": "agi", - "AC2D20.AbilityAbbr.bra": "mus", - "AC2D20.AbilityAbbr.coo": "coo", - "AC2D20.AbilityAbbr.ins": "pers", - "AC2D20.AbilityAbbr.rea": "raz", - "AC2D20.AbilityAbbr.wil": "vol", - "AC2D20.Ability.agi": "Agilidad", - "AC2D20.Ability.bra": "Músculo", - "AC2D20.Ability.coo": "Coordinación", - "AC2D20.Ability.ins": "Perspicacia", - "AC2D20.Ability.rea": "Razón", - "AC2D20.Ability.wil": "Voluntad", - "AC2D20.EffectCreate": "Crear Efecto", - "AC2D20.EffectDelete": "Borrar Efecto", - "AC2D20.EffectEdit": "Editar Efecto", - "AC2D20.EffectToggle": "Alternar Efecto", - "AC2D20.equipped": "Equipado", - "AC2D20.STRESS": { - "current": "Estrés actual", - "stress": "Estrés", - "max": "Estrés Máximo" - }, - "AC2D20.OTHER": "Otro", - "AC2D20.RANGE": { - "reach": "Alcance", - "close": "Corto", - "medium": "Medio", - "long": "Largo", - "extreme": "Extremo" - }, - "AC2D20.RESISTANCE": { - "armor": "Armadura", - "courage": "Coraje", - "fatigue": "Fatiga", - "resistance": "Resistencia" - }, - "AC2D20.SKILL": { - "ACADEMIA": "Académicas", - "ATHLETICS": "Atletismo", - "ENGINEERING": "Ingeniería", - "FIGHTING": "Combate", - "MEDICINE": "Medicina", - "OBSERVATION": "Observación", - "PERSUASION": "Persuasión", - "RESILIENCE": "Resiliencia", - "STEALTH": "Sigilo", - "SURVIVAL": "Supervivencia", - "TACTICS": "Tácticas", - "VEHICLES": "Vehículos" - }, - "AC2D20.FOCUS": { - "Art": "Arte", - "Cryptography": "Criptografía", - "Finance": "Finanzas", - "History": "Historia", - "Linguistics": "Linguística", - "Occultism": "Ocultismo", - "Science": "Ciencia", - "Climbing": "Escalar", - "Lifting": "Levantar", - "Physical Training": "Entrenamiento Físico", - "Running": "Correr", - "Swimming": "Nadar", - "Throwing": "Lanzar", - "Architecture": "Arquitectura", - "Combat Engineering": "Ingeniería de Combate", - "Electronics": "Electrónica", - "Explosives": "Explosivos", - "Mechanical Engineering": "Ingeniería Mecánica", - "Close Quarters": "Cercana", - "Handguns": "Pístolas", - "Hand-to-Hand": "Mano a mano", - "Heavy Weapons": "Armas Pesadas", - "Melee Weapons": "Armas de Melé", - "Threat Awareness": "Sentir el Peligro", - "Exotic": "Exoticas", - "First Aid": "Primeros Auxilios", - "Infectious Diseases": "Enfermedades Infecciosas", - "Pharmacology": "Farmacología", - "Psychiatry": "Psiquiatría", - "Rifles": "Rifles", - "Surgery": "Cirugía", - "Toxicology": "Toxicología", - "Hearing": "Escuchar", - "Instincts": "Instintos", - "Sight": "Ver", - "Smell and Taste": "Oler y Saborear", - "Charm": "Encanto", - "Innuendo": "Seducción", - "Intimidation": "Intimidación", - "Negotiation": "Negociación", - "Rhetoric": "Retórica", - "Deceive": "Engaño", - "Invocation": "Invocación", - "Fortitude": "Fortaleza Interior", - "Discipline": "Disciplina", - "Immunity": "Inmunidad", - "Camouflage": "Camuflaje", - "Disguise": "Disfraz", - "Rural Stealth": "Sigilo a campo abierto", - "Urban Stealth": "Sigilo Urbano", - "Animal Handling": "Manejo de Animales", - "Foraging": "Forrajeo", - "Hunting": "Caza", - "Mysticism": "Misticismo", - "Orienteering": "Orientación", - "Tracking": "Rastrear", - "Air Force": "Fuerza Aérea", - "Army": "Ejército", - "Covert Operations": "Operaciones Encubiertas", - "Leadership": "Liderazgo", - "Navy": "Armada", - "Technical Projects": "Proyectos Técnicos", - "Cars": "Coches", - "Motorcycles": "Motocicletas", - "Heavy Vehicles": "Vehículos Pesados", - "Tanks": "Tanques", - "Aircraft": "Vehículos Aéreos", - "Watercraft": "Vehículos Acuáticos" - }, - "AC2D20.SPELL": { - "SpellTypes": { - "ins": "Tradicional", - "rea": "Investigador", - "wil": "Aficionado" - } - }, - "AC2D20.TEMPLATES": { - "Salvo": "Salva", - "Resistance": "Resistencia", - "Qualities": "Cualidades", - "SkillFocus": "Especialidad de Habilidad", - "Resources": "Recursos", - "Restriction": "Restricción", - "SpecialRule": "Regla Especial", - "SpecialRules": "Reglas Especiales", - "Power": "Poder", - "Size": "Tamaño", - "speed": "Velocidad", - "bonus": "Bono", - "scale": "Escala", - "equipped": "Equipado", - "SizeLevels": { - "Trivial": "Trivial", - "Minor": "Menor", - "Major": "Mayor" - }, - "Abilities": "Habilidades", - "Difficulty": "Dificultad", - "Diff": "Dif", - "Cost": "Coste", - "SpellType": "Tipo", - "Talents": "Talentos", - "Spells": "Conjuros", - "Spells_Rituals": "Conjuros y Rituales", - "Ammo": "Munición", - "Attacks": "ATAQUES", - "Attribute": "Atributo", - "Attributes": "Atributos", - "Attr": "Atri.", - "Compl": "Compl.", - "Complications": "Complicaciones", - "Conditions": "Condiciones", - "Create_Ammo": "Crear Munición", - "Create_Special_Rule": "Crear Regla Especial", - "Create_Weapon": "Crear Arma", - "current": "actual", - "CostEffects": "Coste de Efectos", - "DAMAGE": "DAÑO", - "DAMAGE_EFFECTS": "EFECTOS DE DAÑO", - "DAMAGE_TYPE": "TIPO DE DAÑO", - "Data": "Datos", - "Default_Attribute": "Atributo por Defecto", - "DEFENSE": "DEFENSA", - "Delete": "Borrar", - "Delete_Item": "Borrar Objeto", - "DERIVED": "DERIVADO", - "Description": "Descripción", - "Duration": "Duración", - "Dur": "Dur", - "Edit_Item": "Editar Objeto", - "Effect": "Efecto", - "Effects": "Efectos", - "Encumbrance": "Carga", - "Encumbrance_Level": "Nivel de Carga", - "Encumbered": "SOBRECARGADO", - "ENG": "ENG", - "FAVORITE_WEAPONS": "ARMAS FAVORITAS", - "FIRE_RATE": "CADENCIA DE FUEG", - "Gear": "Equipo", - "GENERAL": "GENERAL", - "Healthy": "Saludable", - "HP_Healed": "PV Curados", - "INITIATIVE": "INICIATIVA", - "INJURIES": "Heridas", - "Issue": "Problema", - "Keywords": "Palabras Clave", - "lbs": "lbs", - "Learned": "Aprendida", - "Luck": "Suerte", - "MAX": "MAX", - "max": "max", - "MAX_PARTY_MOMENTUM": "Inercia Máxima", - "MELEE_BONUS": "BONO MELÉ", - "MELEE_DAMAGE": "DAÑO MELÉ", - "Mod_Type": "Tipo Mod", - "MODULES": "MODULOS", - "Name_Prefix": "Prefijo del Nombre", - "GM_MOMENTUM": "Amenaza DJ", - "PARTY_MOMENTUM": "Inercia Grupo", - "PHYS": "FIS", - "Points": "Puntos", - "POISON": "VENENO", - "RANGE": "Alcance", - "Rank": "Rango", - "Ranks_current_maximum": "Rangos [actual/máximo]", - "Re_roll": "Tirar de Nuevo", - "Requirements": "Requerimientos", - "RESISTANCES": "RESISTENCIAS", - "Resistances": "Resistencias", - "Roll_Formula": "Fórmula de Tirada", - "Skill": "Habilidad", - "Skill_Focus": "Especialidad de Habilidad", - "Skill_Value": "Valor de Habilidad", - "Skills": "Habilidades", - "Source": "Origen", - "Status": "Estatus", - "Successes": "Éxitos", - "Focus": "Especialización", - "TN": "TN", - "Total": "Total", - "Use_Agility": "Usa Agilidad", - "Use_Brawn": "Usa Músculo", - "Use_Coordination": "Usa Coordinación", - "Use_Insight": "Usa Perspicacia", - "Use_Reason": "Usa Razón", - "Use_Will": "Usa Voluntad", - "Weapon_Qualities": "CUALIDADES DE ARMA", - "Weapon_Type": "Tipo de Arma", - "Weapons": "Armas", - "Ritual": "Ritual", - "ritual_stress": "Estrés Ritual", - "ritual_steps": "Fases del Ritual", - "ritual_resistance": "Resistencia", - "ritual_requirements": "Requerimientos", - "fortune": "Fortuna", - "Personal_Truth_Scars": "Verdades Personales & Cicatrices", - "Truths": "Verdades", - "rating": "Valor", - "skill_focus": "Habilidad/Especialidad", - "AddFocus": "Añadir Especialidad" - }, - "AC2D20.UI": { - "Add": "Añadir", - "CarryWeight": "Peso Acarreado", - "Cost": "Coste", - "Damage": "Daño", - "favorite": "Favorito", - "INVENTORY": "Inventario", - "Name": "Nombre", - "ORIGIN": "ORIGEN", - "OTHER": "Otro", - "Quantity": "Cantidad", - "Rarity": "Rareza", - "SPECIAL_RULE": "Regla Especial", - "stashed": "Reservado", - "Type": "Tipo", - "UNSORTED": "Desordenado", - "Weight": "Peso" - }, - "AC2D20.WEAPONS": { - "qualities": "Cualidades", - "type": "Tipo de Arma", - "damageEffect": { - "area": "Área", - "backlash": "Retroceso", - "drain": "Drenar", - "intense": "Intensa", - "persistent": "Persistente", - "piercing": "Perforante", - "snare": "Trampa", - "stun": "Aturdidora", - "vicious": "Feroz" - }, - "damageType": { - "energy": "Enegía", - "physical": "Física", - "poison": "Veneno", - "radiation": "Radiación" - }, - "weaponQuality": { - "accurate": "Precisa", - "closeQuarters": "Cercana", - "cumbersome": "Incómoda", - "debilitating": "Debilitante", - "escalation": "Recrudecimiento", - "giant-killer": "Mata-Gigantes", - "heavy": "Pesada", - "hidden": "Oculta", - "inaccurate": "Imprecisa", - "indirect": "Indirecta", - "munition": "Munición", - "parrying": "Parada", - "reliable": "Fiable", - "subtle": "Sutil", - "unreliable": "No fiable", - "bane": "Flagelo", - "hunger": "Hambrienta" - }, - "weaponTypes": { - "Melee": "Melé", - "Ranged": "Distancia", - "Mental": "Mental", - "agi": "Melé", - "coo": "Distancia", - "wil": "Mental" - } - }, - "AC2D20.ARMOR": { - "qualities": { - "heavy": "Pesada", - "uncomfortable": "Incómoda", - "shield": "Escudo" - } - }, - "AC2D20.VEHICLES.QUALITIES": { - "cargo": "Carga", - "cumbersome": "Incómodo", - "enclosed": "Cerrado", - "exposed": "Expuesto", - "highPerformance": "Alta Eficacia", - "singleSeat:": "Asiento único", - "tough": "Duro" - }, - "ACTOR.TypeCharacter": "Personaje Jugador", - "ACTOR.TypeNpc": "PNJ", - "ACTOR.NpcType": { - "Trooper": "Tropa", - "Lieutenant": "Teniente", - "Nemesis": "Némesis" - }, - "ACTOR.TypeVehicle": "Vehículo", - "ACTOR.Vehicle": { - "Passengers": "Pasajeros", - "Cover": "Cobertura", - "Impact": "Impacto" - }, - "ITEM.TypeArmor": "Armadura", - "ITEM.TypeTalent": "Talento", - "ITEM.TypeSpell": "Conjuro", - "ITEM.TypeSkill": "Habilidad", - "ITEM.TypeSkillkit": "Kit de Habilidades", - "ITEM.TypeEquipment": "Equipo", - "ITEM.TypeSpecial_rule": "Regla Especial", - "ITEM.TypeWeapon": "Arma" -} \ No newline at end of file diff --git a/system/src/app/momentum-tracker.mjs b/system/src/app/momentum-tracker.mjs index a698388..1053268 100644 --- a/system/src/app/momentum-tracker.mjs +++ b/system/src/app/momentum-tracker.mjs @@ -1,145 +1,153 @@ export class MomentumTracker extends Application { - constructor(options = {}) { - if (MomentumTracker._instance) { - throw new Error("MomentumTracker already has an instance!!!"); - } - super(options); - MomentumTracker._instance = this; - MomentumTracker.closed = true; - this.data = {}; - } - // override - static get defaultOptions() { - return mergeObject(super.defaultOptions, { - title: "AP Tracker", - template: "systems/ac2d20/templates/ap/momentum-tracker.html", - classes: ["ac2d20", "momentum-tracker"], - id: "momentum-tracker-app", - popOut: false, - resizable: false, - width: "auto", - height: "200" - }); - } - // override - getData() { - super.getData(); - this.data["isGM"] = game.user.isGM; - this.data["partyMomentum"] = game.settings.get('ac2d20', 'partyMomentum'); - this.data["gmMomentum"] = game.settings.get('ac2d20', 'gmMomentum'); - this.data["maxMomentum"] = game.settings.get('ac2d20', 'maxMomentum'); - if(game.user.isGM) this.data["showGMMomentumToPlayers"] = true; - else this.data["showGMMomentumToPlayers"] = game.settings.get('ac2d20', 'gmMomentumShowToPlayers') - if(game.user.isGM) this.data["maxAppShowToPlayers"] = true; - else this.data["maxAppShowToPlayers"] = game.settings.get('ac2d20', 'maxAppShowToPlayers') - return this.data; - } - - static renderApTracker() { - if (MomentumTracker._instance) - MomentumTracker._instance.render(true); - } - - activateListeners(html) { - super.activateListeners(html); - - if (MomentumTracker.closed) { - html.find('.ap-resource.maxMomentum-box').css("display", "none"); - } - - html.find('.ap-input').change(ev => { - const type = $(ev.currentTarget).parents('.ap-resource').attr('data-type'); - const value = ev.target.value; - MomentumTracker.setAP(type, value); - }); - - html.find('.ap-add, .ap-sub').click(ev => { - const type = $(ev.currentTarget).parents('.ap-resource').attr('data-type'); - const change = $(ev.currentTarget).hasClass('ap-add') ? 1 : -1; - let currentValue = game.settings.get('ac2d20', type); - let maxMomentum = game.settings.get('ac2d20', 'maxMomentum'); - if (parseInt(currentValue) < maxMomentum || parseInt(currentValue) > 0) { - let newValue = parseInt(currentValue) + change; - MomentumTracker.setAP(type, newValue); - } - - }); - - html.find('.toggle-maxAp').click(ev => { - html.find('.ap-resource.maxMomentum-box').slideToggle("fast", function () { MomentumTracker.closed = !MomentumTracker.closed }); - }) - } - - static async adjustAP(type, diff) { - diff = Math.round(diff); - - if (!game.user.isGM) { - game.socket.emit('system.ac2d20', { - operation: 'adjustAP', - data: { diff, type }, - }); - return; - } - - let momentum = game.settings.get('ac2d20', type); - momentum += diff; - - this.setAP(type, momentum); - } - - static async setAP(type, value) { - value = Math.round(value); - if (!game.user.isGM) { - game.socket.emit('system.ac2d20', { - operation: 'setAP', - data: { 'value': value, 'type': type }, - }); - return; - } - - let maxMomentum = game.settings.get('ac2d20', 'maxMomentum'); - let partyMomentum = game.settings.get('ac2d20', 'partyMomentum'); - if (partyMomentum > value && type === 'maxMomentum') { - await game.settings.set('ac2d20', 'maxMomentum', value); - await game.settings.set('ac2d20', 'partyMomentum', value); - MomentumTracker.renderApTracker(); - game.socket.emit('system.ac2d20', { operation: 'updateAP' }); - return; - } - - if (value > maxMomentum && type === 'partyMomentum') { - await game.settings.set('ac2d20', type, maxMomentum); - MomentumTracker.renderApTracker(); - } else if (value < 0) { - await game.settings.set('ac2d20', type, 0); - MomentumTracker.renderApTracker(); - } else { - await game.settings.set('ac2d20', type, value); - MomentumTracker.renderApTracker(); - } - - // emit socket event for the players to update - game.socket.emit('system.ac2d20', { operation: 'updateAP' }); - } - - static updateAP() { - MomentumTracker.renderApTracker(); - } + constructor(options = {}) { + if (MomentumTracker._instance) { + throw new Error("MomentumTracker already has an instance!!!"); + } + super(options); + MomentumTracker._instance = this; + MomentumTracker.closed = true; + this.data = {}; + } + + // override + static get defaultOptions() { + return mergeObject(super.defaultOptions, { + title: "AP Tracker", + template: "systems/ac2d20/templates/ap/momentum-tracker.hbs", + classes: ["ac2d20", "momentum-tracker"], + id: "momentum-tracker-app", + popOut: false, + resizable: false, + width: "auto", + height: "200", + }); + } + + // override + getData() { + super.getData(); + this.data.isGM = game.user.isGM; + this.data.partyMomentum = game.settings.get("ac2d20", "partyMomentum"); + this.data.gmMomentum = game.settings.get("ac2d20", "gmMomentum"); + this.data.maxMomentum = game.settings.get("ac2d20", "maxMomentum"); + if (game.user.isGM) this.data.showGMMomentumToPlayers = true; + else this.data.showGMMomentumToPlayers = game.settings.get("ac2d20", "gmMomentumShowToPlayers"); + if (game.user.isGM) this.data.maxAppShowToPlayers = true; + else this.data.maxAppShowToPlayers = game.settings.get("ac2d20", "maxAppShowToPlayers"); + return this.data; + } + + static renderApTracker() { + if (MomentumTracker._instance) MomentumTracker._instance.render(true); + } + + activateListeners(html) { + super.activateListeners(html); + + if (MomentumTracker.closed) { + html.find(".ap-resource.maxMomentum-box").css("display", "none"); + } + + html.find(".ap-input").change(ev => { + const type = $(ev.currentTarget).parents(".ap-resource").attr("data-type"); + const value = ev.target.value; + MomentumTracker.setAP(type, value); + }); + + html.find(".ap-add, .ap-sub").click(ev => { + const type = $(ev.currentTarget).parents(".ap-resource").attr("data-type"); + const change = $(ev.currentTarget).hasClass("ap-add") ? 1 : -1; + let currentValue = game.settings.get("ac2d20", type); + let maxMomentum = game.settings.get("ac2d20", "maxMomentum"); + if (parseInt(currentValue) < maxMomentum || parseInt(currentValue) > 0) { + let newValue = parseInt(currentValue) + change; + MomentumTracker.setAP(type, newValue); + } + + }); + + html.find(".toggle-maxAp").click(ev => { + html.find(".ap-resource.maxMomentum-box").slideToggle("fast", function() { + MomentumTracker.closed = !MomentumTracker.closed; + }); + }); + } + + static async adjustAP(type, diff) { + diff = Math.round(diff); + + if (!game.user.isGM) { + game.socket.emit("system.ac2d20", { + operation: "adjustAP", + data: { diff, type }, + }); + return; + } + + let momentum = game.settings.get("ac2d20", type); + momentum += diff; + + this.setAP(type, momentum); + } + + static async setAP(type, value) { + value = Math.round(value); + if (!game.user.isGM) { + game.socket.emit("system.ac2d20", { + operation: "setAP", + data: { value: value, type: type }, + }); + return; + } + + let maxMomentum = game.settings.get("ac2d20", "maxMomentum"); + let partyMomentum = game.settings.get("ac2d20", "partyMomentum"); + if (partyMomentum > value && type === "maxMomentum") { + await game.settings.set("ac2d20", "maxMomentum", value); + await game.settings.set("ac2d20", "partyMomentum", value); + MomentumTracker.renderApTracker(); + game.socket.emit("system.ac2d20", { operation: "updateAP" }); + return; + } + + if (value > maxMomentum && type === "partyMomentum") { + await game.settings.set("ac2d20", type, maxMomentum); + MomentumTracker.renderApTracker(); + } + else if (value < 0) { + await game.settings.set("ac2d20", type, 0); + MomentumTracker.renderApTracker(); + } + else { + await game.settings.set("ac2d20", type, value); + MomentumTracker.renderApTracker(); + } + + // emit socket event for the players to update + game.socket.emit("system.ac2d20", { operation: "updateAP" }); + } + + static updateAP() { + MomentumTracker.renderApTracker(); + } } Hooks.once("ready", () => { - if (MomentumTracker._instance) return; - let ap = new MomentumTracker(); - MomentumTracker.renderApTracker(); - game.socket.on("system.ac2d20", (ev) => { - if (ev.operation === "adjustAP") { - if (game.user.isGM) - MomentumTracker.adjustAP(ev.data.type, ev.data.diff); - } - if (ev.operation === "setAP") { - if (game.user.isGM) - MomentumTracker.setAP(ev.data.type, ev.data.value); - } - if (ev.operation === "updateAP") MomentumTracker.updateAP(); - }); + if (MomentumTracker._instance) return; + + new MomentumTracker(); + + MomentumTracker.renderApTracker(); + + game.socket.on("system.ac2d20", ev => { + if (ev.operation === "adjustAP") { + if (game.user.isGM) MomentumTracker.adjustAP(ev.data.type, ev.data.diff); + } + + if (ev.operation === "setAP") { + if (game.user.isGM) MomentumTracker.setAP(ev.data.type, ev.data.value); + } + + if (ev.operation === "updateAP") MomentumTracker.updateAP(); + }); }); diff --git a/system/src/combat/combat-tracker.mjs b/system/src/combat/combat-tracker.mjs index fdb1008..2f1fa82 100644 --- a/system/src/combat/combat-tracker.mjs +++ b/system/src/combat/combat-tracker.mjs @@ -1,82 +1,82 @@ export default class CombatTracker2d20 extends CombatTracker { - static get defaultOptions() { - return { - ...super.defaultOptions, - template: 'systems/ac2d20/templates/combat/combat-tracker.html', - }; - } - - activateListeners(html) { - const tracker = html.find('#combat-tracker'); - const combatants = tracker.find('.combatant'); - - html.find('.ac-combatant-control').click( - ev => this._onACCombatantControl(ev) - ); - - combatants.click(this._onACCombatantMouseDown.bind(this)); - - super.activateListeners(html); - } - - async getData(options) { - const context = await super.getData(options); - - const combat = this.viewed; - for (const turn of context.turns) { - const combatantsTurnDone = combat.combatantsTurnDone; - turn.turnDone = combatantsTurnDone[turn.id] ?? false; - } - - return context; - } - - async _onACCombatantControl(event) { - event.preventDefault(); - event.stopPropagation(); - - if (!game.user.isGM) return; - - if (!this.viewed.started) { - ui.notifications.warn( - game.i18n.localize('AC2D20.Combat.CombatHasNotStarted') - ); - return; - } - - const btn = event.currentTarget; - const li = btn.closest('.combatant'); - const combatant = this.viewed.combatants.get(li.dataset.combatantId); - - if (combatant.isOwner) { - this.viewed.toggleTurnDone(combatant.id); - } - } - - async _onACCombatantMouseDown(event) { - event.preventDefault(); - if (game.user.isGM && this.viewed.started) { - const li = event.currentTarget; - const combatantId = li.dataset.combatantId; - - const combat = this.viewed; - - const currentTurn = combat.turn ?? -1; - - let newTurn = currentTurn; - - for (let [i, turn] of combat.turns.entries()) { - if (turn.isDefeated) continue; - if (turn.id === combatantId) { - newTurn = i; - break; - } - } - - if (newTurn !== currentTurn) { - combat.setTurn(newTurn); - } - } - } + static get defaultOptions() { + return { + ...super.defaultOptions, + template: "systems/ac2d20/templates/combat/combat-tracker.hbs", + }; + } + + activateListeners(html) { + const tracker = html.find("#combat-tracker"); + const combatants = tracker.find(".combatant"); + + html.find(".ac-combatant-control").click( + ev => this._onACCombatantControl(ev) + ); + + combatants.click(this._onACCombatantMouseDown.bind(this)); + + super.activateListeners(html); + } + + async getData(options) { + const context = await super.getData(options); + + const combat = this.viewed; + for (const turn of context.turns) { + const combatantsTurnDone = combat.combatantsTurnDone; + turn.turnDone = combatantsTurnDone[turn.id] ?? false; + } + + return context; + } + + async _onACCombatantControl(event) { + event.preventDefault(); + event.stopPropagation(); + + if (!game.user.isGM) return; + + if (!this.viewed.started) { + ui.notifications.warn( + game.i18n.localize("AC2D20.Combat.CombatHasNotStarted") + ); + return; + } + + const btn = event.currentTarget; + const li = btn.closest(".combatant"); + const combatant = this.viewed.combatants.get(li.dataset.combatantId); + + if (combatant.isOwner) { + this.viewed.toggleTurnDone(combatant.id); + } + } + + async _onACCombatantMouseDown(event) { + event.preventDefault(); + if (game.user.isGM && this.viewed.started) { + const li = event.currentTarget; + const combatantId = li.dataset.combatantId; + + const combat = this.viewed; + + const currentTurn = combat.turn ?? -1; + + let newTurn = currentTurn; + + for (let [i, turn] of combat.turns.entries()) { + if (turn.isDefeated) continue; + if (turn.id === combatantId) { + newTurn = i; + break; + } + } + + if (newTurn !== currentTurn) { + combat.setTurn(newTurn); + } + } + } } diff --git a/system/src/combat/combat.mjs b/system/src/combat/combat.mjs index 4358141..b04881c 100644 --- a/system/src/combat/combat.mjs +++ b/system/src/combat/combat.mjs @@ -2,164 +2,164 @@ export default class Combat2d20 extends Combat { - constructor(options) { - super(options); - - this.flags.combatantsTurnDone = this.flags.combatantsTurnDone ?? []; - } - - get combatantsTurnDone() { - const combatantsTurnDone = this.flags.combatantsTurnDone ?? []; - return combatantsTurnDone[this.round] ?? {}; - } - - get momentumLog() { - const momentumLog = this.flags.momentumLog ?? []; - return momentumLog[this.round] ?? {}; - } - - get shouldUpdateMomentum() { - return game.settings.get( - 'ac2d20', 'combatTrackerMomentumUpdate' - ); - } - - async endCombat() { - return Dialog.confirm({ - title: game.i18n.localize('COMBAT.EndTitle'), - content: `
${game.i18n.localize('COMBAT.EndConfirmation')}
`, - yes: () => { - if (this.shouldUpdateMomentum && this.started) { - if (game.user.isGM) { - game.ac2d20.MomentumTracker.adjustAP('partyMomentum', -1); - } - else { - game.socket.emit('system.ac2d20', { - operation: 'adjustAP', - data: { diff: -1, type: 'partyMomentum' }, - }); - } - - ui.notifications.info( - game.i18n.localize('AC2D20.Combat.CombatEndMomentumPoolDecremented') - ); - } - this.delete(); - }, - }); - } - - async nextRound() { - this.turn = null; - - if (this.shouldUpdateMomentum) { - if (game.user.isGM) { - game.ac2d20.MomentumTracker.adjustAP('partyMomentum', -1); - } - else { - game.socket.emit('system.ac2d20', { - operation: 'adjustAP', - data: { diff: -1, type: 'partyMomentum' }, - }); - } - - ui.notifications.info( - game.i18n.localize('AC2D20.Combat.CombatRoundMomentumPoolDecremented') - ); - } - - let advanceTime = Math.max(this.turns.length - this.turn, 0) * CONFIG.time.turnTime; - advanceTime += CONFIG.time.roundTime; - let nextRound = this.round + 1; - - // Update the document, passing data through a hook first - const updateData = {round: nextRound, turn: this.turn}; - const updateOptions = {advanceTime, direction: 1}; - Hooks.callAll('combatRound', this, updateData, updateOptions); - return this.update(updateData, updateOptions); - } - - async rollInitiative() { - return this; - } - - async setTurn(newTurn) { - this.turn = newTurn; - - // Update the document, passing data through a hook first - const updateData = {round: this.round, turn: newTurn}; - const updateOptions = {advanceTime: CONFIG.time.turnTime, direction: 1}; - Hooks.callAll('combatTurn', this, updateData, updateOptions); - return this.update(updateData, updateOptions); - } - - setupTurns() { - // Determine the turn order and the current turn - const turns = this.combatants.contents; - - // Sort alphabetically by name first - turns.sort((a, b) => { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - }); - - // Now sort by type - turns.sort((a, b) => { - const actorA = game.actors.get(a.actorId); - const actorB = game.actors.get(b.actorId); - - if (actorA.type < actorB.type) { - return -1; - } - if (actorA.type > actorB.type) { - return 1; - } - return 0; - }); - - if ( this.turn !== null) this.turn = Math.clamped(this.turn, 0, turns.length-1); - - // Update state tracking - let c = turns[this.turn]; - this.current = { - round: this.round, - turn: this.turn, - combatantId: c ? c.id : null, - tokenId: c ? c.tokenId : null, - }; - - // Return the array of prepared turns - return this.turns = turns; - } - - async startCombat() { - const updateData = { - round: 1, - turn: 0, - 'flags.combatantsTurnDone': [], - }; - - Hooks.callAll('combatStart', this, updateData); - - return this.update(updateData); - } - - async toggleTurnDone(combatantId) { - if (!game.user.isGM) return; - if (!this.started) return; - - const combatantsTurnDone = this.combatantsTurnDone; - - const turnDone = !(combatantsTurnDone[combatantId] ?? false); - combatantsTurnDone[combatantId] = turnDone; - - this.flags.combatantsTurnDone[this.round] = combatantsTurnDone; - - return this.update({'flags.combatantsTurnDone': this.flags.combatantsTurnDone}); - } + constructor(options) { + super(options); + + this.flags.combatantsTurnDone = this.flags.combatantsTurnDone ?? []; + } + + get combatantsTurnDone() { + const combatantsTurnDone = this.flags.combatantsTurnDone ?? []; + return combatantsTurnDone[this.round] ?? {}; + } + + get momentumLog() { + const momentumLog = this.flags.momentumLog ?? []; + return momentumLog[this.round] ?? {}; + } + + get shouldUpdateMomentum() { + return game.settings.get( + "ac2d20", "combatTrackerMomentumUpdate" + ); + } + + async endCombat() { + return Dialog.confirm({ + title: game.i18n.localize("COMBAT.EndTitle"), + content: `${game.i18n.localize("COMBAT.EndConfirmation")}
`, + yes: () => { + if (this.shouldUpdateMomentum && this.started) { + if (game.user.isGM) { + game.ac2d20.MomentumTracker.adjustAP("partyMomentum", -1); + } + else { + game.socket.emit("system.ac2d20", { + operation: "adjustAP", + data: { diff: -1, type: "partyMomentum" }, + }); + } + + ui.notifications.info( + game.i18n.localize("AC2D20.Combat.CombatEndMomentumPoolDecremented") + ); + } + this.delete(); + }, + }); + } + + async nextRound() { + this.turn = null; + + if (this.shouldUpdateMomentum) { + if (game.user.isGM) { + game.ac2d20.MomentumTracker.adjustAP("partyMomentum", -1); + } + else { + game.socket.emit("system.ac2d20", { + operation: "adjustAP", + data: { diff: -1, type: "partyMomentum" }, + }); + } + + ui.notifications.info( + game.i18n.localize("AC2D20.Combat.CombatRoundMomentumPoolDecremented") + ); + } + + let advanceTime = Math.max(this.turns.length - this.turn, 0) * CONFIG.time.turnTime; + advanceTime += CONFIG.time.roundTime; + let nextRound = this.round + 1; + + // Update the document, passing data through a hook first + const updateData = {round: nextRound, turn: this.turn}; + const updateOptions = {advanceTime, direction: 1}; + Hooks.callAll("combatRound", this, updateData, updateOptions); + return this.update(updateData, updateOptions); + } + + async rollInitiative() { + return this; + } + + async setTurn(newTurn) { + this.turn = newTurn; + + // Update the document, passing data through a hook first + const updateData = {round: this.round, turn: newTurn}; + const updateOptions = {advanceTime: CONFIG.time.turnTime, direction: 1}; + Hooks.callAll("combatTurn", this, updateData, updateOptions); + return this.update(updateData, updateOptions); + } + + setupTurns() { + // Determine the turn order and the current turn + const turns = this.combatants.contents; + + // Sort alphabetically by name first + turns.sort((a, b) => { + if (a.name < b.name) { + return -1; + } + if (a.name > b.name) { + return 1; + } + return 0; + }); + + // Now sort by type + turns.sort((a, b) => { + const actorA = game.actors.get(a.actorId); + const actorB = game.actors.get(b.actorId); + + if (actorA.type < actorB.type) { + return -1; + } + if (actorA.type > actorB.type) { + return 1; + } + return 0; + }); + + if ( this.turn !== null) this.turn = Math.clamped(this.turn, 0, turns.length-1); + + // Update state tracking + let c = turns[this.turn]; + this.current = { + round: this.round, + turn: this.turn, + combatantId: c ? c.id : null, + tokenId: c ? c.tokenId : null, + }; + + // Return the array of prepared turns + return this.turns = turns; + } + + async startCombat() { + const updateData = { + "round": 1, + "turn": 0, + "flags.combatantsTurnDone": [], + }; + + Hooks.callAll("combatStart", this, updateData); + + return this.update(updateData); + } + + async toggleTurnDone(combatantId) { + if (!game.user.isGM) return; + if (!this.started) return; + + const combatantsTurnDone = this.combatantsTurnDone; + + const turnDone = !(combatantsTurnDone[combatantId] ?? false); + combatantsTurnDone[combatantId] = turnDone; + + this.flags.combatantsTurnDone[this.round] = combatantsTurnDone; + + return this.update({"flags.combatantsTurnDone": this.flags.combatantsTurnDone}); + } } diff --git a/system/src/documents/actor.mjs b/system/src/documents/actor.mjs index 3469d4d..d954056 100644 --- a/system/src/documents/actor.mjs +++ b/system/src/documents/actor.mjs @@ -1,36 +1,43 @@ /** - * Extend the base Actor document by defining a custom roll data structure which is ideal for the Simple system. + * Extend the base Actor document by defining a custom roll data structure which + * is ideal for the Simple system. * @extends {Actor} */ export class ACActor extends Actor { - /** @override */ - prepareData() { - super.prepareData(); - } - - /** @override */ - prepareBaseData() { - // Data modifications in this step occur before processing embedded - // documents or derived data. - - // Carry capacity - let carryCapacity = 6; - if(this.system.attributes.bra.value < 9){ - carryCapacity = 6 - }else if(this.system.attributes.bra.value == 9){ - carryCapacity = 7 - } - else if(this.system.attributes.bra.value == 10 || this.system.attributes.bra.value == 11){ - carryCapacity = 8 - }else{ - carryCapacity = 9 - } - this.system.carryCapacity.value = parseInt(carryCapacity) - } - - /** + /** @override */ + prepareData() { + super.prepareData(); + } + + /** @override */ + prepareBaseData() { + // Data modifications in this step occur before processing embedded + // documents or derived data. + + // Carry capacity + const brawn = this.system.attributes.bra.value; + + let carryCapacity = 6; + + if (brawn < 9) { + carryCapacity = 6; + } + else if (brawn === 9) { + carryCapacity = 7; + } + else if (brawn === 10 || brawn === 11) { + carryCapacity = 8; + } + else if (brawn >= 12) { + carryCapacity = 9; + } + + this.system.carryCapacity.value = carryCapacity; + } + + /** * @override * Augment the basic actor data with additional dynamic data. Typically, * you'll want to handle most of your calculated/derived data in this step. @@ -39,108 +46,133 @@ export class ACActor extends Actor { * available both inside and outside of character sheets (such as if an actor * is queried and has a roll executed directly from it). */ - prepareDerivedData() { - // Make separate methods for each Actor type (character, npc, etc.) to keep - // things organized. - this._prepareCharacterData(this); - this._prepareNpcData(this); - } - - /** + prepareDerivedData() { + // Make separate methods for each Actor type (character, npc, etc.) to keep + // things organized. + this._prepareCharacterData(this); + this._prepareNpcData(this); + } + + /** * Prepare Character type specific data */ - _prepareCharacterData(actorData) { - if (this.type !== 'character') return; - } + _prepareCharacterData(actorData) { + // if (this.type !== "character") return; + } - /** + /** * Prepare NPC type specific data. */ - _prepareNpcData(actorData) { - if (this.type !== 'npc') return; - } + _prepareNpcData(actorData) { + // if (this.type !== "npc") return; + } - /** + /** * Override getRollData() that's supplied to rolls. */ - getRollData() { - const data = super.getRollData(); - // Prepare character roll data. - this._getCharacterRollData(data); - this._getNpcRollData(data); - return data; - } - - /** + getRollData() { + const data = super.getRollData(); + // Prepare character roll data. + this._getCharacterRollData(data); + this._getNpcRollData(data); + return data; + } + + /** * Prepare character roll data. */ - _getCharacterRollData(data) { - if (this.type !== 'character') return; - // Copy the ability scores to the top level, so that rolls can use - // formulas like `@bra.value + 4`. - if (data.attributes) { - for (let [k, v] of Object.entries(data.attributes)) { - data[k] = foundry.utils.deepClone(v); - } - } - } - - getComplicationFromInjuries() { - const injuries = [this.system.injuries.injury0, this.system.injuries.injury1, this.system.injuries.injury2] - let inj = injuries.filter((_i) => { - return (_i.text != "" && !_i.treated) - }) - return inj.length; - } - - /** + _getCharacterRollData(data) { + if (this.type !== "character") return; + // Copy the ability scores to the top level, so that rolls can use + // formulas like `@bra.value + 4`. + if (data.attributes) { + for (let [k, v] of Object.entries(data.attributes)) { + data[k] = foundry.utils.deepClone(v); + } + } + } + + getComplicationFromInjuries() { + const injuries = [ + this.system.injuries.injury0, + this.system.injuries.injury1, + this.system.injuries.injury2, + ]; + + let inj = injuries.filter(_i => { + return (_i.text !== "" && !_i.treated); + }); + + return inj.length; + } + + /** * Prepare NPC roll data. */ - _getNpcRollData(data) { - if (this.type !== 'npc') return; - // Process additional NPC data here. - } - - async _preCreate(data, options, user) { - await super._preCreate(data, options, user); - // set icon based on actor type - if(data.img == undefined){ - let ico = `systems/ac2d20/assets/doc-icons/${this.type}.svg`; - this.updateSource({ 'img': ico }); - } - // Setup Tokens - if (this.type === 'character') { - this.prototypeToken.updateSource({ actorLink: true, sight: { enabled: true }, disposition: 1 }) - } - if (this.type === 'npc') { - this.prototypeToken.updateSource({ sight: { enabled: true }, disposition: -1 }) - } - if (this.type === 'vehicle') { - this.prototypeToken.updateSource({ sight: { enabled: true }, disposition: 0 }) - } - // Add Skills to Characters - if (this.type === 'character') { - const packName = game.settings.get('ac2d20', 'compendium-skills'); - if(!packName) - packName = "ac2d20.skills" - - let packSkills = await game.packs.get(packName).getDocuments(); - const items = this.items.map(i => i.toObject()); - packSkills.forEach(s => { - items.push(s.toObject()); - }); - this.updateSource({ items }); - } - } - - getRollShortcuts() { - let out = {}; - // Attributes - for (const name of ["bra", "agi", "coo", "rea", "ins", "wil"]) { - out[name.substring(0, 3)] = this.system.attributes[name].value; - } - // Power - out['pow'] = this.system.power.value; - return out; - } -} \ No newline at end of file + _getNpcRollData(data) { + // if (this.type !== "npc") return; + // Process additional NPC data here. + } + + async _preCreate(data, options, user) { + await super._preCreate(data, options, user); + // set icon based on actor type + if (data.img === undefined) { + let ico = `systems/ac2d20/assets/doc-icons/${this.type}.svg`; + this.updateSource({ img: ico }); + } + // Setup Tokens + if (this.type === "character") { + this.prototypeToken.updateSource({ + actorLink: true, + sight: { + enabled: true, + }, + disposition: 1, + }); + } + if (this.type === "npc") { + this.prototypeToken.updateSource({ sight: { enabled: true }, disposition: -1 }); + } + if (this.type === "vehicle") { + this.prototypeToken.updateSource({ sight: { enabled: true }, disposition: 0 }); + } + // Add Skills to Characters + if (this.type === "character") { + // If the Actor data already contains skill items then this is an + // Actor being duplicated and we don't want to touch their + // items at all + // + const alreadyHasSkills = Array.isArray(data.items) + && data.items.filter(i => i.type === "skill").length > 0; + + if (!alreadyHasSkills) { + let skillsCompendium = game.settings.get("ac2d20", "compendium-skills"); + + if (!skillsCompendium) skillsCompendium = "ac2d20.skills"; + + let packSkills = + await game.packs.get(skillsCompendium).getDocuments(); + + const items = this.items.map(i => i.toObject()); + + packSkills.forEach(s => { + items.push(s.toObject()); + }); + + this.updateSource({ items }); + } + } + } + + getRollShortcuts() { + let out = {}; + // Attributes + for (const name of ["bra", "agi", "coo", "rea", "ins", "wil"]) { + out[name.substring(0, 3)] = this.system.attributes[name].value; + } + // Power + out.pow = this.system.power.value; + return out; + } +} diff --git a/system/src/documents/item.mjs b/system/src/documents/item.mjs index b0c01fb..da1cf92 100644 --- a/system/src/documents/item.mjs +++ b/system/src/documents/item.mjs @@ -3,114 +3,118 @@ * @extends {Item} */ export class ACItem extends Item { - - /** @override */ - prepareData() { - super.prepareData(); - } - async _preCreate(data, options, user) { - await super._preCreate(data, options, user); - if(data.img==undefined){ - let ico = `systems/ac2d20/assets/doc-icons/${data.type}.svg`; - this.updateSource({ 'img': ico }); - } - } + /** @override */ + prepareData() { + super.prepareData(); + } - /** - * Prepare a data object which is passed to any Roll formulas which are created related to this Item + async _preCreate(data, options, user) { + await super._preCreate(data, options, user); + if (data.img === undefined) { + let ico = `systems/ac2d20/assets/doc-icons/${data.type}.svg`; + this.updateSource({ img: ico }); + } + } + + /** + * Prepare a data object which is passed to any Roll formulas which are + * created related to this Item * @private */ - getRollData() { - // If present, return the actor's roll data. - if (!this.actor) return null; - const rollData = this.actor.getRollData(); - rollData.item = foundry.utils.deepClone(this.system); + getRollData() { + // If present, return the actor's roll data. + if (!this.actor) return null; + const rollData = this.actor.getRollData(); + rollData.item = foundry.utils.deepClone(this.system); + + return rollData; + } + + // FOCUS + async addFocus() { + let focuses = this.system.focuses; + const focus = { title: "", isfocus: false, description: "" }; + focuses = [...focuses, focus]; + let updatedItem = { "_id": this.id, "system.focuses": focuses }; + await this.update(updatedItem); + } + + async deleteFocus(_index) { + let focuses = this.system.focuses; + focuses.splice(_index, 1); + let updatedItem = { "_id": this.id, "system.focuses": focuses }; + await this.update(updatedItem); + } - return rollData; - } + async updateFocuses(_focuses) { + let updatedItem = { "_id": this.id, "system.focuses": _focuses }; + await this.update(updatedItem); + } - // FOCUS - async addFocus() { - let focuses = this.system.focuses; - const focus = { title: '', isfocus: false, description: '' } - focuses = [...focuses, focus]; - let updatedItem = { _id: this.id, "system.focuses": focuses }; - await this.update(updatedItem); - } - async deleteFocus(_index) { - let focuses = this.system.focuses; - focuses.splice(_index, 1); - let updatedItem = { _id: this.id, "system.focuses": focuses } ; - await this.update(updatedItem); - } - async updateFocuses(_focuses) { - let updatedItem = { _id: this.id, "system.focuses": _focuses }; - await this.update(updatedItem); - } - /** + /** * Handle clickable rolls. * @param {Event} event The originating click event * @private */ - async roll() { - // Initialize chat data - const speaker = ChatMessage.getSpeaker({ actor: this.actor }); - const rollMode = game.settings.get('core', 'rollMode'); - const label = `[${this.type}] ${this.name}`; + async roll() { + // Initialize chat data + const speaker = ChatMessage.getSpeaker({ actor: this.actor }); + const rollMode = game.settings.get("core", "rollMode"); + const label = `[${this.type}] ${this.name}`; - // If there's no roll data, send a chat message. - if (!this.system.formula) { - ChatMessage.create({ - speaker: speaker, - rollMode: rollMode, - flavor: label, - content: this.system.description ?? '' - }); - } - // Otherwise, create a roll and send a chat message from it. - else { - // Retrieve roll data. - const rollData = this.getRollData(); + // If there's no roll data, send a chat message. + if (!this.system.formula) { + ChatMessage.create({ + speaker: speaker, + rollMode: rollMode, + flavor: label, + content: this.system.description ?? "", + }); + } + // Otherwise, create a roll and send a chat message from it. + else { + // Retrieve roll data. + const rollData = this.getRollData(); - // Invoke the roll and submit it to chat. - const roll = new Roll(rollData.item.formula, rollData).roll(); - roll.toMessage({ - speaker: speaker, - rollMode: rollMode, - flavor: label, - }); - return roll; - } - } + // Invoke the roll and submit it to chat. + const roll = new Roll(rollData.item.formula, rollData).roll(); + roll.toMessage({ + speaker: speaker, + rollMode: rollMode, + flavor: label, + }); + return roll; + } + } - async sendToChat() { - const itemData = duplicate(this.system); - itemData._id = this._id; - itemData.img = this.img; - itemData.name = this.name; - itemData.type = this.type; - itemData.isPhysical = this.system.hasOwnProperty('weight') - itemData.isWeapon = this.type === "weapon"; - itemData.isArmor = this.type === "armor"; - itemData.isTalent = this.type === "talent"; - itemData.isSpell = this.type === "spell"; - itemData.isSkillkit = this.type === "skillkit"; - itemData.isSkillkit = this.type === "skillkit"; - itemData.isEquipment = this.type === "equipment"; - itemData.isSpecial_rule = this.type === "special_rule"; - itemData.isSkill = this.type === "skill"; - const html = await renderTemplate("systems/ac2d20/templates/chat/item.html", itemData); - const chatData = { - user: game.user.id, - rollMode: game.settings.get("core", "rollMode"), - content: html, - }; - if (["gmroll", "blindroll"].includes(chatData.rollMode)) { - chatData.whisper = ChatMessage.getWhisperRecipients("GM"); - } else if (chatData.rollMode === "selfroll") { - chatData.whisper = [game.user]; - } - ChatMessage.create(chatData); - } + async sendToChat() { + const itemData = duplicate(this.system); + itemData._id = this._id; + itemData.img = this.img; + itemData.name = this.name; + itemData.type = this.type; + itemData.isPhysical = this.system.hasOwnProperty("weight"); + itemData.isWeapon = this.type === "weapon"; + itemData.isArmor = this.type === "armor"; + itemData.isTalent = this.type === "talent"; + itemData.isSpell = this.type === "spell"; + itemData.isSkillkit = this.type === "skillkit"; + itemData.isEquipment = this.type === "equipment"; + itemData.isSpecial_rule = this.type === "special_rule"; + itemData.isSkill = this.type === "skill"; + const html = await renderTemplate("systems/ac2d20/templates/chat/item.hbs", itemData); + const chatData = { + user: game.user.id, + rollMode: game.settings.get("core", "rollMode"), + content: html, + }; + if (["gmroll", "blindroll"].includes(chatData.rollMode)) { + chatData.whisper = ChatMessage.getWhisperRecipients("GM"); + } + else if (chatData.rollMode === "selfroll") { + chatData.whisper = [game.user]; + } + ChatMessage.create(chatData); + } } diff --git a/system/src/enrichers.mjs b/system/src/enrichers.mjs index fe58db9..516e21c 100644 --- a/system/src/enrichers.mjs +++ b/system/src/enrichers.mjs @@ -4,12 +4,12 @@ export function registerEnrichers() { { pattern: /@(s(tress)?|c(hallenge)?)/gim, enricher: async (match, options) => { - const i = document.createElement('i'); - i.className = 'cthl-cthulhu'; + const i = document.createElement("i"); + i.className = "cthl-cthulhu"; // Adjust positioning slightly to align better with text. - i.style.position = 'relative'; - i.style.top = '0.2em'; + i.style.position = "relative"; + i.style.top = "0.2em"; return i; }, @@ -17,15 +17,15 @@ export function registerEnrichers() { { pattern: /@(x(ross)?)/gim, enricher: async (match, options) => { - const i = document.createElement('i'); - i.className = 'cth-ico-cth-cross'; + const i = document.createElement("i"); + i.className = "cth-ico-cth-cross"; // Adjust positioning slightly to align better with text. - i.style.position = 'relative'; - i.style.top = '0.1em'; + i.style.position = "relative"; + i.style.top = "0.1em"; return i; }, - } + }, ]; -} \ No newline at end of file +} diff --git a/system/src/helpers/config.mjs b/system/src/helpers/config.mjs index ed0e527..1c2c3fd 100644 --- a/system/src/helpers/config.mjs +++ b/system/src/helpers/config.mjs @@ -1,119 +1,53 @@ export const AC2D20 = {}; AC2D20.attributes = { - "agi": "AC2D20.AbilityAgi", - "bra": "AC2D20.AbilityBra", - "coo": "AC2D20.AbilityCoo", - "ins": "AC2D20.AbilityIns", - "rea": "AC2D20.AbilityRea", - "wil": "AC2D20.AbilityWil", + agi: "AC2D20.AbilityAgi", + bra: "AC2D20.AbilityBra", + coo: "AC2D20.AbilityCoo", + ins: "AC2D20.AbilityIns", + rea: "AC2D20.AbilityRea", + wil: "AC2D20.AbilityWil", }; AC2D20.abilityAbbreviations = { - "agi": "AC2D20.AbilityAgiAbr", - "bra": "AC2D20.AbilityBraAbr", - "coo": "AC2D20.AbilityCooAbr", - "ins": "AC2D20.AbilityInsAbr", - "rea": "AC2D20.AbilityReaAbr", - "wil": "AC2D20.AbilityWilAbr", + agi: "AC2D20.AbilityAgiAbr", + bra: "AC2D20.AbilityBraAbr", + coo: "AC2D20.AbilityCooAbr", + ins: "AC2D20.AbilityInsAbr", + rea: "AC2D20.AbilityReaAbr", + wil: "AC2D20.AbilityWilAbr", }; -// Depricated. This is now created from the skill compendium -// AC2D20.SKILLS = [ -// { -// 'label': 'ACADEMIA', -// 'key': "Academia", -// 'focuses': ['Art', 'Cryptography', 'Finance', 'History', 'Linguistics', 'Occultism', 'Science'] -// }, -// { -// 'label': 'ATHLETICS', -// 'key': "Athletics", -// 'focuses': ['Climbing', 'Lifting', 'Physical Training', 'Running', 'Swimming', 'Throwing'] -// }, -// { -// 'label': 'ENGINEERING', -// 'key': "Engineering", -// 'focuses': ['Architecture', 'Combat Engineering', 'Electronics', 'Explosives', 'Mechanical Engineering'] -// }, -// { -// 'label': 'FIGHTING', -// 'key': "Fighting", -// 'focuses': ['Close Quarters', 'Handguns', 'Hand-to-Hand', 'Heavy Weapons', 'Melee Weapons', 'Rifles', -// 'Threat Awareness', 'Exotic'] -// }, -// { -// 'label': 'MEDICINE', -// 'key': "Medicine", -// 'focuses': ['First Aid', 'Infectious Diseases', 'Pharmacology', 'Psychiatry', 'Surgery', 'Toxicology'] -// }, -// { -// 'label': 'OBSERVATION', -// 'key': "Observation", -// 'focuses': ['Hearing', 'Instincts', 'Sight', 'Smell and Taste'] -// }, -// { -// 'label': 'PERSUASION', -// 'key': "Persuasion", -// 'focuses': ['Charm', 'Innuendo', 'Intimidation', 'Negotiation', 'Rhetoric', 'Deceive', 'Invocation'] -// }, -// { -// 'label': 'RESILIENCE', -// 'key': "Resilience", -// 'focuses': ['Fortitude', 'Discipline', 'Immunity'] -// }, -// { -// 'label': 'STEALTH', -// 'key': "Stealth", -// 'focuses': ['Camouflage', 'Disguise', 'Rural Stealth', 'Urban Stealth'] -// }, -// { -// 'label': 'SURVIVAL', -// 'key': "Survival", -// 'focuses': ['Animal Handling', 'Foraging', 'Hunting', 'Mysticism', 'Orienteering', 'Tracking'] -// }, -// { -// 'label': 'TACTICS', -// 'key': "Tactics", -// 'focuses': ['Air Force', 'Army', 'Covert Operations', 'Leadership', 'Navy', 'Technical Projects'] -// }, -// { -// 'label': 'VEHICLES', -// 'key': "Vehicles", -// 'focuses': ['Cars', 'Motorcycles', 'Heavy Vehicles', 'Tanks', 'Aircraft', 'Watercraft'] -// } -// ]; - AC2D20.Size = ["Trivial", "Minor", "Major"]; AC2D20.WEAPONS = { - "range": { - "reach": "AC2D20.RANGE.reach", - "close": "AC2D20.RANGE.close", - "medium": "AC2D20.RANGE.medium", - "long": "AC2D20.RANGE.long", - "extreme": "AC2D20.RANGE.extreme" - }, - "weaponTypes": [ - { - 'label': "Melee", - 'bonusAttribute': 'agi' - }, - { - 'label': "Ranged", - 'bonusAttribute': 'coo' - }, - { - 'label': "Mental", - 'bonusAttribute': 'wil' - } - ] -} + range: { + reach: "AC2D20.RANGE.reach", + close: "AC2D20.RANGE.close", + medium: "AC2D20.RANGE.medium", + long: "AC2D20.RANGE.long", + extreme: "AC2D20.RANGE.extreme", + }, + weaponTypes: [ + { + label: "Melee", + bonusAttribute: "agi", + }, + { + label: "Ranged", + bonusAttribute: "coo", + }, + { + label: "Mental", + bonusAttribute: "wil", + }, + ], +}; AC2D20.spellcastingTypes = { - "traditional":"traditional", - "researcher":"researcher", - "dabbler":"dabbler" -} - + traditional: "traditional", + researcher: "researcher", + dabbler: "dabbler", +}; diff --git a/system/src/helpers/effects.mjs b/system/src/helpers/effects.mjs index ae677fa..806d1b7 100644 --- a/system/src/helpers/effects.mjs +++ b/system/src/helpers/effects.mjs @@ -3,27 +3,27 @@ * @param {MouseEvent} event The left-click event on the effect control * @param {Actor|Item} owner The owning entity which manages this effect */ - export function onManageActiveEffect(event, owner) { - event.preventDefault(); - const a = event.currentTarget; - const li = a.closest("li"); - const effect = li.dataset.effectId ? owner.effects.get(li.dataset.effectId) : null; - switch ( a.dataset.action ) { - case "create": - return owner.createEmbeddedDocuments("ActiveEffect", [{ - label: "New Effect", - icon: "icons/svg/aura.svg", - origin: owner.uuid, - "duration.rounds": li.dataset.effectType === "temporary" ? 1 : undefined, - disabled: li.dataset.effectType === "inactive" - }]); - case "edit": - return effect.sheet.render(true); - case "delete": - return effect.delete(); - case "toggle": - return effect.update({disabled: !effect.data.disabled}); - } +export function onManageActiveEffect(event, owner) { + event.preventDefault(); + const a = event.currentTarget; + const li = a.closest("li"); + const effect = li.dataset.effectId ? owner.effects.get(li.dataset.effectId) : null; + switch ( a.dataset.action ) { + case "create": + return owner.createEmbeddedDocuments("ActiveEffect", [{ + "label": "New Effect", + "icon": "icons/svg/aura.svg", + "origin": owner.uuid, + "duration.rounds": li.dataset.effectType === "temporary" ? 1 : undefined, + "disabled": li.dataset.effectType === "inactive", + }]); + case "edit": + return effect.sheet.render(true); + case "delete": + return effect.delete(); + case "toggle": + return effect.update({disabled: !effect.data.disabled}); + } } /** @@ -33,31 +33,31 @@ */ export function prepareActiveEffectCategories(effects) { - // Define effect header categories - const categories = { - temporary: { - type: "temporary", - label: "Temporary Effects", - effects: [] - }, - passive: { - type: "passive", - label: "Passive Effects", - effects: [] - }, - inactive: { - type: "inactive", - label: "Inactive Effects", - effects: [] - } - }; + // Define effect header categories + const categories = { + temporary: { + type: "temporary", + label: "Temporary Effects", + effects: [], + }, + passive: { + type: "passive", + label: "Passive Effects", + effects: [], + }, + inactive: { + type: "inactive", + label: "Inactive Effects", + effects: [], + }, + }; - // Iterate over active effects, classifying them into categories - for ( let e of effects ) { - e._getSourceName(); // Trigger a lookup for the source name - if ( e.data.disabled ) categories.inactive.effects.push(e); - else if ( e.isTemporary ) categories.temporary.effects.push(e); - else categories.passive.effects.push(e); - } - return categories; -} \ No newline at end of file + // Iterate over active effects, classifying them into categories + for ( let e of effects ) { + e._getSourceName(); // Trigger a lookup for the source name + if ( e.data.disabled ) categories.inactive.effects.push(e); + else if ( e.isTemporary ) categories.temporary.effects.push(e); + else categories.passive.effects.push(e); + } + return categories; +} diff --git a/system/src/helpers/handlebars.mjs b/system/src/helpers/handlebars.mjs index 36f7d26..6336e34 100644 --- a/system/src/helpers/handlebars.mjs +++ b/system/src/helpers/handlebars.mjs @@ -1,210 +1,199 @@ -export const registerHandlebarsHelpers = function () { - - /* -------------------------------------------- */ - /* GENERAL HELPERS */ - /* -------------------------------------------- */ - Handlebars.registerHelper('concat', function () { - var outStr = ''; - for (var arg in arguments) { - if (typeof arguments[arg] != 'object') { - outStr += arguments[arg]; - } - } - return outStr; - }); - - Handlebars.registerHelper('toLowerCase', function (str) { - return str.toLowerCase(); - }); - - Handlebars.registerHelper('toUpperCase', function (str) { - return str.toUpperCase(); - }); - - Handlebars.registerHelper('subString', function (str, s, e) { - return str.substring(s, e); - }); - - Handlebars.registerHelper("ifCond", function (v1, operator, v2, options) { - switch (operator) { - case "==": - return v1 == v2 ? options.fn(this) : options.inverse(this); - case "===": - return v1 === v2 ? options.fn(this) : options.inverse(this); - case "!=": - return v1 != v2 ? options.fn(this) : options.inverse(this); - case "!==": - return v1 !== v2 ? options.fn(this) : options.inverse(this); - case "<": - return v1 < v2 ? options.fn(this) : options.inverse(this); - case "<=": - return v1 <= v2 ? options.fn(this) : options.inverse(this); - case ">": - return v1 > v2 ? options.fn(this) : options.inverse(this); - case ">=": - return v1 >= v2 ? options.fn(this) : options.inverse(this); - case "&&": - return v1 && v2 ? options.fn(this) : options.inverse(this); - case "||": - return v1 || v2 ? options.fn(this) : options.inverse(this); - default: - return options.inverse(this); - } - }); - - Handlebars.registerHelper("math", function (lvalue, operator, rvalue, options) { - lvalue = parseFloat(lvalue); - rvalue = parseFloat(rvalue); - return { - "+": lvalue + rvalue, - "-": lvalue - rvalue, - "*": lvalue * rvalue, - "/": lvalue / rvalue, - "%": lvalue % rvalue - }[operator]; - }); - - /* -------------------------------------------- */ - /* AC2D20 HELPERS */ - /* -------------------------------------------- */ - - Handlebars.registerHelper('damageFaIconClass', function (str) { - if (str == "physical") - return "fas fa-fist-raised"; - else if (str == "energy") - return "fas fa-bolt"; - else if (str == "radiation") - return "fas fa-radiation"; - else if (str == "poison") - return "fas fa-biohazard"; - }); - - Handlebars.registerHelper('getSkillFocusList', function (key) { - if(key=="") - return []; - const _skill = CONFIG.AC2D20.SKILLS.filter((s) => s.key === key) - return _skill[0].focuses; - }); - - Handlebars.registerHelper('getWeaponEffects', function (effect) { - let effects = []; - Object.entries(effect).forEach(([k, v]) => { - let effString = ''; - let tooltip = '' - if (v.value) { - let tstr = 'AC2D20.WEAPONS.effects.'+ k; - tooltip = Handlebars.helpers.getTooltipFromConfigKey(tstr) - effString += `${v.label}`; - if (v.rank) { - effString += ` ${v.rank}`; - } - effString += `` - effects.push(effString) - } - }) - return effects.join(', ') - }); - - Handlebars.registerHelper('getWeaponQualities', function (qualities) { - let _qualities = []; - Object.entries(qualities).forEach(([k, v]) => { - let quString = ''; - let tooltip = '' - if (v.value) { - let tstr = 'AC2D20.WEAPONS.qualities.'+ k; - tooltip = Handlebars.helpers.getTooltipFromConfigKey(tstr) - quString += `${v.label}`; - _qualities.push(quString) - } - }) - return _qualities.join(', ') - }); - - Handlebars.registerHelper('isCreaturesWeapon', function (weapon) { - if (weapon.system.weaponType == "creatureAttack" || weapon.actor?.type == "creature") - return true; - else - return false; - }); - - Handlebars.registerHelper('isWeaponUsingMeleeBonus', function (weapon, actor) { - if ((weapon.weaponType == "unarmed" || weapon.weaponType == "meleeWeapons") && actor?.type != "creature") - return true; - else - return false; - }); - - Handlebars.registerHelper('hasInjury', function (txt) { - if (txt.length > 0) - return true; - else - return false; - }); - - Handlebars.registerHelper('getAttributeBonus', function (actor, weaponType) { - if (weaponType == 'agi') - return actor.system.attributes['bra'].bonus; - else if (weaponType == 'coo') - return actor.system.attributes['ins'].bonus; - else if (weaponType == 'wil') - return actor.system.attributes['wil'].bonus; - }); - - Handlebars.registerHelper('getArmorQualities', function (qualities) { - let qual = Object.entries(qualities).filter(([k, v]) => v.value).map(m => m[0]); - return qual; - }); - - Handlebars.registerHelper('getSizeLabel', function (num) { - if (num == 0) - return 'Trivial' - else if (num == 1) - return 'Minor' - else if (num == 3) - return 'Major' - else - return '-' - }); - - - Handlebars.registerHelper('clearTextAreaText', function (txt) { - txt.trim(); - txt = txt.replace(/ +/g, ' '); - //! replace new lines with encided \n so stupid textarea doesn't break - txt = txt.replace(/(?:\r\n|\r|\n)/g, ' '); - return txt; - }); - - // FOR TIMES LOOP - Handlebars.registerHelper('times', function (n, block) { - var accum = ''; - for (var i = 0; i < n; ++i) - accum += block.fn(i); - return accum; - }); - - // * Use with #if - // {{#if (or - // (eq section1 "foo") - //(ne section2 "bar"))}} - //.. content - //{{/if}} - Handlebars.registerHelper({ - eq: (v1, v2) => v1 === v2, - ne: (v1, v2) => v1 !== v2, - lt: (v1, v2) => v1 < v2, - gt: (v1, v2) => v1 > v2, - lte: (v1, v2) => v1 <= v2, - gte: (v1, v2) => v1 >= v2, - and() { - return Array.prototype.every.call(arguments, Boolean); - }, - or() { - return Array.prototype.slice.call(arguments, 0, -1).some(Boolean); - } - }); - - Handlebars.registerHelper('getTooltipFromConfigKey', function (key) { - return key.split('.').reduce((o,i)=> o[i], CONFIG) - }) -} \ No newline at end of file +export const registerHandlebarsHelpers = function() { + + /* -------------------------------------------- */ + /* GENERAL HELPERS */ + /* -------------------------------------------- */ + Handlebars.registerHelper("concat", function() { + let outStr = ""; + for (let arg in arguments) { + if (typeof arguments[arg] != "object") { + outStr += arguments[arg]; + } + } + return outStr; + }); + + Handlebars.registerHelper("toLowerCase", function(str) { + return str.toLowerCase(); + }); + + Handlebars.registerHelper("toUpperCase", function(str) { + return str.toUpperCase(); + }); + + Handlebars.registerHelper("subString", function(str, s, e) { + return str.substring(s, e); + }); + + Handlebars.registerHelper("ifCond", function(v1, operator, v2, options) { + switch (operator) { + case "==": + // eslint-disable-next-line eqeqeq + return v1 == v2 ? options.fn(this) : options.inverse(this); + case "===": + return v1 === v2 ? options.fn(this) : options.inverse(this); + case "!=": + // eslint-disable-next-line eqeqeq + return v1 != v2 ? options.fn(this) : options.inverse(this); + case "!==": + return v1 !== v2 ? options.fn(this) : options.inverse(this); + case "<": + return v1 < v2 ? options.fn(this) : options.inverse(this); + case "<=": + return v1 <= v2 ? options.fn(this) : options.inverse(this); + case ">": + return v1 > v2 ? options.fn(this) : options.inverse(this); + case ">=": + return v1 >= v2 ? options.fn(this) : options.inverse(this); + case "&&": + return v1 && v2 ? options.fn(this) : options.inverse(this); + case "||": + return v1 || v2 ? options.fn(this) : options.inverse(this); + default: + return options.inverse(this); + } + }); + + Handlebars.registerHelper("math", function(lvalue, operator, rvalue, options) { + lvalue = parseFloat(lvalue); + rvalue = parseFloat(rvalue); + return { + "+": lvalue + rvalue, + "-": lvalue - rvalue, + "*": lvalue * rvalue, + "/": lvalue / rvalue, + "%": lvalue % rvalue, + }[operator]; + }); + + /* -------------------------------------------- */ + /* AC2D20 HELPERS */ + /* -------------------------------------------- */ + + Handlebars.registerHelper("damageFaIconClass", function(str) { + if (str === "physical") return "fas fa-fist-raised"; + else if (str === "energy") return "fas fa-bolt"; + else if (str === "radiation") return "fas fa-radiation"; + else if (str === "poison") return "fas fa-biohazard"; + }); + + Handlebars.registerHelper("getSkillFocusList", function(key) { + if (key === "") return []; + const _skill = CONFIG.AC2D20.SKILLS.filter(s => s.key === key); + return _skill[0].focuses; + }); + + Handlebars.registerHelper("getWeaponEffects", function(effect) { + let effects = []; + Object.entries(effect).forEach(([k, v]) => { + let effString = ""; + let tooltip = ""; + if (v.value) { + let tstr = `AC2D20.WEAPONS.effects.${k}`; + tooltip = Handlebars.helpers.getTooltipFromConfigKey(tstr); + effString += `${v.label}`; + if (v.rank) { + effString += ` ${v.rank}`; + } + effString += ""; + effects.push(effString); + } + }); + return effects.join(", "); + }); + + Handlebars.registerHelper("getWeaponQualities", function(qualities) { + let _qualities = []; + Object.entries(qualities).forEach(([k, v]) => { + let quString = ""; + let tooltip = ""; + if (v.value) { + let tstr = `AC2D20.WEAPONS.qualities.${k}`; + tooltip = Handlebars.helpers.getTooltipFromConfigKey(tstr); + quString += `${v.label}`; + _qualities.push(quString); + } + }); + return _qualities.join(", "); + }); + + Handlebars.registerHelper("isCreaturesWeapon", function(weapon) { + if (weapon.system.weaponType === "creatureAttack" || weapon.actor?.type === "creature") return true; + else return false; + }); + + Handlebars.registerHelper("isWeaponUsingMeleeBonus", function(weapon, actor) { + if ((weapon.weaponType === "unarmed" || weapon.weaponType === "meleeWeapons") && actor?.type !== "creature") return true; + else return false; + }); + + Handlebars.registerHelper("hasInjury", function(txt) { + if (txt.length > 0) return true; + else return false; + }); + + Handlebars.registerHelper("getAttributeBonus", function(actor, weaponType) { + if (weaponType === "agi") return actor.system.attributes.bra.bonus; + else if (weaponType === "coo") return actor.system.attributes.ins.bonus; + else if (weaponType === "wil") return actor.system.attributes.wil.bonus; + }); + + Handlebars.registerHelper("getArmorQualities", function(qualities) { + let qual = Object.entries(qualities).filter(([k, v]) => v.value).map(m => m[0]); + return qual; + }); + + Handlebars.registerHelper("getSizeLabel", function(num) { + switch (parseInt(num) ?? null) { + case 0: + return "Trivial"; + case 1: + return "Minor"; + case 3: + return "Major"; + default: + return "-"; + } + }); + + + Handlebars.registerHelper("clearTextAreaText", function(txt) { + txt.trim(); + txt = txt.replace(/ +/g, " "); + // ! replace new lines with encided \n so stupid textarea doesn't break + txt = txt.replace(/(?:\r\n|\r|\n)/g, " "); + return txt; + }); + + // FOR TIMES LOOP + Handlebars.registerHelper("times", function(n, block) { + let accum = ""; + for (let i = 0; i < n; ++i) accum += block.fn(i); + return accum; + }); + + // * Use with #if + // {{#if (or + // (eq section1 "foo") + // (ne section2 "bar"))}} + // .. content + // {{/if}} + Handlebars.registerHelper({ + eq: (v1, v2) => v1 === v2, + ne: (v1, v2) => v1 !== v2, + lt: (v1, v2) => v1 < v2, + gt: (v1, v2) => v1 > v2, + lte: (v1, v2) => v1 <= v2, + gte: (v1, v2) => v1 >= v2, + and() { + return Array.prototype.every.call(arguments, Boolean); + }, + or() { + return Array.prototype.slice.call(arguments, 0, -1).some(Boolean); + }, + }); + + Handlebars.registerHelper("getTooltipFromConfigKey", function(key) { + return key.split(".").reduce((o, i) => o[i], CONFIG); + }); +}; diff --git a/system/src/helpers/templates.mjs b/system/src/helpers/templates.mjs index b888d93..f4fe407 100644 --- a/system/src/helpers/templates.mjs +++ b/system/src/helpers/templates.mjs @@ -3,24 +3,24 @@ * Pre-loaded templates are compiled and cached for fast access when rendering * @return {Promise} */ -export const preloadHandlebarsTemplates = async function () { - return loadTemplates([ - "systems/ac2d20/templates/actor/parts/actor-header.html", - "systems/ac2d20/templates/actor/parts/actor-abilities.html", - "systems/ac2d20/templates/actor/parts/actor-talents.html", - "systems/ac2d20/templates/actor/parts/actor-spells.html", - "systems/ac2d20/templates/actor/parts/actor-weapons.html", - "systems/ac2d20/templates/actor/parts/actor-armor.html", - "systems/ac2d20/templates/actor/parts/actor-skillkit.html", - "systems/ac2d20/templates/actor/parts/actor-equipment.html", - "systems/ac2d20/templates/actor/parts/actor-encumbrance.html", - "systems/ac2d20/templates/actor/parts/actor-effects.html", - "systems/ac2d20/templates/actor/parts/npc-abilities.html", - "systems/ac2d20/templates/actor/parts/npc-header.html", - "systems/ac2d20/templates/actor/parts/vehicle-header.html", - "systems/ac2d20/templates/actor/parts/vehicle-abilities.html", - "systems/ac2d20/templates/item/parts/item-header.html", - "systems/ac2d20/templates/item/parts/item-effects.html", - "systems/ac2d20/templates/actor/parts/simple-expandable-item.html" - ]); +export const preloadHandlebarsTemplates = async function() { + return loadTemplates([ + "systems/ac2d20/templates/actor/parts/actor-header.hbs", + "systems/ac2d20/templates/actor/parts/actor-abilities.hbs", + "systems/ac2d20/templates/actor/parts/actor-talents.hbs", + "systems/ac2d20/templates/actor/parts/actor-spells.hbs", + "systems/ac2d20/templates/actor/parts/actor-weapons.hbs", + "systems/ac2d20/templates/actor/parts/actor-armor.hbs", + "systems/ac2d20/templates/actor/parts/actor-skillkit.hbs", + "systems/ac2d20/templates/actor/parts/actor-equipment.hbs", + "systems/ac2d20/templates/actor/parts/actor-encumbrance.hbs", + "systems/ac2d20/templates/actor/parts/actor-effects.hbs", + "systems/ac2d20/templates/actor/parts/npc-abilities.hbs", + "systems/ac2d20/templates/actor/parts/npc-header.hbs", + "systems/ac2d20/templates/actor/parts/vehicle-header.hbs", + "systems/ac2d20/templates/actor/parts/vehicle-abilities.hbs", + "systems/ac2d20/templates/item/parts/item-header.hbs", + "systems/ac2d20/templates/item/parts/item-effects.hbs", + "systems/ac2d20/templates/actor/parts/simple-expandable-item.hbs", + ]); }; diff --git a/system/src/roller/ac2d20-roller.mjs b/system/src/roller/ac2d20-roller.mjs index 659d579..6914138 100644 --- a/system/src/roller/ac2d20-roller.mjs +++ b/system/src/roller/ac2d20-roller.mjs @@ -1,330 +1,325 @@ export class Roller2D20 { - dicesRolled = []; - successTreshold = 0; - critTreshold = 0; - complicationTreshold = 20; - successes = 0; + dicesRolled = []; - static async rollD20({ rollname = "Roll xD20", dicenum = 2, attribute = 0, skill = 0, focus = false, difficulty = 1, complication = 20, actorId = null, itemId = null } = {}) { - let dicesRolled = []; - let successTreshold = parseInt(attribute) + parseInt(skill); - let critTreshold = focus ? parseInt(skill) : 1; - let complicationTreshold = parseInt(complication); - let formula = `${dicenum}d20`; - let roll = new Roll(formula); - await roll.evaluate({ async: true }); - await Roller2D20.parseD20Roll({ - rollname: rollname, - roll: roll, - successTreshold: successTreshold, - critTreshold: critTreshold, - complicationTreshold: complicationTreshold, - actorId: actorId, - itemId: itemId - }); - } + successTreshold = 0; - static async parseD20Roll({ rollname = "Roll xD20", roll = null, successTreshold = 0, critTreshold = 1, complicationTreshold = 20, dicesRolled = [], rerollIndexes = [], actorId = null, itemId = null }) { - let i = 0; - roll.dice.forEach(d => { - d.results.forEach(r => { - let diceSuccess = 0; - let diceComplication = 0; - if (r.result <= successTreshold) { - diceSuccess++; - } - if (r.result <= critTreshold) { - diceSuccess++; - } - if (r.result >= complicationTreshold) { - diceComplication = 1; - } - // if there are no rollIndexes sent then it is a new roll. Otherwise it's a re-roll and we should replace dices at given indexes - if (!rerollIndexes.length) { - dicesRolled.push({ success: diceSuccess, reroll: false, result: r.result, complication: diceComplication }); - } - else { - dicesRolled[rerollIndexes[i]] = { success: diceSuccess, reroll: true, result: r.result, complication: diceComplication }; - i++; - } - }) - }); - await Roller2D20.sendToChat({ - rollname: rollname, - roll: roll, - successTreshold: successTreshold, - critTreshold: critTreshold, - complicationTreshold: complicationTreshold, - dicesRolled: dicesRolled, - rerollIndexes: rerollIndexes, - actorId: actorId, - itemId: itemId - }); - } + critTreshold = 0; - static async rerollD20({ rollname = "Roll xD20", roll = null, successTreshold = 0, critTreshold = 1, complicationTreshold = 20, dicesRolled = [], rerollIndexes = [] } = {}) { - if (!rerollIndexes.length) { - ui.notifications.notify('Select Dice you want to Reroll'); - return; - } - let numOfDice = rerollIndexes.length; - let formula = `${numOfDice}d20`; - let _roll = new Roll(formula); - await _roll.evaluate({ async: true }); - await Roller2D20.parseD20Roll({ - rollname: `${rollname} re-roll`, - roll: _roll, - successTreshold: successTreshold, - critTreshold: critTreshold, - complicationTreshold: complicationTreshold, - dicesRolled: dicesRolled, - rerollIndexes: rerollIndexes - }); - } + complicationTreshold = 20; - static async sendToChat({ rollname = "Roll xD20", roll = null, successTreshold = 0, critTreshold = 1, complicationTreshold = 20, dicesRolled = [], rerollIndexes = [], actorId = null, itemId = null } = {}) { - let successesNum = Roller2D20.getNumOfSuccesses(dicesRolled); - let complicationsNum = Roller2D20.getNumOfComplications(dicesRolled); - let rollData = { - rollname: rollname, - successes: successesNum, - complications: complicationsNum, - results: dicesRolled, - successTreshold: successTreshold, - actorId: actorId, - itemId: itemId - } - const html = await renderTemplate("systems/ac2d20/templates/chat/roll2d20.html", rollData); - let ac2d20Roll = {} - ac2d20Roll.rollname = rollname; - ac2d20Roll.dicesRolled = dicesRolled; - ac2d20Roll.successTreshold = successTreshold; - ac2d20Roll.critTreshold = critTreshold; - ac2d20Roll.complicationTreshold = complicationTreshold; - ac2d20Roll.rerollIndexes = rerollIndexes; - ac2d20Roll.diceFace = "d20"; - let speaker = {actor:actorId} - let chatData = { - user: game.user.id, - speaker: speaker, - rollMode: game.settings.get("core", "rollMode"), - content: html, - flags: { ac2d20roll: ac2d20Roll }, - type: CONST.CHAT_MESSAGE_TYPES.ROLL, - roll: roll, - }; - if (["gmroll", "blindroll"].includes(chatData.rollMode)) { - chatData.whisper = ChatMessage.getWhisperRecipients("GM"); - } else if (chatData.rollMode === "selfroll") { - chatData.whisper = [game.user]; - } - await ChatMessage.create(chatData); - } + successes = 0; - static getNumOfSuccesses(results) { - let s = 0; - results.forEach(d => { - s += d.success; - }); - return s; - } + static async rollD20({ rollname = "Roll xD20", dicenum = 2, attribute = 0, skill = 0, focus = false, difficulty = 1, complication = 20, actorId = null, itemId = null } = {}) { + // let dicesRolled = []; + let successTreshold = parseInt(attribute) + parseInt(skill); + let critTreshold = focus ? parseInt(skill) : 1; + let complicationTreshold = parseInt(complication); + let formula = `${dicenum}d20`; + let roll = new Roll(formula); - static getNumOfComplications(results) { - let r = 0; - results.forEach(d => { - r += d.complication; - }); - return r; - } + await roll.evaluate({ async: true }); - static async rollD6({ rollname = "Roll D6", dicenum = 2, itemId = null, actorId = null } = {}) { - let formula = `${dicenum}ds`; - let roll = new Roll(formula); - await roll.evaluate({ async: true }); - await Roller2D20.parseD6Roll({ - rollname: rollname, - roll: roll, - itemId: itemId, - actorId: actorId - }); - } + await Roller2D20.parseD20Roll({ + rollname: rollname, + roll: roll, + successTreshold: successTreshold, + critTreshold: critTreshold, + complicationTreshold: complicationTreshold, + actorId: actorId, + itemId: itemId, + }); + } - static async parseD6Roll({ rollname = "Roll D6", roll = null, dicesRolled = [], rerollIndexes = [], addDice = [], itemId = null, actorId = null } = {}) { - let diceResults = [ - { result: 1, effect: 0 }, - { result: 2, effect: 0 }, - { result: 0, effect: 0 }, - { result: 0, effect: 0 }, - { result: 1, effect: 1 }, - { result: 1, effect: 1 }, - ]; + static async parseD20Roll({ rollname = "Roll xD20", roll = null, successTreshold = 0, critTreshold = 1, complicationTreshold = 20, dicesRolled = [], rerollIndexes = [], actorId = null, itemId = null }) { + let i = 0; + roll.dice.forEach(d => { + d.results.forEach(r => { + let diceSuccess = 0; + let diceComplication = 0; + if (r.result <= successTreshold) { + diceSuccess++; + } + if (r.result <= critTreshold) { + diceSuccess++; + } + if (r.result >= complicationTreshold) { + diceComplication = 1; + } + // if there are no rollIndexes sent then it is a new roll. + // Otherwise it's a re-roll and we should replace dices at given + // indexes + if (!rerollIndexes.length) { + dicesRolled.push({ + success: diceSuccess, + reroll: false, + result: r.result, + complication: diceComplication, + }); + } + else { + dicesRolled[rerollIndexes[i]] = { + success: diceSuccess, + reroll: true, + result: r.result, + complication: diceComplication, + }; + i++; + } + }); + }); + await Roller2D20.sendToChat({ + rollname: rollname, + roll: roll, + successTreshold: successTreshold, + critTreshold: critTreshold, + complicationTreshold: complicationTreshold, + dicesRolled: dicesRolled, + rerollIndexes: rerollIndexes, + actorId: actorId, + itemId: itemId, + }); + } - let i = 0; - roll.dice.forEach(d => { - d.results.forEach(r => { - let diceResult = diceResults[r.result - 1]; - diceResult.face = r.result; - // if there are no rollIndexes sent then it is a new roll. Otherwise it's a re-roll and we should replace dices at given indexes - if (!rerollIndexes.length) { - dicesRolled.push(diceResult); - } - else { - dicesRolled[rerollIndexes[i]] = diceResult; - i++; - } - }); - }); + static async rerollD20({ rollname = "Roll xD20", roll = null, successTreshold = 0, critTreshold = 1, complicationTreshold = 20, dicesRolled = [], rerollIndexes = [] } = {}) { + if (!rerollIndexes.length) { + ui.notifications.notify("Select Dice you want to Reroll"); + return; + } + let numOfDice = rerollIndexes.length; + let formula = `${numOfDice}d20`; + let _roll = new Roll(formula); + await _roll.evaluate({ async: true }); + await Roller2D20.parseD20Roll({ + rollname: `${rollname} re-roll`, + roll: _roll, + successTreshold: successTreshold, + critTreshold: critTreshold, + complicationTreshold: complicationTreshold, + dicesRolled: dicesRolled, + rerollIndexes: rerollIndexes, + }); + } - if (addDice.length) { - dicesRolled = addDice.concat(dicesRolled); - } + static async sendToChat({ rollname = "Roll xD20", roll = null, successTreshold = 0, critTreshold = 1, complicationTreshold = 20, dicesRolled = [], rerollIndexes = [], actorId = null, itemId = null } = {}) { + let successesNum = Roller2D20.getNumOfSuccesses(dicesRolled); + let complicationsNum = Roller2D20.getNumOfComplications(dicesRolled); + let rollData = { + rollname: rollname, + successes: successesNum, + complications: complicationsNum, + results: dicesRolled, + successTreshold: successTreshold, + actorId: actorId, + itemId: itemId, + }; + const html = await renderTemplate("systems/ac2d20/templates/chat/roll2d20.hbs", rollData); + let ac2d20Roll = {}; + ac2d20Roll.rollname = rollname; + ac2d20Roll.dicesRolled = dicesRolled; + ac2d20Roll.successTreshold = successTreshold; + ac2d20Roll.critTreshold = critTreshold; + ac2d20Roll.complicationTreshold = complicationTreshold; + ac2d20Roll.rerollIndexes = rerollIndexes; + ac2d20Roll.diceFace = "d20"; + let speaker = {actor: actorId}; + let chatData = { + user: game.user.id, + speaker: speaker, + rollMode: game.settings.get("core", "rollMode"), + content: html, + flags: { ac2d20roll: ac2d20Roll }, + type: CONST.CHAT_MESSAGE_TYPES.ROLL, + roll: roll, + }; + if (["gmroll", "blindroll"].includes(chatData.rollMode)) { + chatData.whisper = ChatMessage.getWhisperRecipients("GM"); + } + else if (chatData.rollMode === "selfroll") { + chatData.whisper = [game.user]; + } + await ChatMessage.create(chatData); + } - await Roller2D20.sendD6ToChat({ - rollname: rollname, - roll: roll, - dicesRolled: dicesRolled, - rerollIndexes: rerollIndexes, - itemId: itemId, - actorId: actorId - }); - } + static getNumOfSuccesses(results) { + let s = 0; + results.forEach(d => { + s += d.success; + }); + return s; + } - static async rerollD6({ rollname = "Roll D6", roll = null, dicesRolled = [], rerollIndexes = [], itemId = null, actorId = null } = {}) { - if (!rerollIndexes.length) { - ui.notifications.notify('Select Dice you want to Reroll'); - return; - } - let numOfDice = rerollIndexes.length; - let formula = `${numOfDice}ds`; - let _roll = new Roll(formula); - await _roll.evaluate({ async: true }); - await Roller2D20.parseD6Roll({ - rollname: `${rollname} [re-roll]`, - roll: _roll, - dicesRolled: dicesRolled, - rerollIndexes: rerollIndexes, - itemId: itemId, - actorId: actorId - }); - } + static getNumOfComplications(results) { + let r = 0; + results.forEach(d => { + r += d.complication; + }); + return r; + } - static async addD6({ rollname = "Roll D6", dicenum = 2, ac2d20Roll = null, dicesRolled = [], itemId = null, actorId = null } = {}) { - let formula = `${dicenum}ds`; - let _roll = new Roll(formula); - await _roll.evaluate({ async: true }); - let newRollName = `${ac2d20Roll.rollname} [+ ${dicenum} DC]`; - let oldDiceRolled = ac2d20Roll.dicesRolled; - await Roller2D20.parseD6Roll({ - rollname: newRollName, - roll: _roll, - dicesRolled: dicesRolled, - addDice: oldDiceRolled, - itemId: itemId, - actorId: actorId - }); - } + static async rollD6({ rollname = "Roll D6", dicenum = 2, itemId = null, actorId = null } = {}) { + let formula = `${dicenum}ds`; + let roll = new Roll(formula); + await roll.evaluate({ async: true }); + await Roller2D20.parseD6Roll({ + rollname: rollname, + roll: roll, + itemId: itemId, + actorId: actorId, + }); + } - static async sendD6ToChat({ rollname = "Roll D6", roll = null, dicesRolled = [], rerollIndexes = [], itemId = null, actorId = null } = {}) { - let damage = dicesRolled.reduce((a, b) => ({ result: a.result + b.result })).result; - let effects = dicesRolled.reduce((a, b) => ({ effect: a.effect + b.effect })).effect; - //let weaponDamageTypesList = []; - //let weaponDamageEffectsList = []; - //let weaponQualityList = []; + static async parseD6Roll({ rollname = "Roll D6", roll = null, dicesRolled = [], rerollIndexes = [], addDice = [], itemId = null, actorId = null } = {}) { + let diceResults = [ + { result: 1, effect: 0 }, + { result: 2, effect: 0 }, + { result: 0, effect: 0 }, + { result: 0, effect: 0 }, + { result: 1, effect: 1 }, + { result: 1, effect: 1 }, + ]; - let itemEffects = []; - let itemQualities = []; + let i = 0; + roll.dice.forEach(d => { + d.results.forEach(r => { + let diceResult = diceResults[r.result - 1]; + diceResult.face = r.result; + // if there are no rollIndexes sent then it is a new roll. + // Otherwise it's a re-roll and we should replace dices at given + // indexes + if (!rerollIndexes.length) { + dicesRolled.push(diceResult); + } + else { + dicesRolled[rerollIndexes[i]] = diceResult; + i++; + } + }); + }); - if (itemId && actorId) { - let actor = game.actors.get(actorId); - let item = null - if (actor) { - item = actor.items.get(itemId) - } - if (item) { - if (item.type === 'spell') { - itemEffects = item.system.costEffects; - } else if (item.type === 'weapon') { - for (let de in item.system.effect) { - if (item.system.effect[de].value) { - let rank = item.system.effect[de].rank ?? ""; - let damageEffectLabel = game.i18n.localize(`AC2D20.WEAPONS.damageEffect.${de}`); - let efectLabel = `${damageEffectLabel}${rank}`; - itemEffects.push(efectLabel); - } - } - itemEffects = itemEffects.join(', ') + if (addDice.length) { + dicesRolled = addDice.concat(dicesRolled); + } - for (let qu in item.system.qualities) { - if (item.system.qualities[qu].value) { - let quLabel = game.i18n.localize(`AC2D20.WEAPONS.qualities.${qu}`); - itemQualities.push(quLabel) - } - } - } - } + await Roller2D20.sendD6ToChat({ + rollname: rollname, + roll: roll, + dicesRolled: dicesRolled, + rerollIndexes: rerollIndexes, + itemId: itemId, + actorId: actorId, + }); + } - } + static async rerollD6({ rollname = "Roll D6", roll = null, dicesRolled = [], rerollIndexes = [], itemId = null, actorId = null } = {}) { + if (!rerollIndexes.length) { + ui.notifications.notify("Select Dice you want to Reroll"); + return; + } + let numOfDice = rerollIndexes.length; + let formula = `${numOfDice}ds`; + let _roll = new Roll(formula); + await _roll.evaluate({ async: true }); + await Roller2D20.parseD6Roll({ + rollname: `${rollname} [re-roll]`, + roll: _roll, + dicesRolled: dicesRolled, + rerollIndexes: rerollIndexes, + itemId: itemId, + actorId: actorId, + }); + } - // if (weapon != null) { - // for (let de in weapon.data.effect) { - // if (weapon.data.effect[de].value) { - // let rank = weapon.data.effect[de].rank ?? ""; - // let damageEffectLabel = game.i18n.localize(`AC2D20.WEAPONS.damageEffect.${de}`); - // let efectLabel = `${damageEffectLabel}${rank}`; - // weaponDamageEffectsList.push(efectLabel); - // } - // } + static async addD6({ rollname = "Roll D6", dicenum = 2, ac2d20Roll = null, dicesRolled = [], itemId = null, actorId = null } = {}) { + let formula = `${dicenum}ds`; + let _roll = new Roll(formula); + await _roll.evaluate({ async: true }); + let newRollName = `${ac2d20Roll.rollname} [+ ${dicenum} DC]`; + let oldDiceRolled = ac2d20Roll.dicesRolled; + await Roller2D20.parseD6Roll({ + rollname: newRollName, + roll: _roll, + dicesRolled: dicesRolled, + addDice: oldDiceRolled, + itemId: itemId, + actorId: actorId, + }); + } - // for (let qu in weapon.data.qualities) { - // if (weapon.data.qualities[qu].value) { - // //let rank = weapon.system.effect[qu].rank ?? ""; - // let quLabel = game.i18n.localize(`AC2D20.WEAPONS.qualities.${qu}`); - // //let quLabel = `${damageEffectLabel}${rank}`; - // weaponQualityList.push(quLabel); - // } - // } - // } - //let weaponDamageEffects = weaponDamageEffectsList.join(', '); - // let rollData = { - // rollname: rollname, - // damage: damage, - // effects: effects, - // results: dicesRolled, - // weaponDamageEffects: weaponDamageEffects, - // weaponQualityList: weaponQualityList - // } - let rollData = { - rollname: rollname, - damage: damage, - effects: effects, - results: dicesRolled, - itemEffects: itemEffects, - itemQualities: itemQualities - } - const html = await renderTemplate("systems/ac2d20/templates/chat/rollD6.html", rollData); - let ac2d20Roll = {} - ac2d20Roll.rollname = rollname; - ac2d20Roll.dicesRolled = dicesRolled; - ac2d20Roll.damage = damage; - ac2d20Roll.effects = effects; - ac2d20Roll.rerollIndexes = rerollIndexes; - ac2d20Roll.diceFace = "d6"; + static async sendD6ToChat({ rollname = "Roll D6", roll = null, dicesRolled = [], rerollIndexes = [], itemId = null, actorId = null } = {}) { + let damage = dicesRolled.reduce((a, b) => ({ result: a.result + b.result })).result; + let effects = dicesRolled.reduce((a, b) => ({ effect: a.effect + b.effect })).effect; + // let weaponDamageTypesList = []; + // let weaponDamageEffectsList = []; + // let weaponQualityList = []; - let chatData = { - user: game.user.id, - rollMode: game.settings.get("core", "rollMode"), - content: html, - flags: { ac2d20roll: ac2d20Roll, itemId: itemId, actorId: actorId }, - type: CONST.CHAT_MESSAGE_TYPES.ROLL, - roll: roll, - }; - if (["gmroll", "blindroll"].includes(chatData.rollMode)) { - chatData.whisper = ChatMessage.getWhisperRecipients("GM"); - } else if (chatData.rollMode === "selfroll") { - chatData.whisper = [game.user]; - } - await ChatMessage.create(chatData); + let itemEffects = []; + let itemQualities = []; - } + if (itemId && actorId) { + let actor = game.actors.get(actorId); + let item = null; + if (actor) { + item = actor.items.get(itemId); + } + if (item) { + if (item.type === "spell") { + itemEffects = item.system.costEffects; + } + else if (item.type === "weapon") { + for (let de in item.system.effect) { + if (item.system.effect[de].value) { + let rank = item.system.effect[de].rank ?? ""; + let damageEffectLabel = game.i18n.localize(`AC2D20.WEAPONS.damageEffect.${de}`); + let efectLabel = `${damageEffectLabel}${rank}`; + itemEffects.push(efectLabel); + } + } + itemEffects = itemEffects.join(", "); + + for (let qu in item.system.qualities) { + if (item.system.qualities[qu].value) { + let quLabel = game.i18n.localize(`AC2D20.WEAPONS.qualities.${qu}`); + itemQualities.push(quLabel); + } + } + } + } + + } + + let rollData = { + rollname: rollname, + damage: damage, + effects: effects, + results: dicesRolled, + itemEffects: itemEffects, + itemQualities: itemQualities, + }; + const html = await renderTemplate("systems/ac2d20/templates/chat/rollD6.hbs", rollData); + let ac2d20Roll = {}; + ac2d20Roll.rollname = rollname; + ac2d20Roll.dicesRolled = dicesRolled; + ac2d20Roll.damage = damage; + ac2d20Roll.effects = effects; + ac2d20Roll.rerollIndexes = rerollIndexes; + ac2d20Roll.diceFace = "d6"; + + let chatData = { + user: game.user.id, + rollMode: game.settings.get("core", "rollMode"), + content: html, + flags: { ac2d20roll: ac2d20Roll, itemId: itemId, actorId: actorId }, + type: CONST.CHAT_MESSAGE_TYPES.ROLL, + roll: roll, + }; + if (["gmroll", "blindroll"].includes(chatData.rollMode)) { + chatData.whisper = ChatMessage.getWhisperRecipients("GM"); + } + else if (chatData.rollMode === "selfroll") { + chatData.whisper = [game.user]; + } + await ChatMessage.create(chatData); + + } } diff --git a/system/src/roller/challengeDie.js b/system/src/roller/challengeDie.js index 6b22540..1c8db85 100644 --- a/system/src/roller/challengeDie.js +++ b/system/src/roller/challengeDie.js @@ -1,61 +1,59 @@ export default class DieACChallenge extends Die { - constructor(termData) { - termData.faces = 6; - super(termData); - } - - static DENOMINATION = 's'; - - /** @override */ - getResultLabel(result) { - return { - "1": '', - "2": '', - "3": '', - "4": '', - "5": '', - "6": '' - }[result.result]; - } - - static values = { - 1: 1, - 2: 2, - 3: 0, - 4: 0, - 5: "", - 6: "", - }; - - get total() { - if (!this._evaluated) return null; - return this.results.reduce((t, r) => { - if (!r.active) return t; - if (r.count !== undefined) return t + r.count; - return t + DieACChallenge.getValue(r.result); - }, 0); - } - - /** @override */ - roll(options) { - const roll = super.roll(options); - roll.effect = roll.result === 5 || roll.result === 6; - return roll; - } - - get resultValues() { - return this.results.map(result => { - return DieACChallenge.getResultLabel(result.result); - }); - } - - static getValue(dieSide) { - // 1 if Effect, otherwise take the value - return typeof DieACChallenge.values[dieSide] === 'string' - ? 1 - : DieACChallenge.values[dieSide]; - } - + constructor(termData) { + termData.faces = 6; + super(termData); + } + + static DENOMINATION = "s"; + + /** @override */ + getResultLabel(result) { + return { + 1: '', + 2: '', + 3: '', + 4: '', + 5: '', + 6: '', + }[result.result]; + } + + static values = { + 1: 1, + 2: 2, + 3: 0, + 4: 0, + 5: "", + 6: "", + }; + + get total() { + if (!this._evaluated) return null; + return this.results.reduce((t, r) => { + if (!r.active) return t; + if (r.count !== undefined) return t + r.count; + return t + DieACChallenge.getValue(r.result); + }, 0); + } + + /** @override */ + roll(options) { + const roll = super.roll(options); + roll.effect = roll.result === 5 || roll.result === 6; + return roll; + } + + get resultValues() { + return this.results.map(result => { + return DieACChallenge.getResultLabel(result.result); + }); + } + + static getValue(dieSide) { + // 1 if Effect, otherwise take the value + return typeof DieACChallenge.values[dieSide] === "string" + ? 1 + : DieACChallenge.values[dieSide]; + } } - diff --git a/system/src/roller/dialog2d20.js b/system/src/roller/dialog2d20.js index 45fb8a0..3cb1b5e 100644 --- a/system/src/roller/dialog2d20.js +++ b/system/src/roller/dialog2d20.js @@ -1,74 +1,109 @@ export class Dialog2d20 extends Dialog { + constructor( + rollName, + diceNum, + attribute, + skill, + focus, + complication, + actor, + prefAttribute, + actorId, + itemId, + dialogData={}, + options={} + ) { + super(dialogData, options); + this.rollName = rollName; + this.diceNum = diceNum; + this.attribute = attribute; + this.skill = skill; + this.focus = focus; + this.complication = complication; + this.actor = actor; + this.prefAttribute = prefAttribute; + this.actorId = actorId; + this.itemId = itemId; + this.options.classes = ["dice-icon"]; + } - constructor(rollName, diceNum, attribute, skill, focus, complication, actor, prefAttribute, actorId, itemId, dialogData = {}, options = {}) { - super(dialogData, options); - this.rollName = rollName; - this.diceNum = diceNum; - this.attribute = attribute; - this.skill = skill; - this.focus = focus; - this.complication = complication; - this.actor = actor; - this.prefAttribute = prefAttribute; - this.actorId = actorId; - this.itemId = itemId; - this.options.classes = ["dice-icon"]; - } + activateListeners(html) { + super.activateListeners(html); - //override - activateListeners(html) { - super.activateListeners(html); - html.ready((e) => { - this.markDiceNumber(html, this.diceNum); - }) - html.on('click', '.dice-icon', (e, i, a) => { - let index = e.currentTarget.dataset.index; - this.diceNum = parseInt(index); - this.markDiceNumber(html, this.diceNum); - }); - html.on('click', '.roll', (event) => { - let attr = html.find('[name="attribute"]').val(); - if (!attr) { - let attrAbr = html.find('.select-attribute').val(); - attr = this.actor.attributes[attrAbr].value; - } - let skill = html.find('[name="skill"]').val(); - let complication = html.find('[name="complication"]').val(); - let isFocus = html.find('[name="focus"]').is(':checked'); - game.ac2d20.Roller2D20.rollD20({ rollname: this.rollName, dicenum: this.diceNum, attribute: attr, skill: skill, focus: isFocus, complication: complication, actorId: this.actorId, itemId: this.itemId }) - }); - } + html.ready(e => { + this.markDiceNumber(html, this.diceNum); + }); - markDiceNumber(html) { - $(html).find('.dice-icon').removeClass('marked'); - $(html).find(`[data-index="${this.diceNum}"]`).addClass('marked'); - } + html.on("click", ".dice-icon", (e, i, a) => { + let index = e.currentTarget.dataset.index; + this.diceNum = parseInt(index); + this.markDiceNumber(html, this.diceNum); + }); - static async createDialog({ rollName = "Roll D20", diceNum = 2, attribute = 0, skill = 0, focus = false, complication = 20, actor = null, prefAttribute = null, actorId = null, itemId=null } = {}) { - let dialogData = {} - dialogData.rollName = rollName; - dialogData.diceNum = diceNum; - dialogData.attribute = attribute; - dialogData.skill = skill; - dialogData.focus = focus; - dialogData.complication = complication; - dialogData.attributes = ['agi', 'bra', 'coo', 'ins', 'rea', 'wil']; - dialogData.actor = actor; - dialogData.prefAttribute = prefAttribute; - dialogData.actorId = actorId; - dialogData.itemId = itemId; - const html = await renderTemplate("systems/ac2d20/templates/dialogs/dialog2d20.html", dialogData); - let d = new Dialog2d20(rollName, diceNum, attribute, skill, focus, complication, actor, prefAttribute, actorId, itemId, { - title: rollName, - content: html, - buttons: { - roll: { - icon: '', - label: "ROLL" - } - } - }); - d.render(true); - } -} \ No newline at end of file + html.on("click", ".roll", event => { + let attr = html.find('[name="attribute"]').val(); + if (!attr) { + let attrAbr = html.find(".select-attribute").val(); + attr = this.actor.attributes[attrAbr].value; + } + let skill = html.find('[name="skill"]').val(); + let complication = html.find('[name="complication"]').val(); + let isFocus = html.find('[name="focus"]').is(":checked"); + game.ac2d20.Roller2D20.rollD20({ + rollname: this.rollName, + dicenum: this.diceNum, + attribute: attr, + skill: skill, + focus: isFocus, + complication: complication, + actorId: this.actorId, + itemId: this.itemId, + }); + }); + } + + markDiceNumber(html) { + $(html).find(".dice-icon").removeClass("marked"); + $(html).find(`[data-index="${this.diceNum}"]`).addClass("marked"); + } + + static async createDialog({ rollName = "Roll D20", diceNum = 2, attribute = 0, skill = 0, focus = false, complication = 20, actor = null, prefAttribute = null, actorId = null, itemId=null } = {}) { + let dialogData = {}; + dialogData.rollName = rollName; + dialogData.diceNum = diceNum; + dialogData.attribute = attribute; + dialogData.skill = skill; + dialogData.focus = focus; + dialogData.complication = complication; + dialogData.attributes = ["agi", "bra", "coo", "ins", "rea", "wil"]; + dialogData.actor = actor; + dialogData.prefAttribute = prefAttribute; + dialogData.actorId = actorId; + dialogData.itemId = itemId; + const html = await renderTemplate("systems/ac2d20/templates/dialogs/dialog2d20.hbs", dialogData); + let d = new Dialog2d20( + rollName, + diceNum, + attribute, + skill, + focus, + complication, + actor, + prefAttribute, + actorId, + itemId, + { + title: rollName, + content: html, + buttons: { + roll: { + icon: '', + label: "ROLL", + }, + }, + } + ); + d.render(true); + } +} diff --git a/system/src/roller/dialogD6.js b/system/src/roller/dialogD6.js index 40d0f26..8713a50 100644 --- a/system/src/roller/dialogD6.js +++ b/system/src/roller/dialogD6.js @@ -1,43 +1,68 @@ export class DialogD6 extends Dialog { - constructor(rollName, diceNum, dialogData = {}, options = {}) { - super(dialogData, options); - this.rollName = rollName; - this.diceNum = diceNum; - this.options.classes = ["dice-icon"]; - } + constructor(rollName, diceNum, dialogData = {}, options = {}) { + super(dialogData, options); + this.rollName = rollName; + this.diceNum = diceNum; + this.options.classes = ["dice-icon"]; + } - static async createDialog({ rollName = "Challenge Roll", diceNum = 2, ac2d20Roll = null, itemId = null, actorId = null } = {}) { - let dialogData = {} - dialogData.rollName = rollName; - dialogData.diceNum = diceNum; - dialogData.ac2d20Roll = ac2d20Roll; - dialogData.itemId = itemId; - dialogData.actorId = actorId; - const html = `{{localize "AC2D20.TEMPLATES.SpellType"}}: {{localize (concat 'AC2D20.SPELL.SpellTypes.' spellType)}}
-{{localize "AC2D20.TEMPLATES.Skill"}}: {{skill}} ({{focus}})
-{{localize "AC2D20.TEMPLATES.Difficulty"}}: {{difficulty}}
-{{localize "AC2D20.TEMPLATES.Cost"}}: {{cost}} ({{costEffects}})
-{{localize "AC2D20.TEMPLATES.Duration"}}: {{duration}}
++ {{localize "AC2D20.TEMPLATES.Skill"}}: + {{skill}} + {{#if focus}} + ({{focus}}) + {{/if}} +
++ {{localize "AC2D20.TEMPLATES.Difficulty"}}: + {{difficulty}} +
++ {{localize "AC2D20.TEMPLATES.Cost"}}: + {{cost}} + {{#if costEffects}} + ({{costEffects}}) + {{/if}} +
++ {{localize "AC2D20.TEMPLATES.Duration"}}: + {{duration}} +
{{/if}} {{#if isSkill}} @@ -67,4 +84,4 @@