From eb1683e24d5bba75d9d35602c902346d0f1ee5c3 Mon Sep 17 00:00:00 2001 From: "J. Arena" Date: Wed, 27 May 2026 11:15:45 -0500 Subject: [PATCH] jspcd, dry, lint --- .cspell.json | 16 + .github/workflows/mega-linter.yml | 226 +++++++++++++ .jscpd.json | 15 + .mega-linter.yml | 24 ++ src/classes/components/_equipmentUtils.ts | 28 ++ .../active_effects/_activeEffectUtils.ts | 42 +++ .../mech/components/equipment/WeaponMod.ts | 22 +- .../mech/components/frame/CoreSystem.ts | 22 +- src/classes/npc/feature/NpcItem/NpcWeapon.ts | 22 +- .../pilot/components/reserves/Reserve.ts | 22 +- .../_components/ActiveModeSortBar.vue | 107 ++++++ .../active_mode/gm/EncounterManager.vue | 95 +----- .../gm/_components/AddFromShare.vue | 40 +-- src/features/active_mode/pc/SheetManager.vue | 98 +----- .../active_mode/pc/_components/SheetItem.vue | 39 +-- .../runner/_shared/_EndRoundDialog.vue | 43 +++ .../runner/_shared/_RunnerLeaveDialog.vue | 38 +++ .../runner/_shared/_RunnerOptionsHeader.vue | 74 ++++ .../runner/_shared/_runnerOptionsMixin.ts | 55 +++ .../runner/gm/EncounterPanels/MechPanel.vue | 51 +-- .../EncounterPanels/_CombatActionsBlock.vue | 28 ++ .../runner/gm/EncounterPanels/_PanelBase.vue | 138 ++------ .../_components/ActorTelemetry.vue | 28 +- .../_components/BaseActionsPanel.vue | 185 ++++++++++ .../_components/CombatStatblockExport.vue | 28 +- .../_components/DamageConditionSelector.vue | 8 +- .../_components/GmEndRoundPanel.vue | 40 +-- .../_components/NpcActionsPanel.vue | 184 ++-------- .../_components/PilotActionsPanel.vue | 237 +++---------- .../_components/StatusConditionItem.vue | 42 +++ .../_components/StatusConditionSelector.vue | 56 +-- .../_components/TrackableStatsComplex.vue | 47 +-- .../_components/TrackableStatsSimple.vue | 49 +-- .../_components/_StatblockJustifyOptions.vue | 33 ++ .../_components/_trackableStatsMixin.ts | 44 +++ .../loadouts/_PilotEquipCardBody.vue | 59 ++++ .../_components/loadouts/_aiControlButton.vue | 57 ++++ .../_components/loadouts/_deployButton.vue | 52 +-- .../loadouts/_equipCommandPanel.vue | 97 +----- .../_components/loadouts/_pilotArmorCard.vue | 75 +--- .../loadouts/_pilotEquipCombatCardMixin.ts | 32 ++ .../_components/loadouts/_pilotWeaponCard.vue | 78 +---- .../action_buttons/_barrageButtonMixin.ts | 23 ++ .../action_buttons/mechBarrageButton.vue | 23 +- .../action_buttons/npcBarrageButton.vue | 25 +- .../gm/EncounterPanels/encounter-panels.css | 7 + .../runner/gm/GMEncounterRunner.vue | 31 +- .../runner/gm/InfoPanels/GmOptionsPanel.vue | 129 +------ .../active_mode/runner/pilot/PilotRunner.vue | 31 +- .../runner/pilot/_components/PcEndRound.vue | 35 +- .../pilot/_components/PcOptionsPanel.vue | 130 +------ src/features/compendium/SearchBar.vue | 33 +- .../Views/CampaignLibrary/index.vue | 33 +- .../containers/campaignContentContainer.vue | 53 +-- .../Reference/_components/SrdViewDesktop.vue | 46 +-- .../Reference/_components/SrdViewMobile.vue | 46 +-- .../Reference/_components/_srdViewMixin.ts | 43 +++ .../components/CompendiumPageButton.vue | 19 +- .../components/compendium-card-base.css | 18 + .../components/views/CompendiumCard.vue | 19 +- src/features/compendium/search-bar.css | 32 ++ .../_components/PageContentContainer.vue | 53 +-- .../combatants/CombatantEditor.vue | 135 ++------ .../_components/combatants/CombatantGroup.vue | 60 ++++ .../_components/map/HexMapHorizontal.vue | 19 +- .../_components/map/HexMapVertical.vue | 19 +- .../encounters/_components/map/SquareMap.vue | 9 +- .../gm/encounters/_components/map/mapUtils.ts | 22 ++ .../gm/encounters/print/OptionsDialog.vue | 76 +---- .../print/components/PrintAction.vue | 51 --- .../gm/narrative/print/OptionsDialog.vue | 128 ++----- .../gm/narrative/print/PrintOptionSelect.vue | 74 ---- .../npcs/_components/NpcClassSelector.vue | 58 +--- .../_components/_npcClassSelectorMixin.ts | 60 ++++ src/features/gm/npc_roster/npcs/builder.vue | 58 +--- .../gm/npc_roster/print/OptionsDialog.vue | 151 ++------- .../gm/npc_roster/print/PrintOptionSelect.vue | 72 ---- .../npc_roster/print/extras/TagInfoPrint.vue | 39 +-- .../main_menu/_components/MassifLcpTable.vue | 320 ++---------------- .../components/CommunityTable.vue | 259 +------------- .../PilotSheet/MobileOptions.vue | 58 +--- .../PilotSheet/components/PilotEditMenu.vue | 61 +--- .../PilotSheet/pilotActionsMixin.ts | 62 ++++ .../pilot_management/Print/OptionsDialog.vue | 2 +- .../Print/PrintOptionSelect.vue | 72 ---- .../Print/components/PrintMechNameBlock.vue | 46 +++ .../Print/components/PrintStatBox.vue | 22 ++ .../Print/components/_PrintMechHpRows.vue | 97 ++++++ .../Print/extras/TagInfoPrint.vue | 38 +-- .../Print/layouts/_usePrintOptions.ts | 19 ++ .../Print/layouts/cards/PilotPrint.vue | 6 - .../Print/layouts/expanded/MechPrint.vue | 240 +------------ .../Print/layouts/expanded/PilotPrint.vue | 12 - .../Print/layouts/minimal/MechPrint.vue | 20 +- .../Print/layouts/minimal/PilotPrint.vue | 12 - .../Print/layouts/standard/MechPrint.vue | 301 ++-------------- .../Print/layouts/standard/PilotPrint.vue | 12 - .../Print/layouts/terse/MechPrint.vue | 15 - .../Print/layouts/terse/PilotPrint.vue | 12 - .../Roster/components/GroupMenu.vue | 24 +- .../Roster/components/GroupPanel.vue | 24 +- .../Roster/components/GroupShareDialog.vue | 39 +-- .../Roster/components/PilotListItem.vue | 39 +-- .../Roster/components/_GroupEmblemModal.vue | 27 ++ .../components/_SelectorFilterSwitches.vue | 39 +++ .../components/mount/weapon/_ModSelector.vue | 48 +-- .../mount/weapon/_WeaponSelector.vue | 25 +- .../components/system/_SystemSelector.vue | 32 +- .../loadout/pilot_loadout/_PLArmorCard.vue | 38 +-- .../loadout/pilot_loadout/_PLCardMixin.ts | 40 +++ .../loadout/pilot_loadout/_PLGearCard.vue | 38 +-- .../loadout/pilot_loadout/_PLWeaponCard.vue | 38 +-- .../link/_components/LinkSheetHaseBlock.vue | 104 ++++++ .../link/_components/LinkSheetMechHeader.vue | 25 ++ .../link/_components/LinkSheetPilotName.vue | 22 ++ .../link/_views/BuildLinkSheet.vue | 130 +------ .../link/_views/FullLinkSheet.vue | 130 +------ src/shared/ShareCodeDialog.vue | 39 +-- src/shared/ShareCodeResult.vue | 45 +++ src/shared/campaignColorOptions.ts | 51 +++ .../print/PrintOptionSelect.vue | 0 src/shared/print/PrintOptionsBase.vue | 93 +++++ .../CompendiumBrowser/views/_selectorBar.vue | 71 +--- .../views/_selectorScatter.vue | 72 +--- .../CompendiumBrowser/views/_selectorUtils.ts | 79 +++++ src/ui/components/LcpTable.vue | 288 ++++++++++++++++ .../buttons/subcomponents/_btnSubMixin.ts | 51 +++ .../buttons/subcomponents/cc_btn_base.css | 46 +++ .../buttons/subcomponents/cc_btn_block.vue | 6 +- .../subcomponents/cc_btn_flat_size.css | 36 ++ .../buttons/subcomponents/cc_btn_icon.vue | 6 +- .../buttons/subcomponents/cc_btn_std.vue | 112 +----- .../buttons/subcomponents/cc_btn_stk.vue | 90 +---- .../buttons/subcomponents/cc_btn_text.vue | 85 +---- .../buttons/subcomponents/cc_btn_tonal.vue | 111 +----- .../components/chips/CCCombatActionChip.vue | 69 ++-- .../chips/_CombatActionIndicator.vue | 45 +++ .../_shared/AccuracyDifficultyRow.vue | 84 +++++ .../_shared/CheckRollInterface.vue | 73 +--- .../_shared/SaveRollInterface.vue | 73 +--- .../headings/headings/cc_heading_base.css | 11 + .../headings/headings/cc_heading_filled.vue | 78 ----- .../headings/headings/cc_heading_minor.vue | 14 +- .../inputs/tickbar/_TickbarActivator.vue | 96 ++++++ .../components/inputs/tickbar/_bottomBar.vue | 128 +------ .../components/inputs/tickbar/_centerBar.vue | 15 +- .../inputs/tickbar/_tickbarMixin.ts | 46 +++ src/ui/components/inputs/tickbar/_topBar.vue | 147 ++------ src/ui/components/inputs/tickbar/tickbar.css | 13 + .../panels/filters/MechItemFilterBase.vue | 109 ++++++ .../panels/filters/_MechSystemFilter.vue | 95 +----- .../panels/filters/_MechWeaponFilter.vue | 107 +----- src/ui/components/print/TagInfoDisplay.vue | 35 ++ src/ui/components/tables/CCRefStressTable.vue | 252 ++++++-------- .../components/tables/CCRefStructureTable.vue | 242 ++++++------- .../components/tables/_RefRollTableBase.vue | 76 +++++ src/ui/style/pilot-list-item.css | 38 +++ 157 files changed, 4035 insertions(+), 6176 deletions(-) create mode 100644 .cspell.json create mode 100644 .github/workflows/mega-linter.yml create mode 100644 .jscpd.json create mode 100644 .mega-linter.yml create mode 100644 src/classes/components/_equipmentUtils.ts create mode 100644 src/classes/components/feature/active_effects/_activeEffectUtils.ts create mode 100644 src/features/active_mode/_components/ActiveModeSortBar.vue create mode 100644 src/features/active_mode/runner/_shared/_EndRoundDialog.vue create mode 100644 src/features/active_mode/runner/_shared/_RunnerLeaveDialog.vue create mode 100644 src/features/active_mode/runner/_shared/_RunnerOptionsHeader.vue create mode 100644 src/features/active_mode/runner/_shared/_runnerOptionsMixin.ts create mode 100644 src/features/active_mode/runner/gm/EncounterPanels/_CombatActionsBlock.vue create mode 100644 src/features/active_mode/runner/gm/EncounterPanels/_components/BaseActionsPanel.vue create mode 100644 src/features/active_mode/runner/gm/EncounterPanels/_components/StatusConditionItem.vue create mode 100644 src/features/active_mode/runner/gm/EncounterPanels/_components/_StatblockJustifyOptions.vue create mode 100644 src/features/active_mode/runner/gm/EncounterPanels/_components/_trackableStatsMixin.ts create mode 100644 src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_PilotEquipCardBody.vue create mode 100644 src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_aiControlButton.vue create mode 100644 src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_pilotEquipCombatCardMixin.ts create mode 100644 src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/action_buttons/_barrageButtonMixin.ts create mode 100644 src/features/active_mode/runner/gm/EncounterPanels/encounter-panels.css create mode 100644 src/features/compendium/Views/Reference/_components/_srdViewMixin.ts create mode 100644 src/features/compendium/components/compendium-card-base.css create mode 100644 src/features/compendium/search-bar.css create mode 100644 src/features/gm/encounters/_components/combatants/CombatantGroup.vue create mode 100644 src/features/gm/encounters/_components/map/mapUtils.ts delete mode 100644 src/features/gm/encounters/print/components/PrintAction.vue delete mode 100644 src/features/gm/narrative/print/PrintOptionSelect.vue create mode 100644 src/features/gm/npc_roster/npcs/_components/_npcClassSelectorMixin.ts delete mode 100644 src/features/gm/npc_roster/print/PrintOptionSelect.vue create mode 100644 src/features/pilot_management/PilotSheet/pilotActionsMixin.ts delete mode 100644 src/features/pilot_management/Print/PrintOptionSelect.vue create mode 100644 src/features/pilot_management/Print/components/PrintMechNameBlock.vue create mode 100644 src/features/pilot_management/Print/components/PrintStatBox.vue create mode 100644 src/features/pilot_management/Print/components/_PrintMechHpRows.vue create mode 100644 src/features/pilot_management/Roster/components/_GroupEmblemModal.vue create mode 100644 src/features/pilot_management/_components/loadout/mech_loadout/components/_SelectorFilterSwitches.vue create mode 100644 src/features/pilot_management/_components/loadout/pilot_loadout/_PLCardMixin.ts create mode 100644 src/features/pilot_management/link/_components/LinkSheetHaseBlock.vue create mode 100644 src/features/pilot_management/link/_components/LinkSheetMechHeader.vue create mode 100644 src/features/pilot_management/link/_components/LinkSheetPilotName.vue create mode 100644 src/shared/ShareCodeResult.vue create mode 100644 src/shared/campaignColorOptions.ts rename src/{features/gm/encounters => shared}/print/PrintOptionSelect.vue (100%) create mode 100644 src/shared/print/PrintOptionsBase.vue create mode 100644 src/ui/components/CompendiumBrowser/views/_selectorUtils.ts create mode 100644 src/ui/components/LcpTable.vue create mode 100644 src/ui/components/buttons/subcomponents/_btnSubMixin.ts create mode 100644 src/ui/components/buttons/subcomponents/cc_btn_base.css create mode 100644 src/ui/components/buttons/subcomponents/cc_btn_flat_size.css create mode 100644 src/ui/components/chips/_CombatActionIndicator.vue create mode 100644 src/ui/components/chips/_activeeffect/_shared/AccuracyDifficultyRow.vue create mode 100644 src/ui/components/headings/headings/cc_heading_base.css delete mode 100644 src/ui/components/headings/headings/cc_heading_filled.vue create mode 100644 src/ui/components/inputs/tickbar/_TickbarActivator.vue create mode 100644 src/ui/components/inputs/tickbar/_tickbarMixin.ts create mode 100644 src/ui/components/inputs/tickbar/tickbar.css create mode 100644 src/ui/components/panels/filters/MechItemFilterBase.vue create mode 100644 src/ui/components/print/TagInfoDisplay.vue create mode 100644 src/ui/components/tables/_RefRollTableBase.vue create mode 100644 src/ui/style/pilot-list-item.css diff --git a/.cspell.json b/.cspell.json new file mode 100644 index 000000000..b798d2932 --- /dev/null +++ b/.cspell.json @@ -0,0 +1,16 @@ +{ + "ignorePaths": [ + "**/node_modules/**", + "**/vscode-extension/**", + "**/.git/**", + "**/.pnpm-lock.json", + ".vscode", + "megalinter", + "package-lock.json", + "report" + ], + "language": "en", + "noConfigSearch": true, + "words": ["megalinter", "oxsecurity"], + "version": "0.2" +} diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml new file mode 100644 index 000000000..0b0b2e7e5 --- /dev/null +++ b/.github/workflows/mega-linter.yml @@ -0,0 +1,226 @@ +# MegaLinter GitHub Action configuration file +# More info at https://megalinter.io +--- +name: MegaLinter + +# Trigger mega-linter at every push. Action will also be visible from +# Pull Requests to main +on: + # Comment this line to trigger action only on pull-requests + # (not recommended if you don't pay for GH Actions) + push: + + pull_request: + branches: + - main + - master + +# Comment env block if you do not want to apply fixes +env: + # Apply linter fixes configuration + # + # When active, APPLY_FIXES must also be defined as environment variable + # (in github/workflows/mega-linter.yml or other CI tool) + APPLY_FIXES: none + + # Decide which event triggers application of fixes in a commit or a PR + # (pull_request, push, all) + APPLY_FIXES_EVENT: pull_request + + # If APPLY_FIXES is used, defines if the fixes are directly committed (commit) + # or posted in a PR (pull_request) + APPLY_FIXES_MODE: commit + +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +permissions: {} + +jobs: + megalinter: + name: MegaLinter + runs-on: ubuntu-latest + + # Give the default GITHUB_TOKEN write permission to commit and push, comment + # issues, and post new Pull Requests; remove the ones you do not need + permissions: + contents: write + issues: write + pull-requests: write + + steps: + # Git Checkout + - name: Checkout Code + uses: actions/checkout@v6 + with: + # SECURITY NOTE: Using a Personal Access Token (PAT) is NOT + # recommended. Open-source projects have been heavily targeted by + # supply-chain attacks in recent months, and a leaked PAT can give + # attackers broad write access to your repository — better safe + # than sorry! If you only need workflows to re-trigger after + # MegaLinter applies fixes, prefer one of these safer alternatives: + # - Manually re-run the workflow from the GitHub Actions tab, or + # - Push another commit on the branch to trigger workflows again. + # Only define `secrets.PAT` if you fully understand the trade-off. + token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} + persist-credentials: false # Comment this line and uncomment the next one if you use APPLY_FIXES + # persist-credentials: true # zizmor: ignore[artipacked] + + # If you use VALIDATE_ALL_CODEBASE = true, you can remove this line to + # improve performance + fetch-depth: 0 + + # MegaLinter + - name: MegaLinter + + # You can override MegaLinter flavor used to have faster performances + # More info at https://megalinter.io/latest/flavors/ + uses: oxsecurity/megalinter/flavors/javascript@v9 + + id: ml + + # All available variables are described in documentation + # https://megalinter.io/latest/config-file/ + env: + # Validates all source when push on main, else just the git diff with + # main. Override with true if you always want to lint all sources + # + # To validate the entire codebase, set to: + # VALIDATE_ALL_CODEBASE: true + # + # To validate only diff with main, set to: + # VALIDATE_ALL_CODEBASE: >- + # ${{ + # github.event_name == 'push' && + # github.ref == 'refs/heads/main' + # }} + VALIDATE_ALL_CODEBASE: true + + # Disable LLM Advisor for bot PRs (dependabot, renovate, etc.) + LLM_ADVISOR_ENABLED: >- + ${{ + github.event_name != 'pull_request' || + (github.event.pull_request.user.login != 'dependabot[bot]' && + github.event.pull_request.user.login != 'renovate[bot]' && + github.event.pull_request.user.login != 'github-actions[bot]' && + !startsWith(github.event.pull_request.user.login, 'dependabot') && + !startsWith(github.event.pull_request.user.login, 'renovate')) + }} + + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Uncomment to use ApiReporter (Grafana) + # API_REPORTER: true + # API_REPORTER_URL: ${{ secrets.API_REPORTER_URL }} + # API_REPORTER_BASIC_AUTH_USERNAME: ${{ secrets.API_REPORTER_BASIC_AUTH_USERNAME }} + # API_REPORTER_BASIC_AUTH_PASSWORD: ${{ secrets.API_REPORTER_BASIC_AUTH_PASSWORD }} + # API_REPORTER_METRICS_URL: ${{ secrets.API_REPORTER_METRICS_URL }} + # API_REPORTER_METRICS_BASIC_AUTH_USERNAME: ${{ secrets.API_REPORTER_METRICS_BASIC_AUTH_USERNAME }} + # API_REPORTER_METRICS_BASIC_AUTH_PASSWORD: ${{ secrets.API_REPORTER_METRICS_BASIC_AUTH_PASSWORD }} + # API_REPORTER_DEBUG: false + + # ADD YOUR CUSTOM ENV VARIABLES HERE TO OVERRIDE VALUES OF + # .mega-linter.yml AT THE ROOT OF YOUR REPOSITORY + + # Upload MegaLinter artifacts + - name: Archive production artifacts + uses: actions/upload-artifact@v7 + if: success() || failure() + with: + name: MegaLinter reports + include-hidden-files: "true" + path: | + megalinter-reports + mega-linter.log + + # Create pull request if applicable + # (for now works only on PR from same repository, not from forks) + - name: Create Pull Request with applied fixes + uses: peter-evans/create-pull-request@v7 + id: cpr + if: >- + steps.ml.outputs.has_updated_sources == 1 && + ( + env.APPLY_FIXES_EVENT == 'all' || + env.APPLY_FIXES_EVENT == github.event_name + ) && + env.APPLY_FIXES_MODE == 'pull_request' && + ( + github.event_name == 'push' || + github.event.pull_request.head.repo.full_name == github.repository + ) && + !contains(github.event.head_commit.message, 'skip fix') + with: + # SECURITY NOTE: see the warning on the checkout step above — + # using `secrets.PAT` is NOT recommended for security reasons. + # Prefer manually re-running the workflow or pushing another + # commit on the branch to trigger workflows again. + token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} + commit-message: "[MegaLinter] Apply linters automatic fixes" + title: "[MegaLinter] Apply linters automatic fixes" + labels: bot + + - name: Create PR output + if: >- + steps.ml.outputs.has_updated_sources == 1 && + ( + env.APPLY_FIXES_EVENT == 'all' || + env.APPLY_FIXES_EVENT == github.event_name + ) && + env.APPLY_FIXES_MODE == 'pull_request' && + ( + github.event_name == 'push' || + github.event.pull_request.head.repo.full_name == github.repository + ) && + !contains(github.event.head_commit.message, 'skip fix') + env: + PR_NUMBER: ${{ steps.cpr.outputs.pull-request-number }} + PR_URL: ${{ steps.cpr.outputs.pull-request-url }} + run: | + echo "PR Number - ${PR_NUMBER}" + echo "PR URL - ${PR_URL}" + + # Push new commit if applicable + # (for now works only on PR from same repository, not from forks) + - name: Prepare commit + if: >- + steps.ml.outputs.has_updated_sources == 1 && + ( + env.APPLY_FIXES_EVENT == 'all' || + env.APPLY_FIXES_EVENT == github.event_name + ) && + env.APPLY_FIXES_MODE == 'commit' && + github.ref != 'refs/heads/main' && + ( + github.event_name == 'push' || + github.event.pull_request.head.repo.full_name == github.repository + ) && + !contains(github.event.head_commit.message, 'skip fix') + run: sudo chown -Rc $UID .git/ + + - name: Commit and push applied linter fixes + uses: stefanzweifel/git-auto-commit-action@v7 + if: >- + steps.ml.outputs.has_updated_sources == 1 && + ( + env.APPLY_FIXES_EVENT == 'all' || + env.APPLY_FIXES_EVENT == github.event_name + ) && + env.APPLY_FIXES_MODE == 'commit' && + github.ref != 'refs/heads/main' && + ( + github.event_name == 'push' || + github.event.pull_request.head.repo.full_name == github.repository + ) && + !contains(github.event.head_commit.message, 'skip fix') + with: + branch: >- + ${{ + github.event.pull_request.head.ref || + github.head_ref || + github.ref + }} + commit_message: "[MegaLinter] Apply linters fixes" + commit_user_name: megalinter-bot + commit_user_email: 129584137+megalinter-bot@users.noreply.github.com diff --git a/.jscpd.json b/.jscpd.json new file mode 100644 index 000000000..2cee5f5d5 --- /dev/null +++ b/.jscpd.json @@ -0,0 +1,15 @@ +{ + "threshold": 0, + "reporters": ["html", "markdown"], + "ignore": [ + "**/node_modules/**", + "**/.git/**", + "**/.rbenv/**", + "**/.venv/**", + "**/*cache*/**", + "**/.github/**", + "**/.idea/**", + "**/report/**", + "**/*.svg" + ] +} diff --git a/.mega-linter.yml b/.mega-linter.yml new file mode 100644 index 000000000..367b5e15b --- /dev/null +++ b/.mega-linter.yml @@ -0,0 +1,24 @@ +# Configuration file for MegaLinter +# +# See all available variables at https://megalinter.io/latest/config-file/ and in +# linters documentation +--- +# all, none, or list of linter keys +APPLY_FIXES: none + +# If you use ENABLE variable, all other languages/formats/tooling-formats will +# be disabled by default +# ENABLE: + +# If you use ENABLE_LINTERS variable, all other linters will be disabled by +# default +# ENABLE_LINTERS: + +# DISABLE: + # - COPYPASTE # Uncomment to disable checks of excessive copy-pastes + # - SPELL # Uncomment to disable checks of spelling mistakes + +SHOW_ELAPSED_TIME: true + +# Uncomment if you want MegaLinter to detect errors but not block CI to pass +# DISABLE_ERRORS: true diff --git a/src/classes/components/_equipmentUtils.ts b/src/classes/components/_equipmentUtils.ts new file mode 100644 index 000000000..88d88c044 --- /dev/null +++ b/src/classes/components/_equipmentUtils.ts @@ -0,0 +1,28 @@ +import { CompendiumStore } from '@/features/compendium/store' +import { CompendiumItem } from '../CompendiumItem' +import { MechEquipment } from '../mech/components/equipment/MechEquipment' + +export function resolveSpecialEquipment(ids: string[]): CompendiumItem[] { + if (!ids) return [] + const res = ids.map(x => { + const w = CompendiumStore().MechWeapons.find(item => item.ID === x) + if (w) return w + const s = CompendiumStore().MechSystems.find(item => item.ID === x) + if (s) return s + const wm = CompendiumStore().WeaponMods.find(item => item.ID === x) + if (wm) return wm + const pg = CompendiumStore().PilotGear.find((item: any) => item.ID === x) + if (pg) return pg + return false + }) + return res as CompendiumItem[] +} + +export function resolveIntegratedEquipment(ids: string[]): MechEquipment[] { + if (!ids) return [] + return ids.map(x => { + const w = CompendiumStore().MechWeapons.find(item => item.ID === x) + if (w) return w as MechEquipment + return CompendiumStore().MechSystems.find(item => item.ID === x) as MechEquipment + }) as MechEquipment[] +} diff --git a/src/classes/components/feature/active_effects/_activeEffectUtils.ts b/src/classes/components/feature/active_effects/_activeEffectUtils.ts new file mode 100644 index 000000000..5eaa9bf92 --- /dev/null +++ b/src/classes/components/feature/active_effects/_activeEffectUtils.ts @@ -0,0 +1,42 @@ +import { ActiveEffect, IActiveEffectData } from './ActiveEffect' + +interface IActiveEffectCallbackData { + on_miss?: string | IActiveEffectData + on_attack?: string | IActiveEffectData + on_hit?: string | IActiveEffectData + on_crit?: string | IActiveEffectData +} + +interface IActiveEffectCallbackTarget { + OnMiss?: ActiveEffect + OnAttack?: ActiveEffect + OnHit?: ActiveEffect + OnCrit?: ActiveEffect +} + +export function initActiveEffectCallbacks( + data: IActiveEffectCallbackData, + target: IActiveEffectCallbackTarget, + owner: any +): void { + if (data.on_miss) { + if (typeof data.on_miss === 'string') + target.OnMiss = new ActiveEffect({ name: 'On Miss Effect', detail: data.on_miss }, owner) + else target.OnMiss = new ActiveEffect(data.on_miss, owner) + } + if (data.on_attack) { + if (typeof data.on_attack === 'string') + target.OnAttack = new ActiveEffect({ name: 'On Attack Effect', detail: data.on_attack }, owner) + else target.OnAttack = new ActiveEffect(data.on_attack, owner) + } + if (data.on_hit) { + if (typeof data.on_hit === 'string') + target.OnHit = new ActiveEffect({ name: 'On Hit Effect', detail: data.on_hit }, owner) + else target.OnHit = new ActiveEffect(data.on_hit, owner) + } + if (data.on_crit) { + if (typeof data.on_crit === 'string') + target.OnCrit = new ActiveEffect({ name: 'On Crit Effect', detail: data.on_crit }, owner) + else target.OnCrit = new ActiveEffect(data.on_crit, owner) + } +} diff --git a/src/classes/mech/components/equipment/WeaponMod.ts b/src/classes/mech/components/equipment/WeaponMod.ts index 14d6f104a..0ff49015e 100644 --- a/src/classes/mech/components/equipment/WeaponMod.ts +++ b/src/classes/mech/components/equipment/WeaponMod.ts @@ -9,6 +9,7 @@ import { ActiveEffect, IActiveEffectData, } from '@/classes/components/feature/active_effects/ActiveEffect' +import { initActiveEffectCallbacks } from '@/classes/components/feature/active_effects/_activeEffectUtils' interface IWeaponModData extends IMechEquipmentData { allowed_types?: WeaponType[] @@ -62,26 +63,7 @@ class WeaponMod extends MechEquipment { this.AddedRange = data.added_range ? data.added_range.map(x => new Range(x)) : [] - if (data.on_miss) { - if (typeof data.on_miss === 'string') - this.OnMiss = new ActiveEffect({ name: 'On Miss Effect', detail: data.on_miss }, this) - else this.OnMiss = new ActiveEffect(data.on_miss, this) - } - if (data.on_attack) { - if (typeof data.on_attack === 'string') - this.OnAttack = new ActiveEffect({ name: 'On Attack Effect', detail: data.on_attack }, this) - else this.OnAttack = new ActiveEffect(data.on_attack, this) - } - if (data.on_hit) { - if (typeof data.on_hit === 'string') - this.OnHit = new ActiveEffect({ name: 'On Hit Effect', detail: data.on_hit }, this) - else this.OnHit = new ActiveEffect(data.on_hit, this) - } - if (data.on_crit) { - if (typeof data.on_crit === 'string') - this.OnCrit = new ActiveEffect({ name: 'On Crit Effect', detail: data.on_crit }, this) - else this.OnCrit = new ActiveEffect(data.on_crit, this) - } + initActiveEffectCallbacks(data, this, this) this.ItemType = ItemType.WeaponMod } diff --git a/src/classes/mech/components/frame/CoreSystem.ts b/src/classes/mech/components/frame/CoreSystem.ts index 02e7437c4..c7dfd75f0 100644 --- a/src/classes/mech/components/frame/CoreSystem.ts +++ b/src/classes/mech/components/frame/CoreSystem.ts @@ -2,6 +2,7 @@ import { CompendiumStore } from '@/features/compendium/store' import { ActivationType, Duration } from '../../../enums' import { MechSystem } from '../equipment/MechSystem' import { MechWeapon } from '../equipment/MechWeapon' +import { resolveSpecialEquipment, resolveIntegratedEquipment } from '../../../components/_equipmentUtils' import Tag, { ITagData } from '../../../Tag' import { IActionData, Action } from '../../../Action' import { IBonusData, Bonus } from '../../../components/feature/bonus/Bonus' @@ -161,28 +162,11 @@ class CoreSystem { } public get SpecialEquipment(): CompendiumItem[] { - if (!this._special_equipment) return [] - const res = this._special_equipment.map(x => { - const w = CompendiumStore().MechWeapons.find(item => item.ID === x) - if (w) return w - const s = CompendiumStore().MechSystems.find(item => item.ID === x) - if (s) return s - const wm = CompendiumStore().WeaponMods.find(item => item.ID === x) - if (wm) return wm - const pg = CompendiumStore().PilotGear.find((item: any) => item.ID === x) - if (pg) return pg - return false - }) - return res as CompendiumItem[] + return resolveSpecialEquipment(this._special_equipment) } public get IntegratedEquipment(): MechEquipment[] { - if (!this._integrated) return [] - return this._integrated.map(x => { - const w = CompendiumStore().MechWeapons.find(item => item.ID === x) - if (w) return w as MechEquipment - return CompendiumStore().MechSystems.find(item => item.ID === x) as MechEquipment - }) as MechEquipment[] + return resolveIntegratedEquipment(this._integrated) } public get PassiveIntegratedWeapons(): MechWeapon[] { diff --git a/src/classes/npc/feature/NpcItem/NpcWeapon.ts b/src/classes/npc/feature/NpcItem/NpcWeapon.ts index c6744eae6..7ecc9d6aa 100644 --- a/src/classes/npc/feature/NpcItem/NpcWeapon.ts +++ b/src/classes/npc/feature/NpcItem/NpcWeapon.ts @@ -7,6 +7,7 @@ import { ActiveEffect, IActiveEffectData, } from '@/classes/components/feature/active_effects/ActiveEffect' +import { initActiveEffectCallbacks } from '@/classes/components/feature/active_effects/_activeEffectUtils' import { Eidolon } from '../../eidolon/Eidolon' import { Unit } from '../../unit/Unit' @@ -49,26 +50,7 @@ export class NpcWeapon extends NpcFeature { this._range = data.range.map(x => new Range(x)) this._weapon_type = data.weapon_type - if (data.on_miss) { - if (typeof data.on_miss === 'string') - this.OnMiss = new ActiveEffect({ name: 'On Miss Effect', detail: data.on_miss }, this) - else this.OnMiss = new ActiveEffect(data.on_miss, this) - } - if (data.on_attack) { - if (typeof data.on_attack === 'string') - this.OnAttack = new ActiveEffect({ name: 'On Attack Effect', detail: data.on_attack }, this) - else this.OnAttack = new ActiveEffect(data.on_attack, this) - } - if (data.on_hit) { - if (typeof data.on_hit === 'string') - this.OnHit = new ActiveEffect({ name: 'On Hit Effect', detail: data.on_hit }, this) - else this.OnHit = new ActiveEffect(data.on_hit, this) - } - if (data.on_crit) { - if (typeof data.on_crit === 'string') - this.OnCrit = new ActiveEffect({ name: 'On Crit Effect', detail: data.on_crit }, this) - else this.OnCrit = new ActiveEffect(data.on_crit, this) - } + initActiveEffectCallbacks(data, this, this) this.Attacks = this._expand(data.attacks) this._accuracy = this._expand(data.accuracy) this._attack_bonus = this._expand(data.attack_bonus) diff --git a/src/classes/pilot/components/reserves/Reserve.ts b/src/classes/pilot/components/reserves/Reserve.ts index 9acf113df..38edac5ac 100644 --- a/src/classes/pilot/components/reserves/Reserve.ts +++ b/src/classes/pilot/components/reserves/Reserve.ts @@ -1,5 +1,6 @@ import { CompendiumStore } from '@/features/compendium/store' import { CompendiumItem } from '../../../CompendiumItem' +import { resolveSpecialEquipment, resolveIntegratedEquipment } from '../../../components/_equipmentUtils' import { ISynergyData, Synergy } from '../../../components/feature/synergy/Synergy' import { ContentPack } from '../../../ContentPack' import { ReserveType, ItemType } from '../../../enums' @@ -82,28 +83,11 @@ class Reserve extends CompendiumItem { } public get SpecialEquipment(): CompendiumItem[] { - if (!this._special_equipment) return [] - const res = this._special_equipment.map(x => { - const w = CompendiumStore().MechWeapons.find(item => item.ID === x) - if (w) return w - const s = CompendiumStore().MechSystems.find(item => item.ID === x) - if (s) return s - const wm = CompendiumStore().WeaponMods.find(item => item.ID === x) - if (wm) return wm - const pg = CompendiumStore().PilotGear.find((item: any) => item.ID === x) - if (pg) return pg - return false - }) - return res as CompendiumItem[] + return resolveSpecialEquipment(this._special_equipment) } public get IntegratedEquipment(): MechEquipment[] { - if (!this._integrated) return [] - return this._integrated.map(x => { - const w = CompendiumStore().MechWeapons.find(item => item.ID === x) - if (w) return w as MechEquipment - return CompendiumStore().MechSystems.find(item => item.ID === x) as MechEquipment - }) as MechEquipment[] + return resolveIntegratedEquipment(this._integrated) } public get IntegratedWeapons(): MechWeapon[] { diff --git a/src/features/active_mode/_components/ActiveModeSortBar.vue b/src/features/active_mode/_components/ActiveModeSortBar.vue new file mode 100644 index 000000000..e9d909074 --- /dev/null +++ b/src/features/active_mode/_components/ActiveModeSortBar.vue @@ -0,0 +1,107 @@ + + + diff --git a/src/features/active_mode/gm/EncounterManager.vue b/src/features/active_mode/gm/EncounterManager.vue index b8cbceccf..054e2d2e1 100644 --- a/src/features/active_mode/gm/EncounterManager.vue +++ b/src/features/active_mode/gm/EncounterManager.vue @@ -2,82 +2,14 @@
Local Active Encounters
- - -
- - - Sort by Recent - - - - - Sort by Name - - - - - Sort by created timestamp - -
-
- - - -
+ @@ -428,7 +360,7 @@ import { ref, computed } from 'vue'; import { useDisplay } from 'vuetify'; import { useRouter } from 'vue-router'; -import ActiveModeOrganizer from '@/features/active_mode/_components/ActiveModeOrganizer.vue'; +import ActiveModeSortBar from '@/features/active_mode/_components/ActiveModeSortBar.vue'; import { CombatLog } from '@/classes/components/combat/CombatLog'; import { ActionSummary } from '@/classes/components/feature/active_effects/EffectActionSummary'; import { Encounter } from '@/classes/encounter/Encounter'; @@ -500,15 +432,6 @@ const deleted = computed(() => EncounterStore().ActiveEncounters.filter((e) => e.SaveController.IsDeleted) ); -function setSort(field: string) { - if (sort.value === field) { - asc.value = !asc.value; - } else { - sort.value = field; - asc.value = true; - } -} - async function launch(encounter: any) { await EncounterStore().AssignActiveEncounter(encounter); router.push(`gm-encounter-runner/${encounter.ID}`); diff --git a/src/features/active_mode/gm/_components/AddFromShare.vue b/src/features/active_mode/gm/_components/AddFromShare.vue index 532f7d631..d938f046c 100644 --- a/src/features/active_mode/gm/_components/AddFromShare.vue +++ b/src/features/active_mode/gm/_components/AddFromShare.vue @@ -7,43 +7,7 @@ :remote-items="remoteItems" @set-query-result="queryResult = $event"> - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - @@ -425,6 +352,15 @@ export default { return ['attackBonus', 'grapple', 'ram'] }, + statColumns() { + const spacer = { key: '__spacer__' } + const g1 = this.item.StatController.GetStatCollection(['hull', 'agi', 'sys', 'eng']) + const g2 = this.item.StatController.GetStatCollection(['evasion', 'edef', 'techAttack', 'sensorRange', 'saveTarget']) + const g3 = this.item.StatController.GetStatCollection(this.extraStatSet).filter((x: any) => this.item.StatController.MaxStats[x.key]) + const g4 = this.item.StatController.CustomStats(this.item.ItemType) + return [...g1, spacer, ...g2, ...g3, ...g4] + }, + mobile() { return this.$vuetify.display.mdAndDown; @@ -477,11 +413,5 @@ export default { diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/ActorTelemetry.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/ActorTelemetry.vue index 72ac7c219..ceb3bc75b 100644 --- a/src/features/active_mode/runner/gm/EncounterPanels/_components/ActorTelemetry.vue +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/ActorTelemetry.vue @@ -23,30 +23,8 @@ forthcoming. Telemetry data is collected at the end of every round - - - - - - -
- -
-
-
-
+ import { CombatLog } from '@/classes/components/combat/CombatLog'; +import StatblockJustifyOptions from './_StatblockJustifyOptions.vue'; export default { name: 'ActorLogs', + components: { StatblockJustifyOptions }, props: { actor: { type: Object, diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/BaseActionsPanel.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/BaseActionsPanel.vue new file mode 100644 index 000000000..ce04e4bd5 --- /dev/null +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/BaseActionsPanel.vue @@ -0,0 +1,185 @@ + + + + + diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/CombatStatblockExport.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/CombatStatblockExport.vue index 620e1f341..f480a6286 100644 --- a/src/features/active_mode/runner/gm/EncounterPanels/_components/CombatStatblockExport.vue +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/CombatStatblockExport.vue @@ -16,30 +16,8 @@ diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/GmEndRoundPanel.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/GmEndRoundPanel.vue index 204454348..b0d327f76 100644 --- a/src/features/active_mode/runner/gm/EncounterPanels/_components/GmEndRoundPanel.vue +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/GmEndRoundPanel.vue @@ -1,38 +1,7 @@ - - diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/PilotActionsPanel.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/PilotActionsPanel.vue index 85d657e24..df1920dbc 100644 --- a/src/features/active_mode/runner/gm/EncounterPanels/_components/PilotActionsPanel.vue +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/PilotActionsPanel.vue @@ -1,186 +1,64 @@ - diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/StatusConditionItem.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/StatusConditionItem.vue new file mode 100644 index 000000000..2ae7e5fa7 --- /dev/null +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/StatusConditionItem.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/StatusConditionSelector.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/StatusConditionSelector.vue index a1af72666..80d3c002e 100644 --- a/src/features/active_mode/runner/gm/EncounterPanels/_components/StatusConditionSelector.vue +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/StatusConditionSelector.vue @@ -4,59 +4,19 @@ - - -
{{ status.Name }}
- {{ status.Terse || status.Effects }} -
+
- - -
{{ status.Name }}
- - {{ appliedStatus(status) }} - - {{ status.Terse || status.Effects }} -
+
@@ -140,9 +100,11 @@ import * as _ from 'lodash-es'; import { CompendiumStore } from '@/stores'; import { useMobile } from '@/composables/useMobile'; +import StatusConditionItem from './StatusConditionItem.vue'; export default { name: 'StatusConditionSelector', + components: { StatusConditionItem }, mixins: [useMobile], props: { controller: { diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/TrackableStatsComplex.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/TrackableStatsComplex.vue index 07d60dd6d..07bac5496 100644 --- a/src/features/active_mode/runner/gm/EncounterPanels/_components/TrackableStatsComplex.vue +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/TrackableStatsComplex.vue @@ -125,65 +125,24 @@ \ No newline at end of file diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/TrackableStatsSimple.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/TrackableStatsSimple.vue index 3bc0d8466..bd6352ce9 100644 --- a/src/features/active_mode/runner/gm/EncounterPanels/_components/TrackableStatsSimple.vue +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/TrackableStatsSimple.vue @@ -156,64 +156,23 @@ \ No newline at end of file diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/_StatblockJustifyOptions.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/_StatblockJustifyOptions.vue new file mode 100644 index 000000000..401fed250 --- /dev/null +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/_StatblockJustifyOptions.vue @@ -0,0 +1,33 @@ + + + diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/_trackableStatsMixin.ts b/src/features/active_mode/runner/gm/EncounterPanels/_components/_trackableStatsMixin.ts new file mode 100644 index 000000000..dc5a754a3 --- /dev/null +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/_trackableStatsMixin.ts @@ -0,0 +1,44 @@ +import { Rules } from '@/classes/utility/Rules'; + +export const trackableStatsMixin = { + data: () => ({ + batteryIcons: [ + 'mdi-battery-outline', + 'mdi-battery-low', + 'mdi-battery-medium', + 'mdi-battery-high', + ], + batteryIndex: 3, + }), + computed: { + overchargeTrack(this: any) { + return this.item.OverchangeTrack ? this.item.OverchangeTrack : Rules.Overcharge; + }, + }, + methods: { + getIcon(stat: string) { + const icons: Record = { + structure: 'cc:structure', + armor: 'mdi-shield-outline', + hp: 'mdi-heart-outline', + reactor: 'cc:reactor', + heat: 'cc:heat', + repair: 'cc:repair', + techAttack: 'cc:quick_tech', + }; + return icons[stat]; + }, + drainBattery(this: any) { + if (this.batteryIndex > 0) { + this.item.CombatController.CorePower = false; + const interval = setInterval(() => { + this.batteryIndex--; + if (this.batteryIndex === 0) clearInterval(interval); + }, 60); + } else { + this.item.CombatController.CorePower = true; + this.batteryIndex = 3; + } + }, + }, +}; diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_PilotEquipCardBody.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_PilotEquipCardBody.vue new file mode 100644 index 000000000..f5ecfaafe --- /dev/null +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_PilotEquipCardBody.vue @@ -0,0 +1,59 @@ + + + diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_aiControlButton.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_aiControlButton.vue new file mode 100644 index 000000000..32a6ab83b --- /dev/null +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_aiControlButton.vue @@ -0,0 +1,57 @@ + + + diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_deployButton.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_deployButton.vue index 98d3618ac..f75c3a87d 100644 --- a/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_deployButton.vue +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_deployButton.vue @@ -11,41 +11,24 @@ - - diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_pilotEquipCombatCardMixin.ts b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_pilotEquipCombatCardMixin.ts new file mode 100644 index 000000000..561256cc5 --- /dev/null +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_pilotEquipCombatCardMixin.ts @@ -0,0 +1,32 @@ +import { useMobile } from '@/composables/useMobile' +import DestroyedOverlay from './_DestroyedOverlay.vue' +import FlavorDescription from './_FlavorDescription.vue' +import PilotEquipCardBody from './_PilotEquipCardBody.vue' + +export const pilotEquipCombatCardMixin = { + components: { + EquipmentDestroyedOverlay: DestroyedOverlay, + EquipmentFlavorDescription: FlavorDescription, + PilotEquipCardBody, + }, + mixins: [useMobile], + props: { + item: { + type: Object, + required: true, + }, + pilot: { + type: Object, + required: true, + }, + encounter: { + type: Object, + required: true, + }, + owner: { + type: Object, + required: true, + }, + }, + emits: ['deploy'], +} diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_pilotWeaponCard.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_pilotWeaponCard.vue index 18e5fff33..5022bb841 100644 --- a/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_pilotWeaponCard.vue +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/_pilotWeaponCard.vue @@ -44,41 +44,11 @@ :action="action" /> -
-
-

-

- - - - - - - - - - - - -
+ import EquipCommandPanel from './_equipCommandPanel.vue' import OnElement from '@/ui/components/cards/items/_components/OnElement.vue' -import DestroyedOverlay from './_DestroyedOverlay.vue' -import FlavorDescription from './_FlavorDescription.vue' -import ActionsDeployables from './_ActionsDeployables.vue' -import { useMobile } from '@/composables/useMobile' -import { externalPilotItemBonuses } from '@/composables/useExternalItemBonuses' +import { pilotEquipCombatCardMixin } from './_pilotEquipCombatCardMixin' export default { name: 'PilotWeaponCombatCard', - components: { - EquipCommandPanel, - OnElement, - EquipmentDestroyedOverlay: DestroyedOverlay, - EquipmentFlavorDescription: FlavorDescription, - EquipmentActionsDeployables: ActionsDeployables, - }, - mixins: [useMobile], - props: { - item: { - type: Object, - required: true, - }, - pilot: { - type: Object, - required: true, - }, - encounter: { - type: Object, - required: true, - }, - owner: { - type: Object, - required: true, - }, - }, - emits: ['deploy'], - computed: { - externalPilotItemBonuses, - }, + components: { EquipCommandPanel, OnElement }, + mixins: [pilotEquipCombatCardMixin], } diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/action_buttons/_barrageButtonMixin.ts b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/action_buttons/_barrageButtonMixin.ts new file mode 100644 index 000000000..f84f051fd --- /dev/null +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/action_buttons/_barrageButtonMixin.ts @@ -0,0 +1,23 @@ +export const barrageButtonMixin = { + created(this: any) { + this.reset(); + }, + methods: { + reset(this: any, clearAction = false) { + if (clearAction) this.owner.CombatController.ClearActionUsed(this.action.ID); + this.selectedWeapons = new Array(2); + this.events = new Array(2); + if (!this.selectedWeapons[0] && this.presetWeapon) { + this.setSelected(0, this.presetWeapon); + } + }, + apply(this: any) { + const actor = this.owner.actor.CombatController.ActiveActor.CombatController; + this.selectedWeapons.forEach((w: any) => { + actor.MarkActionUsed(w.InstanceID); + if (w.IsLoading) w.Used = true; + }); + this.reset(); + }, + }, +}; diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/action_buttons/mechBarrageButton.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/action_buttons/mechBarrageButton.vue index bcb0bae6f..2418f2210 100644 --- a/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/action_buttons/mechBarrageButton.vue +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/action_buttons/mechBarrageButton.vue @@ -178,6 +178,7 @@ import ApplyButton from '@/ui/components/chips/_activeeffect/ApplyButton.vue'; import StagedPanel from './_stagedPanel.vue'; import { ActiveEffectEvent } from '@/classes/components/feature/active_effects/ActiveEffectEvent'; import CombatActionButton from './CombatActionButton.vue'; +import { barrageButtonMixin } from './_barrageButtonMixin'; export default { name: 'MechBarrageButton', @@ -189,6 +190,7 @@ export default { StagedPanel, CombatActionButton, }, + mixins: [barrageButtonMixin], props: { action: { type: Object, @@ -251,9 +253,6 @@ export default { return this.eventArray.every((e) => e.BaseEvent.Staged); } }, - created() { - this.reset(); - }, methods: { ordnanceWarning(selectedWeapon) { if (!selectedWeapon) return false; @@ -323,24 +322,6 @@ export default { ); } }, - reset(clearAction = false) { - if (clearAction) this.owner.CombatController.ClearActionUsed(this.action.ID); - - this.selectedWeapons = new Array(2); - this.events = new Array(2); - - if (!this.selectedWeapons[0] && this.presetWeapon) { - this.setSelected(0, this.presetWeapon); - } - }, - apply() { - const actor = this.owner.actor.CombatController.ActiveActor.CombatController; - this.selectedWeapons.forEach((w) => { - actor.MarkActionUsed(w.InstanceID); - if (w.IsLoading) w.Used = true; - }); - this.reset(); - }, }, }; diff --git a/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/action_buttons/npcBarrageButton.vue b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/action_buttons/npcBarrageButton.vue index c9e26d7c1..d914b04d4 100644 --- a/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/action_buttons/npcBarrageButton.vue +++ b/src/features/active_mode/runner/gm/EncounterPanels/_components/loadouts/action_buttons/npcBarrageButton.vue @@ -124,9 +124,10 @@ import { ActiveEffectEvent } from '@/classes/components/feature/active_effects/A import { NpcWeapon } from '@/classes/npc/feature/NpcItem/NpcWeapon'; import { NpcFeatureType } from '@/classes/npc/feature/NpcFeature'; import CombatActionButton from './CombatActionButton.vue'; +import { barrageButtonMixin } from './_barrageButtonMixin'; export default { - name: 'MechBarrageButton', + name: 'NpcBarrageButton', components: { MenuInput, NpcWeaponAttack, @@ -134,6 +135,7 @@ export default { StagedPanel, CombatActionButton, }, + mixins: [barrageButtonMixin], props: { action: { type: Object, @@ -191,9 +193,6 @@ export default { return this.owner.actor.CombatController.Tier; } }, - created() { - this.reset(); - }, methods: { ordnanceWarning(selectedWeapon) { if (!selectedWeapon) return false; @@ -226,24 +225,6 @@ export default { this.events.push(undefined as any); } }, - reset(clearAction = false) { - if (clearAction) this.owner.CombatController.ClearActionUsed(this.action.ID); - - this.selectedWeapons = new Array(2); - this.events = new Array(2); - - if (!this.selectedWeapons[0] && this.presetWeapon) { - this.setSelected(0, this.presetWeapon); - } - }, - apply() { - const actor = this.owner.actor.CombatController.ActiveActor.CombatController; - this.selectedWeapons.forEach((w) => { - actor.MarkActionUsed(w.InstanceID); - if (w.IsLoading) w.Used = true; - }); - this.reset(); - }, }, }; diff --git a/src/features/active_mode/runner/gm/EncounterPanels/encounter-panels.css b/src/features/active_mode/runner/gm/EncounterPanels/encounter-panels.css new file mode 100644 index 000000000..16caa5c5d --- /dev/null +++ b/src/features/active_mode/runner/gm/EncounterPanels/encounter-panels.css @@ -0,0 +1,7 @@ +.bg-stripes { + background: repeating-linear-gradient(-45deg, + rgba(249, 219, 78, 0.5), + rgba(249, 219, 78, 0.5) 10px, + rgba(100, 100, 100, 0.5) 10px, + rgba(100, 100, 100, 0.5) 20px); +} diff --git a/src/features/active_mode/runner/gm/GMEncounterRunner.vue b/src/features/active_mode/runner/gm/GMEncounterRunner.vue index 8336ec389..502d5739d 100644 --- a/src/features/active_mode/runner/gm/GMEncounterRunner.vue +++ b/src/features/active_mode/runner/gm/GMEncounterRunner.vue @@ -130,32 +130,10 @@ @close="tableDialog = false" /> - - - -
- Do you want to save this encounter before exiting?
- - - Cancel - - Exit Without Saving - - Save and Exit - -
-
+ @@ -185,6 +163,7 @@ import EidolonPanel from './EncounterPanels/EidolonPanel.vue'; import ActorLogs from './EncounterPanels/_components/ActorLogs.vue'; import CombatStatblockExport from './EncounterPanels/_components/CombatStatblockExport.vue'; import ActorTelemetry from './EncounterPanels/_components/ActorTelemetry.vue'; +import RunnerLeaveDialog from '../_shared/_RunnerLeaveDialog.vue'; const panelMap: Record = { 'encounter-info': EncounterInfoPanel, diff --git a/src/features/active_mode/runner/gm/InfoPanels/GmOptionsPanel.vue b/src/features/active_mode/runner/gm/InfoPanels/GmOptionsPanel.vue index 6eb470021..aa88dcd46 100644 --- a/src/features/active_mode/runner/gm/InfoPanels/GmOptionsPanel.vue +++ b/src/features/active_mode/runner/gm/InfoPanels/GmOptionsPanel.vue @@ -1,68 +1,10 @@ @@ -161,6 +139,7 @@ import OptionsPanel from './_components/PcOptionsPanel.vue'; import DeployablesPanel from './_components/PcDeployablesPanel.vue'; import PcEndRound from './_components/PcEndRound.vue'; import PcEndEncounter from './_components/PcEndEncounter.vue'; +import RunnerLeaveDialog from '../_shared/_RunnerLeaveDialog.vue'; const panelMap: Record = { 'pc': PcPanel, diff --git a/src/features/active_mode/runner/pilot/_components/PcEndRound.vue b/src/features/active_mode/runner/pilot/_components/PcEndRound.vue index 8e5d9f452..7220c4987 100644 --- a/src/features/active_mode/runner/pilot/_components/PcEndRound.vue +++ b/src/features/active_mode/runner/pilot/_components/PcEndRound.vue @@ -1,33 +1,7 @@ diff --git a/src/features/compendium/Views/CampaignLibrary/index.vue b/src/features/compendium/Views/CampaignLibrary/index.vue index 0927e2120..5f0046303 100644 --- a/src/features/compendium/Views/CampaignLibrary/index.vue +++ b/src/features/compendium/Views/CampaignLibrary/index.vue @@ -74,36 +74,5 @@ export default { diff --git a/src/features/compendium/Views/CampaignLibrary/pages/containers/campaignContentContainer.vue b/src/features/compendium/Views/CampaignLibrary/pages/containers/campaignContentContainer.vue index bfaff7bea..2044fdaa3 100644 --- a/src/features/compendium/Views/CampaignLibrary/pages/containers/campaignContentContainer.vue +++ b/src/features/compendium/Views/CampaignLibrary/pages/containers/campaignContentContainer.vue @@ -42,6 +42,7 @@ diff --git a/src/features/compendium/Views/Reference/_components/SrdViewMobile.vue b/src/features/compendium/Views/Reference/_components/SrdViewMobile.vue index a4bf018dc..155033816 100644 --- a/src/features/compendium/Views/Reference/_components/SrdViewMobile.vue +++ b/src/features/compendium/Views/Reference/_components/SrdViewMobile.vue @@ -81,54 +81,12 @@ diff --git a/src/features/compendium/Views/Reference/_components/_srdViewMixin.ts b/src/features/compendium/Views/Reference/_components/_srdViewMixin.ts new file mode 100644 index 000000000..bb64a90d8 --- /dev/null +++ b/src/features/compendium/Views/Reference/_components/_srdViewMixin.ts @@ -0,0 +1,43 @@ +import { NavStore } from '@/stores'; + +export const srdViewMixin = { + inheritAttrs: false, + props: { + title: { + type: String, + }, + content: { + type: Array, + default: () => [], + }, + preScroll: { + type: String, + default: '', + }, + }, + mounted(this: any) { + if (this.preScroll) { + this.scrollTo(this.preScroll); + } else window.scrollTo({ top: 0 }); + }, + computed: { + lang(this: any) { + return NavStore().Language; + }, + }, + methods: { + getLangItem(this: any, item: any, type: string) { + if (typeof item === 'string') return item; + return item[type][this.lang] ? item[type][this.lang] : item[type].en; + }, + scrollTo(this: any, item: any): void { + const title = this.getLangItem(item, 'title'); + const el = document.getElementById(`e_${title.replace(/\W/g, '')}`); + if (el) { + const yOffset = -60; + const y = el.getBoundingClientRect().top + window.pageYOffset + yOffset; + window.scrollTo({ top: y, behavior: 'smooth' }); + } + }, + }, +}; diff --git a/src/features/compendium/components/CompendiumPageButton.vue b/src/features/compendium/components/CompendiumPageButton.vue index 8b760dc59..b9547e0a5 100644 --- a/src/features/compendium/components/CompendiumPageButton.vue +++ b/src/features/compendium/components/CompendiumPageButton.vue @@ -64,29 +64,12 @@ export default { diff --git a/src/features/gm/encounters/print/components/PrintAction.vue b/src/features/gm/encounters/print/components/PrintAction.vue deleted file mode 100644 index f12d394c1..000000000 --- a/src/features/gm/encounters/print/components/PrintAction.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - - - diff --git a/src/features/gm/narrative/print/OptionsDialog.vue b/src/features/gm/narrative/print/OptionsDialog.vue index e115724ca..44df7fc08 100644 --- a/src/features/gm/narrative/print/OptionsDialog.vue +++ b/src/features/gm/narrative/print/OptionsDialog.vue @@ -1,110 +1,28 @@ - - - +const includeOptions = computed(() => { + switch (props.options.layout.title) { + case 'Minimal': + return [] + default: + return [ + { title: 'Include Image' }, + { title: 'Additional Detail' }, + { title: 'Clocks' }, + { title: 'Tables' }, + { title: 'Append Lined Section' }, + { title: 'Append Unlined Section' }, + ] + } +}) + diff --git a/src/features/gm/narrative/print/PrintOptionSelect.vue b/src/features/gm/narrative/print/PrintOptionSelect.vue deleted file mode 100644 index 8bff0ec6a..000000000 --- a/src/features/gm/narrative/print/PrintOptionSelect.vue +++ /dev/null @@ -1,74 +0,0 @@ - - - diff --git a/src/features/gm/npc_roster/npcs/_components/NpcClassSelector.vue b/src/features/gm/npc_roster/npcs/_components/NpcClassSelector.vue index 93e5aaf90..d5eab2724 100644 --- a/src/features/gm/npc_roster/npcs/_components/NpcClassSelector.vue +++ b/src/features/gm/npc_roster/npcs/_components/NpcClassSelector.vue @@ -42,65 +42,15 @@ +const props = defineProps<{ options: Record }>() +const emit = defineEmits<{ set: [options: any] }>() + +watch(() => props.options, (val) => emit('set', val), { deep: true }) - +const extraOptions = computed(() => [{ title: 'Relevant Tag Reference' }]) + diff --git a/src/features/gm/npc_roster/print/PrintOptionSelect.vue b/src/features/gm/npc_roster/print/PrintOptionSelect.vue deleted file mode 100644 index a30156b29..000000000 --- a/src/features/gm/npc_roster/print/PrintOptionSelect.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - diff --git a/src/features/gm/npc_roster/print/extras/TagInfoPrint.vue b/src/features/gm/npc_roster/print/extras/TagInfoPrint.vue index e09f0066f..b9333d064 100644 --- a/src/features/gm/npc_roster/print/extras/TagInfoPrint.vue +++ b/src/features/gm/npc_roster/print/extras/TagInfoPrint.vue @@ -1,40 +1,17 @@ - - diff --git a/src/features/main_menu/_components/MassifLcpTable.vue b/src/features/main_menu/_components/MassifLcpTable.vue index 3f0e56f9f..9d8ac3e3a 100644 --- a/src/features/main_menu/_components/MassifLcpTable.vue +++ b/src/features/main_menu/_components/MassifLcpTable.vue @@ -1,101 +1,20 @@ diff --git a/src/features/pilot_management/PilotSheet/components/PilotEditMenu.vue b/src/features/pilot_management/PilotSheet/components/PilotEditMenu.vue index b9b4d2352..1006a32b2 100644 --- a/src/features/pilot_management/PilotSheet/components/PilotEditMenu.vue +++ b/src/features/pilot_management/PilotSheet/components/PilotEditMenu.vue @@ -143,20 +143,15 @@ diff --git a/src/features/pilot_management/PilotSheet/pilotActionsMixin.ts b/src/features/pilot_management/PilotSheet/pilotActionsMixin.ts new file mode 100644 index 000000000..78627c925 --- /dev/null +++ b/src/features/pilot_management/PilotSheet/pilotActionsMixin.ts @@ -0,0 +1,62 @@ +import { saveFile } from '@/io/Data' +import { Pilot } from '@/classes/pilot/Pilot' +import { UserStore } from '@/stores' +import { CloudController } from '@/classes/components/cloud/CloudController' +import logger from '@/user/logger' + +export const pilotActionsMixin = { + methods: { + exportPilot(v2 = false) { + try { + saveFile( + this.pilot.Callsign.toUpperCase().replace(/\W/g, '') + '.json', + Pilot.Serialize(this.pilot as Pilot), + 'Save Pilot', + v2 + ) + this.$notify({ + title: 'Export Success', + text: `Pilot data saved as "${this.pilot.Callsign.toUpperCase().replace( + /\W/g, + '' + )}.json"`, + data: { type: 'success', icon: 'mdi-check' }, + }) + } catch (error) { + logger.error(`Pilot export failed: ${error}`, this, error) + this.$notify({ + title: 'Export Error', + text: 'COMP/CON was unable to export pilot data', + data: { type: 'error', icon: 'mdi-alert' }, + }) + } + }, + async remoteUpdate() { + try { + await CloudController.UpdateRemote(this.pilot) + await UserStore().refreshDbData() + this.$notify({ + title: `Sync Complete`, + text: `Pilot ${this.pilot.Callsign} // ${this.pilot.Name} synced.`, + data: { icon: 'mdi-cloud-check-variant', color: 'success-darken-2' }, + }) + } catch (err) { + logger.error(`Error syncing pilot: ${err}`, this, err) + this.$notify({ + title: `Sync Failed`, + text: `Failed to sync Pilot ${this.pilot.Callsign} // ${this.pilot.Name}. ${err}`, + data: { icon: 'mdi-alert', color: 'error' }, + }) + } + }, + async convert() { + this.loading = true + UserStore().deleteRemoteItem(this.pilot.SaveController.RemoteCode) + this.pilot.CloudController.GenerateMetadata() + this.pilot.SaveController.ClearRemote() + await UserStore().refreshDbData() + this.loading = false + this.$emit('close') + }, + }, +} diff --git a/src/features/pilot_management/Print/OptionsDialog.vue b/src/features/pilot_management/Print/OptionsDialog.vue index 2ada00f3d..ad081ccfe 100644 --- a/src/features/pilot_management/Print/OptionsDialog.vue +++ b/src/features/pilot_management/Print/OptionsDialog.vue @@ -90,7 +90,7 @@ diff --git a/src/features/pilot_management/Print/components/PrintMechNameBlock.vue b/src/features/pilot_management/Print/components/PrintMechNameBlock.vue new file mode 100644 index 000000000..e55717a93 --- /dev/null +++ b/src/features/pilot_management/Print/components/PrintMechNameBlock.vue @@ -0,0 +1,46 @@ + + + diff --git a/src/features/pilot_management/Print/components/PrintStatBox.vue b/src/features/pilot_management/Print/components/PrintStatBox.vue new file mode 100644 index 000000000..66df63096 --- /dev/null +++ b/src/features/pilot_management/Print/components/PrintStatBox.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/features/pilot_management/Print/components/_PrintMechHpRows.vue b/src/features/pilot_management/Print/components/_PrintMechHpRows.vue new file mode 100644 index 000000000..b3df612c2 --- /dev/null +++ b/src/features/pilot_management/Print/components/_PrintMechHpRows.vue @@ -0,0 +1,97 @@ + + + diff --git a/src/features/pilot_management/Print/extras/TagInfoPrint.vue b/src/features/pilot_management/Print/extras/TagInfoPrint.vue index 341ffdae5..1573dcbaa 100644 --- a/src/features/pilot_management/Print/extras/TagInfoPrint.vue +++ b/src/features/pilot_management/Print/extras/TagInfoPrint.vue @@ -1,36 +1,14 @@ - - diff --git a/src/features/pilot_management/Print/layouts/_usePrintOptions.ts b/src/features/pilot_management/Print/layouts/_usePrintOptions.ts index 5ef6b0339..0caf41df0 100644 --- a/src/features/pilot_management/Print/layouts/_usePrintOptions.ts +++ b/src/features/pilot_management/Print/layouts/_usePrintOptions.ts @@ -5,6 +5,14 @@ export interface PrintOptions { } export const usePrintOptions = { + computed: { + blank(this: any): boolean { + return this.options.content.title === 'Blank' + }, + landscape(this: any): boolean { + return this.options.orientation.title === 'Landscape' + }, + }, methods: { hasPilotOption(this: any, title: string): boolean { return this.options.pilotInclude.some((x: any) => x.title === title) @@ -12,5 +20,16 @@ export const usePrintOptions = { hasMechOption(this: any, title: string): boolean { return this.options.mechInclude.some((x: any) => x.title === title) }, + signed(val: number): string { + return val > -1 ? `+${val}` : `${val}` + }, + showTag(id: string): boolean { + const hiddenTags = ['tg_hidden', 'tg_unique', 'tg_set_damage_type'] + return !hiddenTags.includes(id) + }, + showCollectedEffect(w: any): boolean { + if (!w.Profiles[0].Effect) return false + return w.Profiles.every((x: any) => x.Effect === w.Profiles[0].Effect) + }, }, } diff --git a/src/features/pilot_management/Print/layouts/cards/PilotPrint.vue b/src/features/pilot_management/Print/layouts/cards/PilotPrint.vue index f19ddf02f..0cf18cbe9 100644 --- a/src/features/pilot_management/Print/layouts/cards/PilotPrint.vue +++ b/src/features/pilot_management/Print/layouts/cards/PilotPrint.vue @@ -428,12 +428,6 @@ export default { }, }, computed: { - blank() { - return this.options.content.title === 'Blank'; - }, - landscape() { - return this.options.orientation === 'landscape'; - }, talentActions() { return this.pilot.TalentsController.Talents.flatMap((t) => t.Talent.Ranks) .filter((r) => r.Actions.length > 0) diff --git a/src/features/pilot_management/Print/layouts/expanded/MechPrint.vue b/src/features/pilot_management/Print/layouts/expanded/MechPrint.vue index dba918c4e..55f45f1ca 100644 --- a/src/features/pilot_management/Print/layouts/expanded/MechPrint.vue +++ b/src/features/pilot_management/Print/layouts/expanded/MechPrint.vue @@ -1,212 +1,25 @@ diff --git a/src/ui/components/buttons/subcomponents/cc_btn_tonal.vue b/src/ui/components/buttons/subcomponents/cc_btn_tonal.vue index 23cd79df2..203e6cc62 100644 --- a/src/ui/components/buttons/subcomponents/cc_btn_tonal.vue +++ b/src/ui/components/buttons/subcomponents/cc_btn_tonal.vue @@ -41,46 +41,27 @@ diff --git a/src/ui/components/chips/CCCombatActionChip.vue b/src/ui/components/chips/CCCombatActionChip.vue index 66452edd5..4b0e79eb8 100644 --- a/src/ui/components/chips/CCCombatActionChip.vue +++ b/src/ui/components/chips/CCCombatActionChip.vue @@ -4,50 +4,32 @@ align="center"> - - + + diff --git a/src/ui/components/chips/_activeeffect/_shared/AccuracyDifficultyRow.vue b/src/ui/components/chips/_activeeffect/_shared/AccuracyDifficultyRow.vue new file mode 100644 index 000000000..4e10a1ac3 --- /dev/null +++ b/src/ui/components/chips/_activeeffect/_shared/AccuracyDifficultyRow.vue @@ -0,0 +1,84 @@ + + + diff --git a/src/ui/components/chips/_activeeffect/_shared/CheckRollInterface.vue b/src/ui/components/chips/_activeeffect/_shared/CheckRollInterface.vue index 00e8266bf..7b46a1ccb 100644 --- a/src/ui/components/chips/_activeeffect/_shared/CheckRollInterface.vue +++ b/src/ui/components/chips/_activeeffect/_shared/CheckRollInterface.vue @@ -42,75 +42,9 @@ - - 1d20 - + - - - - - - - - - - - - - - + - - 1d20 - + - - - - - - - - - - - - - - + import { DiceRoller } from '@/classes/dice/DiceRoller' +import AccuracyDifficultyRow from './AccuracyDifficultyRow.vue' const props = defineProps<{ rollData: object diff --git a/src/ui/components/headings/headings/cc_heading_base.css b/src/ui/components/headings/headings/cc_heading_base.css new file mode 100644 index 000000000..6b02e0131 --- /dev/null +++ b/src/ui/components/headings/headings/cc_heading_base.css @@ -0,0 +1,11 @@ +.cc-panel-clip { + clip-path: polygon(0% 0%, 100% 0%, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0% 100%); +} + +.cc-panel-slice { + clip-path: polygon(0% 0%, 100% 0%, 100% 0%, calc(100% - 24px) 100%, 0% 100%); +} + +.cc-panel-clip-comfortable { + clip-path: polygon(0% 0%, 100% 0%, 100% calc(100% - 24px), calc(100% - 24px) 100%, 0% 100%); +} diff --git a/src/ui/components/headings/headings/cc_heading_filled.vue b/src/ui/components/headings/headings/cc_heading_filled.vue deleted file mode 100644 index 82bfa1264..000000000 --- a/src/ui/components/headings/headings/cc_heading_filled.vue +++ /dev/null @@ -1,78 +0,0 @@ - - - - - diff --git a/src/ui/components/headings/headings/cc_heading_minor.vue b/src/ui/components/headings/headings/cc_heading_minor.vue index 3a874ec3d..75f727ace 100644 --- a/src/ui/components/headings/headings/cc_heading_minor.vue +++ b/src/ui/components/headings/headings/cc_heading_minor.vue @@ -60,17 +60,5 @@ export default { diff --git a/src/ui/components/inputs/tickbar/_TickbarActivator.vue b/src/ui/components/inputs/tickbar/_TickbarActivator.vue new file mode 100644 index 000000000..b476b39f6 --- /dev/null +++ b/src/ui/components/inputs/tickbar/_TickbarActivator.vue @@ -0,0 +1,96 @@ + + + + + diff --git a/src/ui/components/inputs/tickbar/_bottomBar.vue b/src/ui/components/inputs/tickbar/_bottomBar.vue index 58f4e6263..b649248bf 100644 --- a/src/ui/components/inputs/tickbar/_bottomBar.vue +++ b/src/ui/components/inputs/tickbar/_bottomBar.vue @@ -2,59 +2,16 @@
- - - + @@ -105,11 +62,13 @@ diff --git a/src/ui/components/inputs/tickbar/_centerBar.vue b/src/ui/components/inputs/tickbar/_centerBar.vue index 79b1975cf..a68021367 100644 --- a/src/ui/components/inputs/tickbar/_centerBar.vue +++ b/src/ui/components/inputs/tickbar/_centerBar.vue @@ -181,6 +181,8 @@ export default { diff --git a/src/ui/components/inputs/tickbar/_tickbarMixin.ts b/src/ui/components/inputs/tickbar/_tickbarMixin.ts new file mode 100644 index 000000000..023d8be02 --- /dev/null +++ b/src/ui/components/inputs/tickbar/_tickbarMixin.ts @@ -0,0 +1,46 @@ +export const tickbarMixin = { + data() { + return { + hover: null as number | null, + internalValue: (this as any).modelValue, + }; + }, + computed: { + tickThreshold(this: any) { + if (this.$vuetify.display.mdAndDown) return 1; + if (this.$vuetify.display.lgAndDown) return 4; + return 6; + }, + pctBackground(this: any) { + if (!this.ticks || this.ticks <= 0) return ''; + const pct = Math.round((this.modelValue / this.ticks) * 100); + return `background: linear-gradient(45deg, rgb(var(--v-theme-${this.color})) ${pct}%, rgb(var(--v-theme-${this.bgColor})) ${pct}%)`; + }, + }, + watch: { + modelValue(this: any, val: number) { + this.internalValue = val; + }, + internalValue(this: any, val: number) { + this.$emit('update:modelValue', val); + }, + }, + methods: { + isHovered(this: any, i: number) { + return this.hover && this.hover >= i; + }, + isMouseovered(this: any, i: number) { + return this.hover === i; + }, + isActive(this: any, i: number) { + return this.modelValue && this.modelValue >= i; + }, + setVal(this: any, val: number) { + if (this.stopAdd && val > this.modelValue) return; + if (this.ticks && val > this.ticks) val = this.ticks; + if (val < 0) val = 0; + if (this.modelValue === 1 && val === 1) val = 0; + this.$emit('update:modelValue', val); + }, + }, +}; diff --git a/src/ui/components/inputs/tickbar/_topBar.vue b/src/ui/components/inputs/tickbar/_topBar.vue index abb70c2e8..4757137d2 100644 --- a/src/ui/components/inputs/tickbar/_topBar.vue +++ b/src/ui/components/inputs/tickbar/_topBar.vue @@ -2,69 +2,22 @@
- - diff --git a/src/ui/components/inputs/tickbar/tickbar.css b/src/ui/components/inputs/tickbar/tickbar.css new file mode 100644 index 000000000..397eeca63 --- /dev/null +++ b/src/ui/components/inputs/tickbar/tickbar.css @@ -0,0 +1,13 @@ +.tick { + opacity: 0.3; + transform: opacity 0.2s ease-in-out; +} + +.hovered { + opacity: 0.5; +} + +.highlighted { + opacity: 1; + filter: saturate(200%); +} diff --git a/src/ui/components/panels/filters/MechItemFilterBase.vue b/src/ui/components/panels/filters/MechItemFilterBase.vue new file mode 100644 index 000000000..132d2bc16 --- /dev/null +++ b/src/ui/components/panels/filters/MechItemFilterBase.vue @@ -0,0 +1,109 @@ + + + diff --git a/src/ui/components/panels/filters/_MechSystemFilter.vue b/src/ui/components/panels/filters/_MechSystemFilter.vue index de6e293ae..506da7af5 100644 --- a/src/ui/components/panels/filters/_MechSystemFilter.vue +++ b/src/ui/components/panels/filters/_MechSystemFilter.vue @@ -1,7 +1,8 @@ + + diff --git a/src/ui/components/tables/CCRefStressTable.vue b/src/ui/components/tables/CCRefStressTable.vue index 3845f6258..6b8bfd6cc 100644 --- a/src/ui/components/tables/CCRefStressTable.vue +++ b/src/ui/components/tables/CCRefStressTable.vue @@ -1,166 +1,114 @@ - - diff --git a/src/ui/components/tables/CCRefStructureTable.vue b/src/ui/components/tables/CCRefStructureTable.vue index f78e435b3..07fbb88cb 100644 --- a/src/ui/components/tables/CCRefStructureTable.vue +++ b/src/ui/components/tables/CCRefStructureTable.vue @@ -1,160 +1,110 @@ - - diff --git a/src/ui/components/tables/_RefRollTableBase.vue b/src/ui/components/tables/_RefRollTableBase.vue new file mode 100644 index 000000000..51dd6062f --- /dev/null +++ b/src/ui/components/tables/_RefRollTableBase.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/src/ui/style/pilot-list-item.css b/src/ui/style/pilot-list-item.css new file mode 100644 index 000000000..20566e749 --- /dev/null +++ b/src/ui/style/pilot-list-item.css @@ -0,0 +1,38 @@ +.detail-row { + background-color: rgb(var(--v-theme-light-panel)); + border-bottom: 1px rgb(var(--v-theme-primary)) solid; + border-right: 1px rgb(var(--v-theme-primary)) solid; + border-left: 1px rgb(var(--v-theme-primary)) solid; + margin-left: -13px; + min-height: 138px; +} + +.detail-row-mobile { + background-color: rgb(var(--v-theme-light-panel)); + border-bottom: 1px rgb(var(--v-theme-primary)) solid; + border-right: 1px rgb(var(--v-theme-primary)) solid; + border-left: 1px rgb(var(--v-theme-primary)) solid; + margin-left: -1px; + min-height: 57px; +} + +.cToolbar { + background-color: rgb(var(--v-theme-primary)); +} + +.cToolbar-missing { + background: repeating-linear-gradient(45deg, + rgb(var(--v-theme-error-darken-2)), + rgb(var(--v-theme-error-darken-2)) 10px, + rgb(var(--v-theme-error-darken-3)) 10px, + rgb(var(--v-theme-error-darken-3)) 20px); +} + +.light { + transition: background-color 0.2s ease-in-out; + background-color: rgb(var(--v-theme-primary)); +} + +.li-top-element:hover .light { + background-color: rgb(var(--v-theme-success)); +}