diff --git a/.github/workflows/CBA.yml b/.github/workflows/CBA.yml index 152a66235cf2d..34684c3ca3fb7 100644 --- a/.github/workflows/CBA.yml +++ b/.github/workflows/CBA.yml @@ -34,7 +34,7 @@ jobs: ClangBuildAnalyzer --stop . buildAnalysis - name: Analyze run: ClangBuildAnalyzer --analyze buildAnalysis - - uses: actions/upload-artifact@v3.1.2 + - uses: actions/upload-artifact@v4 with: name: ClangBuildAnalyzer-traces path: "**/obj/*.json" diff --git a/.github/workflows/astyle.yml b/.github/workflows/astyle.yml index 1d5fe95dada10..cb839f1bf3883 100644 --- a/.github/workflows/astyle.yml +++ b/.github/workflows/astyle.yml @@ -16,7 +16,7 @@ jobs: cancel_others: 'true' paths: '[".github/workflows/astyle.yml", "Makefile", ".astylerc", "**.cpp", "**.h", "**.c"]' - run: echo ${{ github.event.number }} > pull_request_id - - uses: actions/upload-artifact@v3.1.2 + - uses: actions/upload-artifact@v4 with: name: pull_request_id path: pull_request_id diff --git a/.github/workflows/check-branch-name.yml b/.github/workflows/check-branch-name.yml index 57a6a908256f4..b860cb3cd5cc3 100644 --- a/.github/workflows/check-branch-name.yml +++ b/.github/workflows/check-branch-name.yml @@ -11,7 +11,7 @@ jobs: if: github.head_ref == 'master' && github.repository == 'CleverRaven/Cataclysm-DDA' steps: - name: Post warning - uses: actions/github-script@v6.3.3 + uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index ed70cd3d7327c..1b8080303e3cb 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -84,7 +84,7 @@ jobs: run: bash ./build-scripts/requirements.sh - name: determine changed files if: ${{ github.event_name == 'pull_request' }} - uses: actions/github-script@v6.3.3 + uses: actions/github-script@v7 with: script: | var fs = require('fs'); diff --git a/.github/workflows/comment-commands.yml b/.github/workflows/comment-commands.yml index 3a3df16611c12..075c4586cfd8d 100644 --- a/.github/workflows/comment-commands.yml +++ b/.github/workflows/comment-commands.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v4 - name: Set-up Comvent - uses: rytswd/comvent@v0.5.2 + uses: rytswd/comvent@main id: comvent with: token: ${{ secrets.GITHUB_TOKEN }} @@ -65,7 +65,7 @@ jobs: uses: actions/checkout@v4 - name: Set-up Comvent - uses: rytswd/comvent@v0.5.2 + uses: rytswd/comvent@main id: comvent with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/detect-translation-file-changes.yml b/.github/workflows/detect-translation-file-changes.yml index 4695763dd94fe..6f7aab063b730 100644 --- a/.github/workflows/detect-translation-file-changes.yml +++ b/.github/workflows/detect-translation-file-changes.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: "Detect translation file changes" - uses: actions/github-script@v6.3.3 + uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/format_emscripten.yml b/.github/workflows/format_emscripten.yml index 82c1993cd2096..e98c2f5eb2312 100644 --- a/.github/workflows/format_emscripten.yml +++ b/.github/workflows/format_emscripten.yml @@ -31,7 +31,7 @@ jobs: run: ls -a - name: Upload zipped html as artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: formatter path: formatter.html @@ -40,7 +40,7 @@ jobs: with: ref: gh-pages - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v3.1.4 with: name: formatter diff --git a/.github/workflows/json.yml b/.github/workflows/json.yml index 518e3b7805995..623d36a3f2168 100644 --- a/.github/workflows/json.yml +++ b/.github/workflows/json.yml @@ -16,7 +16,7 @@ jobs: cancel_others: 'true' paths: '["**.json", ".github/workflows/json.yml"]' - run: echo ${{ github.event.number }} > pull_request_id - - uses: actions/upload-artifact@v3.1.2 + - uses: actions/upload-artifact@v4 with: name: pull_request_id path: pull_request_id diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml index ae20d8883c855..bfa5623351033 100644 --- a/.github/workflows/matrix.yml +++ b/.github/workflows/matrix.yml @@ -333,18 +333,18 @@ jobs: echo ${{ github.event.number }} > pull_request_id echo "false" > ${{ env.ARCHIVE_SUCCESS }} if: ${{ env.ARCHIVE_SUCCESS && failure() }} - - uses: actions/upload-artifact@v3.1.2 + - uses: actions/upload-artifact@v4 if: ${{ always() && env.ARCHIVE_SUCCESS }} with: name: pull_request_id path: pull_request_id - - uses: actions/upload-artifact@v3.1.2 + - uses: actions/upload-artifact@v4 if: ${{ always() && env.ARCHIVE_SUCCESS }} with: name: ${{ env.ARCHIVE_SUCCESS }} path: ${{ env.ARCHIVE_SUCCESS }} - name: upload artifacts if failed - uses: actions/upload-artifact@v3.1.2 + uses: actions/upload-artifact@v4 if: failure() with: name: cata_test diff --git a/.github/workflows/msvc-full-features.yml b/.github/workflows/msvc-full-features.yml index 62290662666b8..1d5baeeccd105 100644 --- a/.github/workflows/msvc-full-features.yml +++ b/.github/workflows/msvc-full-features.yml @@ -68,7 +68,7 @@ jobs: make - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v1.3.1 + uses: microsoft/setup-msbuild@v2 - name: Use GNU tar to enable zstd for actions/cache run: | @@ -91,7 +91,7 @@ jobs: vcpkg integrate install --vcpkg-root '${{ runner.workspace }}\b\vcpkg' - name: Download ccache - uses: robinraju/release-downloader@v1.4 + uses: robinraju/release-downloader@v1.9 with: repository: 'ccache/ccache' tag: 'v4.6.1' diff --git a/.github/workflows/post-spell-check-result.yml b/.github/workflows/post-spell-check-result.yml index c093c5b28ca6b..f8b321db0ceed 100644 --- a/.github/workflows/post-spell-check-result.yml +++ b/.github/workflows/post-spell-check-result.yml @@ -16,13 +16,13 @@ jobs: github.event.workflow_run.conclusion == 'success' }} steps: - name: Download pr id artifact - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@v3.1.4 with: workflow: ${{ github.event.workflow_run.name }} run_id: ${{ github.event.workflow_run.id }} name: pull_request_id - name: Download spell check retcode artifact - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@v3.1.4 with: workflow: ${{ github.event.workflow_run.name }} run_id: ${{ github.event.workflow_run.id }} @@ -32,14 +32,14 @@ jobs: run: echo "spell-check-retcode=$( cat spell_check_retcode )" >> $GITHUB_OUTPUT - name: Download spell check output artifact if: steps.set-spell-check-retcode.outputs.spell-check-retcode >= 1 - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@v3.1.4 with: workflow: ${{ github.event.workflow_run.name }} run_id: ${{ github.event.workflow_run.id }} name: spell_check_output - name: 'Comment on PR' if: steps.set-spell-check-retcode.outputs.spell-check-retcode >= 1 - uses: actions/github-script@v6.3.3 + uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/pull-translations.yml b/.github/workflows/pull-translations.yml index 7723463308728..bf0f129e69219 100644 --- a/.github/workflows/pull-translations.yml +++ b/.github/workflows/pull-translations.yml @@ -15,7 +15,7 @@ jobs: run: | curl -sL https://github.com/transifex/cli/releases/download/v1.6.4/tx-linux-amd64.tar.gz | sudo tar zxvf - -C /usr/bin tx - name: "Delete existing i18n branch" - uses: actions/github-script@v6.3.3 + uses: actions/github-script@v7 with: github-token: ${{ secrets.TX_PR_CREATOR }} script: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3c5e9beba5759..a2d6580ae8758 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -195,7 +195,7 @@ jobs: uses: lukka/get-cmake@latest - name: Install dependencies (windows msvc) (1/4) if: runner.os == 'Windows' - uses: microsoft/setup-msbuild@v1.3.1 + uses: microsoft/setup-msbuild@v2 - name: Install dependencies (windows msvc) (2/4) if: runner.os == 'Windows' uses: lukka/run-vcpkg@v11 @@ -249,7 +249,7 @@ jobs: uses: mymindstorm/setup-emsdk@v13 - name: Install runtime dependencies (mac) if: runner.os == 'macOS' - uses: BrettDong/setup-sdl2-frameworks@v1 + uses: BrettDong/setup-sdl2-frameworks@v2 with: sdl2: latest sdl2-ttf: latest @@ -297,7 +297,7 @@ jobs: (cd build && zip ../cdda-${{ matrix.artifact }}-${{ needs.release.outputs.timestamp }}.${{ matrix.ext }} *) - name: Login to GitHub Container Registry if: matrix.artifact == 'windows-objectcreator-x64' || matrix.artifact == 'linux-objectcreator-x64' - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} @@ -357,7 +357,7 @@ jobs: mv Cataclysm.dmg cdda-${{ matrix.artifact }}-${{ needs.release.outputs.timestamp }}.dmg - name: Set up JDK 8 (android) if: runner.os == 'Linux' && matrix.android != 'none' && matrix.mxe == 'none' - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'adopt' diff --git a/.github/workflows/test_labeler.yml b/.github/workflows/test_labeler.yml index 5b57a99ebf1d2..b4d34ba6b3e0b 100644 --- a/.github/workflows/test_labeler.yml +++ b/.github/workflows/test_labeler.yml @@ -24,7 +24,7 @@ jobs: fi - name: Download success artifact from basic build if: ${{ github.event.workflow_run.name == 'General build matrix' }} - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@v3.1.4 with: workflow: ${{ github.event.workflow_run.name }} run_id: ${{ github.event.workflow_run.id }} @@ -33,7 +33,7 @@ jobs: id: set-basic-build-success run: echo "basic-build-success=$( cat basic-build )" >> $GITHUB_OUTPUT - name: Download pr id artifact - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@v3.1.4 with: workflow: ${{ github.event.workflow_run.name }} run_id: ${{ github.event.workflow_run.id }} @@ -43,7 +43,7 @@ jobs: run: echo "pr-id=$( cat pull_request_id )" >> $GITHUB_OUTPUT - name: set-label if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.conclusion != 'skipped' || steps.set-basic-build-success.outputs.basic-build-success == 'true' }} - uses: actions/github-script@v6.3.3 + uses: actions/github-script@v7 with: script: | if ('${{ steps.set-pr-id.outputs.pr-id }}'.trim().length == 0) { @@ -58,7 +58,7 @@ jobs: } - name: remove-label if: ${{ github.event.workflow_run.conclusion == 'failure' && steps.set-basic-build-success.outputs.basic-build-success != 'true' }} - uses: actions/github-script@v6.3.3 + uses: actions/github-script@v7 with: script: | if ('${{ steps.set-pr-id.outputs.pr-id }}'.trim().length == 0) { diff --git a/.github/workflows/text-changes-analyzer.yml b/.github/workflows/text-changes-analyzer.yml index 39c26dbc839d5..07ad4b601ddef 100644 --- a/.github/workflows/text-changes-analyzer.yml +++ b/.github/workflows/text-changes-analyzer.yml @@ -68,15 +68,15 @@ jobs: wc -c spell_check_output | grep -o '[0-9]*' > spell_check_retcode echo "length=$(cat spell_check_retcode)" >> $GITHUB_OUTPUT - run: echo ${{ github.event.number }} > pull_request_id - - uses: actions/upload-artifact@v3.1.2 + - uses: actions/upload-artifact@v4 with: name: pull_request_id path: pull_request_id - - uses: actions/upload-artifact@v3.1.2 + - uses: actions/upload-artifact@v4 with: name: spell_check_retcode path: spell_check_retcode - - uses: actions/upload-artifact@v3.1.2 + - uses: actions/upload-artifact@v4 if: steps.get_length.outputs.length >= 1 with: name: spell_check_output diff --git a/data/json/effects_on_condition/dream_eocs.json b/data/json/effects_on_condition/dream_eocs.json index 271a39fb61e85..3a292c8e4f704 100644 --- a/data/json/effects_on_condition/dream_eocs.json +++ b/data/json/effects_on_condition/dream_eocs.json @@ -26,7 +26,7 @@ "condition": { "and": [ { - "or": [ + "and": [ { "not": { "u_has_effect": "pre_common_cold" } }, { "not": { "u_has_effect": "common_cold" } }, { "not": { "u_has_effect": "pre_flu" } }, diff --git a/data/json/faults/faults_electronic.json b/data/json/faults/faults_electronic.json index 94c67650e1d9b..49921a98d1194 100644 --- a/data/json/faults/faults_electronic.json +++ b/data/json/faults/faults_electronic.json @@ -36,11 +36,8 @@ "faults_removed": [ "fault_electronic_blown_capacitor" ], "skills": { "electronics": 4 }, "requirements": [ - { - "qualities": [ { "id": "SCREW", "level": 1 } ], - "tools": [ [ "soldering_iron" ], [ "soldering_iron_portable" ] ], - "components": [ [ [ "e_scrap", 1 ] ] ] - } + [ "soldering_standard", 5 ], + { "qualities": [ { "id": "SCREW", "level": 1 } ], "components": [ [ [ "e_scrap", 1 ] ] ] } ] }, { @@ -61,11 +58,8 @@ "faults_removed": [ "fault_electronic_shorted_circuit" ], "skills": { "electronics": 5 }, "requirements": [ - { - "qualities": [ { "id": "SCREW", "level": 1 } ], - "tools": [ [ "soldering_iron" ], [ "soldering_iron_portable" ] ], - "components": [ [ [ "circuit", 1 ] ] ] - } + [ "soldering_standard", 5 ], + { "qualities": [ { "id": "SCREW", "level": 1 } ], "components": [ [ [ "circuit", 1 ] ] ] } ] } ] diff --git a/data/json/itemgroups/vending_machines.json b/data/json/itemgroups/vending_machines.json index 381fba3cd6ec1..155b6a020b5e4 100644 --- a/data/json/itemgroups/vending_machines.json +++ b/data/json/itemgroups/vending_machines.json @@ -25,19 +25,6 @@ { "group": "vending_drink_items", "prob": 20, "count-min": 5, "count-max": 25 } ] }, - { - "type": "item_group", - "subtype": "collection", - "id": "vending_ammo", - "entries": [ - { "group": "ammo_pistol_common", "count-min": 3, "count-max": 8 }, - { "group": "ammo_rifle_common", "prob": 50, "count-min": 2, "count-max": 6 }, - { "group": "ammo_shotgun_common", "prob": 50, "count-min": 2, "count-max": 6 }, - { "group": "ammo_pistol_rare", "prob": 20, "count-min": 1, "count-max": 2 }, - { "group": "ammo_rifle_rare", "prob": 20, "count-min": 1, "count-max": 2 }, - { "group": "ammo_shotgun_rare", "prob": 20, "count-min": 1, "count-max": 2 } - ] - }, { "id": "vending_drink_home_impr", "type": "item_group", diff --git a/data/json/items/armor/storage.json b/data/json/items/armor/storage.json index fad17b8a58a61..0caeac89eb682 100644 --- a/data/json/items/armor/storage.json +++ b/data/json/items/armor/storage.json @@ -2637,8 +2637,8 @@ "pocket_data": [ { "pocket_type": "CONTAINER", - "max_contains_volume": "25 L", - "max_contains_weight": "30 kg", + "max_contains_volume": "15 L", + "max_contains_weight": "15 kg", "max_item_length": "60 cm", "moves": 300 } diff --git a/data/json/items/gun/22.json b/data/json/items/gun/22.json index 2f584d1467290..ac9e0ab8b33cb 100644 --- a/data/json/items/gun/22.json +++ b/data/json/items/gun/22.json @@ -100,7 +100,7 @@ [ "underbarrel mount", 1 ] ], "faults": [ "fault_gun_blackpowder", "fault_gun_dirt" ], - "flags": [ "RELOAD_ONE" ], + "flags": [ "RELOAD_ONE", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", diff --git a/data/json/items/gun/270win.json b/data/json/items/gun/270win.json index 4dc21e9650567..1e2dfb1fdc797 100644 --- a/data/json/items/gun/270win.json +++ b/data/json/items/gun/270win.json @@ -30,7 +30,7 @@ "clip_size": 4, "barrel_volume": "750 ml", "barrel_length": "610 mm", - "flags": [ "RELOAD_ONE", "NEVER_JAMS", "EASY_CLEAN" ], + "flags": [ "RELOAD_ONE", "NEVER_JAMS", "EASY_CLEAN", "NO_TURRET" ], "valid_mod_locations": [ [ "barrel", 1 ], [ "brass catcher", 1 ], diff --git a/data/json/items/gun/300.json b/data/json/items/gun/300.json index 171a89f238bc6..f920623434202 100644 --- a/data/json/items/gun/300.json +++ b/data/json/items/gun/300.json @@ -19,7 +19,7 @@ "dispersion": 90, "durability": 8, "barrel_volume": "500 ml", - "flags": [ "NEVER_JAMS", "EASY_CLEAN" ], + "flags": [ "NEVER_JAMS", "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", "item_restriction": [ "m2010mag" ] } ], "melee_damage": { "bash": 12 } }, @@ -46,7 +46,7 @@ "blackpowder_tolerance": 24, "clip_size": 3, "barrel_volume": "750 ml", - "flags": [ "RELOAD_ONE", "EASY_CLEAN" ], + "flags": [ "RELOAD_ONE", "EASY_CLEAN", "NO_TURRET" ], "valid_mod_locations": [ [ "barrel", 1 ], [ "brass catcher", 1 ], @@ -84,7 +84,7 @@ "blackpowder_tolerance": 24, "clip_size": 3, "barrel_volume": "750 ml", - "flags": [ "RELOAD_ONE", "EASY_CLEAN" ], + "flags": [ "RELOAD_ONE", "EASY_CLEAN", "NO_TURRET" ], "valid_mod_locations": [ [ "barrel", 1 ], [ "brass catcher", 1 ], @@ -136,7 +136,7 @@ [ "stock accessory", 2 ], [ "stock", 1 ] ], - "flags": [ "EASY_CLEAN" ], + "flags": [ "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "magazine_well": "300 ml", diff --git a/data/json/items/gun/3006.json b/data/json/items/gun/3006.json index 2ee698b6e43cf..d5f450c8d305b 100644 --- a/data/json/items/gun/3006.json +++ b/data/json/items/gun/3006.json @@ -36,6 +36,7 @@ [ "underbarrel mount", 1 ] ], "faults": [ "fault_gun_blackpowder", "fault_gun_dirt" ], + "flags": [ "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", "item_restriction": [ "blrmag" ] } ], "melee_damage": { "bash": 12 } }, @@ -116,7 +117,7 @@ [ "stock mount", 1 ], [ "underbarrel mount", 1 ] ], - "flags": [ "RELOAD_ONE", "EASY_CLEAN" ], + "flags": [ "RELOAD_ONE", "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "3006": 5 }, "allowed_speedloaders": [ "3006_clip" ] } ], @@ -188,7 +189,7 @@ "blackpowder_tolerance": 24, "clip_size": 4, "barrel_volume": "750 ml", - "flags": [ "RELOAD_ONE", "NEVER_JAMS", "EASY_CLEAN" ], + "flags": [ "RELOAD_ONE", "NEVER_JAMS", "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "3006": 4 } } ], "melee_damage": { "bash": 12 } }, @@ -232,7 +233,7 @@ [ "stock accessory", 2 ], [ "stock", 1 ] ], - "flags": "RELOAD_ONE", + "flags": [ "RELOAD_ONE", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "3006": 4 } } ], "melee_damage": { "bash": 12 } } diff --git a/data/json/items/gun/303.json b/data/json/items/gun/303.json index 7821f91de5851..7cb1a336a6821 100644 --- a/data/json/items/gun/303.json +++ b/data/json/items/gun/303.json @@ -28,7 +28,7 @@ "dispersion": 170, "durability": 8, "blackpowder_tolerance": 40, - "flags": [ "EASY_CLEAN" ], + "flags": [ "EASY_CLEAN", "NO_TURRET" ], "valid_mod_locations": [ [ "barrel", 1 ], [ "bayonet lug", 1 ], @@ -74,7 +74,7 @@ "dispersion": 150, "durability": 8, "blackpowder_tolerance": 40, - "flags": [ "EASY_CLEAN" ], + "flags": [ "EASY_CLEAN", "NO_TURRET" ], "valid_mod_locations": [ [ "barrel", 1 ], [ "bayonet lug", 1 ], diff --git a/data/json/items/gun/308.json b/data/json/items/gun/308.json index 392a6ca30a5a2..61e356f541364 100644 --- a/data/json/items/gun/308.json +++ b/data/json/items/gun/308.json @@ -289,7 +289,7 @@ "blackpowder_tolerance": 24, "clip_size": 3, "barrel_volume": "750 ml", - "flags": [ "RELOAD_ONE", "NEVER_JAMS", "EASY_CLEAN" ], + "flags": [ "RELOAD_ONE", "NEVER_JAMS", "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "308": 3 } } ], "melee_damage": { "bash": 12 } }, @@ -351,7 +351,7 @@ [ "rail mount", 1 ], [ "underbarrel", 1 ] ], - "flags": [ "RELOAD_ONE", "NEVER_JAMS", "EASY_CLEAN" ], + "flags": [ "RELOAD_ONE", "NEVER_JAMS", "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "308": 5 } } ], "melee_damage": { "bash": 12 } }, @@ -566,7 +566,7 @@ [ "underbarrel", 1 ], [ "underbarrel mount", 1 ] ], - "flags": [ "NEVER_JAMS", "EASY_CLEAN" ], + "flags": [ "NEVER_JAMS", "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", "item_restriction": [ "steyr_scout_mag", "steyr_scout_mag_makeshift" ] } ], "melee_damage": { "bash": 10 } } diff --git a/data/json/items/gun/338lapua.json b/data/json/items/gun/338lapua.json index b7ffb048b0869..8fc0b9a344f06 100644 --- a/data/json/items/gun/338lapua.json +++ b/data/json/items/gun/338lapua.json @@ -28,7 +28,7 @@ "durability": 10, "blackpowder_tolerance": 24, "default_mods": [ "cheek_pad", "butt_hook", "bipod", "rifle_scope", "muzzle_brake" ], - "flags": [ "EASY_CLEAN" ], + "flags": [ "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", "item_restriction": [ "ai_338mag", "ai_338mag_10" ] } ], "melee_damage": { "bash": 12 } }, @@ -75,7 +75,7 @@ [ "rail mount", 1 ], [ "stock mount", 1 ] ], - "flags": [ "RELOAD_ONE", "RELOAD_EJECT", "EASY_CLEAN" ], + "flags": [ "RELOAD_ONE", "RELOAD_EJECT", "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "338lapua": 1 } } ], "melee_damage": { "bash": 12 } }, @@ -108,7 +108,7 @@ "durability": 10, "blackpowder_tolerance": 24, "built_in_mods": [ "cheek_pad" ], - "flags": [ "EASY_CLEAN" ], + "flags": [ "EASY_CLEAN", "NO_TURRET" ], "//": "Cheek pad required for holding the buttstock in place and keep it from folding.", "default_mods": [ "match_trigger", "muzzle_brake" ], "valid_mod_locations": [ @@ -166,7 +166,7 @@ [ "underbarrel", 1 ], [ "stock", 1 ] ], - "flags": [ "NO_TURRET", "EASY_CLEAN" ], + "flags": [ "NO_TURRET", "EASY_CLEAN", "NO_TURRET" ], "//3": "This should be removed once vehicle turrets are capable of mounting guns with mods attached. As it stands, trying to mount this style of weapon would require the player to remove the conversion kit, thus rendering it unusable anyhow.", "melee_damage": { "bash": 12 } } diff --git a/data/json/items/gun/36paper.json b/data/json/items/gun/36paper.json index 0dce2e56ed9ec..dbe3b878b243a 100644 --- a/data/json/items/gun/36paper.json +++ b/data/json/items/gun/36paper.json @@ -19,6 +19,7 @@ "blackpowder_tolerance": 96, "clip_size": 6, "proportional": { "reload": 2.0 }, + "flags": [ "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "36paper": 6 } } ], "melee_damage": { "bash": 8 } } diff --git a/data/json/items/gun/38.json b/data/json/items/gun/38.json index c47f7842c98ed..f31068de85e54 100644 --- a/data/json/items/gun/38.json +++ b/data/json/items/gun/38.json @@ -28,7 +28,7 @@ "reload": 200, "valid_mod_locations": [ [ "grip", 1 ], [ "sights", 1 ], [ "underbarrel", 1 ], [ "rail mount", 1 ], [ "stock mount", 1 ] ], "faults": [ "fault_gun_blackpowder", "fault_gun_dirt" ], - "flags": [ "RELOAD_ONE", "RELOAD_EJECT", "EASY_CLEAN" ], + "flags": [ "RELOAD_ONE", "RELOAD_EJECT", "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "38": 2 } } ], "melee_damage": { "bash": 3 } }, diff --git a/data/json/items/gun/44.json b/data/json/items/gun/44.json index 34255e82e904a..a025f9c83cfc2 100644 --- a/data/json/items/gun/44.json +++ b/data/json/items/gun/44.json @@ -77,6 +77,7 @@ [ "rail mount", 1 ], [ "underbarrel mount", 1 ] ], + "flags": [ "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "44": 10 } } ], "melee_damage": { "bash": 12 } }, diff --git a/data/json/items/gun/44paper.json b/data/json/items/gun/44paper.json index 0fbc54510781d..4e162f8653c87 100644 --- a/data/json/items/gun/44paper.json +++ b/data/json/items/gun/44paper.json @@ -18,6 +18,7 @@ "durability": 7, "blackpowder_tolerance": 96, "clip_size": 6, + "flags": [ "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "44paper": 6 } } ], "melee_damage": { "bash": 8 } } diff --git a/data/json/items/gun/4570.json b/data/json/items/gun/4570.json index 018acfd6e1d9b..8c4cf48206f69 100644 --- a/data/json/items/gun/4570.json +++ b/data/json/items/gun/4570.json @@ -32,7 +32,7 @@ [ "stock mount", 1 ], [ "underbarrel mount", 1 ] ], - "flags": [ "RELOAD_ONE" ], + "flags": [ "RELOAD_ONE", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "4570": 6 } } ], "melee_damage": { "bash": 12 } }, diff --git a/data/json/items/gun/458wm.json b/data/json/items/gun/458wm.json index 580742a65cbf7..fc8c179e1ff88 100644 --- a/data/json/items/gun/458wm.json +++ b/data/json/items/gun/458wm.json @@ -19,6 +19,7 @@ "price": 176000, "price_postapoc": 5000, "ammo": [ "458wm" ], + "flags": [ "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "458wm": 3 } } ] } ] diff --git a/data/json/items/gun/45colt.json b/data/json/items/gun/45colt.json index f143c29a7a42f..8699232c9aab9 100644 --- a/data/json/items/gun/45colt.json +++ b/data/json/items/gun/45colt.json @@ -31,7 +31,7 @@ [ "stock mount", 1 ], [ "underbarrel mount", 1 ] ], - "flags": [ "RELOAD_ONE", "NEVER_JAMS", "RELOAD_EJECT", "EASY_CLEAN" ], + "flags": [ "RELOAD_ONE", "NEVER_JAMS", "RELOAD_EJECT", "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "45colt": 2, "410shot": 2 } } ], "melee_damage": { "bash": 2 } }, @@ -96,6 +96,7 @@ "clip_size": 6, "blackpowder_tolerance": 56, "//proportional": { "reload": 1.5 }, + "flags": [ "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "45colt": 6 } } ], "melee_damage": { "bash": 8 } } diff --git a/data/json/items/gun/50.json b/data/json/items/gun/50.json index f76e55fe30382..5ca0a76bcfc5d 100644 --- a/data/json/items/gun/50.json +++ b/data/json/items/gun/50.json @@ -114,7 +114,7 @@ "reload": 450, "barrel_volume": "1250 ml", "default_mods": [ "recoil_stock", "bipod", "rifle_scope", "muzzle_brake" ], - "flags": [ "NEVER_JAMS", "EASY_CLEAN" ], + "flags": [ "NEVER_JAMS", "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", "item_restriction": [ "tac50mag" ] } ], "melee_damage": { "bash": 12 } }, @@ -154,7 +154,7 @@ ], "default_mods": [ "bipod", "rifle_scope", "muzzle_brake" ], "clip_size": 1, - "flags": [ "NEVER_JAMS", "RELOAD_EJECT", "EASY_CLEAN" ], + "flags": [ "NEVER_JAMS", "RELOAD_EJECT", "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "50": 1 } } ], "melee_damage": { "bash": 12 } } diff --git a/data/json/items/gun/762R.json b/data/json/items/gun/762R.json index 0d7e0c3a93fca..a9964a8c55c51 100644 --- a/data/json/items/gun/762R.json +++ b/data/json/items/gun/762R.json @@ -51,7 +51,7 @@ [ "stock accessory", 2 ], [ "underbarrel", 1 ] ], - "flags": [ "RELOAD_ONE" ], + "flags": [ "RELOAD_ONE", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "762R": 5 }, "allowed_speedloaders": [ "762R_clip" ] } ], @@ -107,7 +107,7 @@ [ "stock accessory", 2 ], [ "underbarrel mount", 1 ] ], - "flags": [ "RELOAD_ONE" ], + "flags": [ "RELOAD_ONE", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "762R": 5 }, "allowed_speedloaders": [ "762R_clip" ] } ], diff --git a/data/json/items/gun/77mm_jap.json b/data/json/items/gun/77mm_jap.json index 92e9cc4fd6b97..871af8bcc30de 100644 --- a/data/json/items/gun/77mm_jap.json +++ b/data/json/items/gun/77mm_jap.json @@ -34,7 +34,7 @@ "durability": 10, "blackpowder_tolerance": 24, "clip_size": 5, - "flags": [ "RELOAD_ONE", "NEVER_JAMS", "EASY_CLEAN" ], + "flags": [ "RELOAD_ONE", "NEVER_JAMS", "EASY_CLEAN", "NO_TURRET" ], "valid_mod_locations": [ [ "barrel", 1 ], [ "bayonet lug", 1 ], diff --git a/data/json/items/gun/artisan_guns.json b/data/json/items/gun/artisan_guns.json index a82e5b134b69a..088191eccfd6a 100644 --- a/data/json/items/gun/artisan_guns.json +++ b/data/json/items/gun/artisan_guns.json @@ -100,7 +100,7 @@ "to_hit": { "grip": "weapon", "length": "hand", "surface": "point", "balance": "neutral" }, "qualities": [ [ "CUT", 2 ], [ "CUT_FINE", 1 ], [ "BUTCHER", 14 ] ], "techniques": [ "RAPID" ], - "flags": [ "DURABLE_MELEE", "ALLOWS_BODY_BLOCK" ], + "flags": [ "DURABLE_MELEE", "ALLOWS_BODY_BLOCK", "NO_TURRET" ], "weapon_category": [ "AUTOMATIC_PISTOLS", "SHIVS" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "ammo_restriction": { "32": 2 } } ], "melee_damage": { "stab": 16 } diff --git a/data/json/items/gun/shot.json b/data/json/items/gun/shot.json index 318892a66bc7a..66c88f4c3509c 100644 --- a/data/json/items/gun/shot.json +++ b/data/json/items/gun/shot.json @@ -723,7 +723,7 @@ [ "sights mount", 1 ], [ "underbarrel mount", 1 ] ], - "flags": [ "RELOAD_ONE" ], + "flags": [ "RELOAD_ONE", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "shot": 6 } } ], "melee_damage": { "bash": 8 } }, @@ -819,6 +819,7 @@ [ "stock accessory", 2 ], [ "underbarrel mount", 1 ] ], + "flags": [ "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "shot": 4 } } ] }, { @@ -877,7 +878,7 @@ "reload": 600, "modes": [ [ "DEFAULT", "single", 1 ] ], "valid_mod_locations": [ [ "sling", 1 ], [ "sights mount", 1 ], [ "underbarrel mount", 1 ] ], - "flags": [ "RELOAD_EJECT", "EASY_CLEAN" ], + "flags": [ "RELOAD_EJECT", "EASY_CLEAN", "NO_TURRET" ], "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "shot": 1 } } ], "melee_damage": { "bash": 8 } }, diff --git a/data/json/mapgen/s_gun.json b/data/json/mapgen/s_gun.json index ad797d8497365..f61fbbd872f0d 100644 --- a/data/json/mapgen/s_gun.json +++ b/data/json/mapgen/s_gun.json @@ -200,7 +200,7 @@ ",,,,,,,,,,,,,,,,,,,,,,,," ], "palettes": [ "gun_store_palette" ], - "vendingmachines": { "V": { "item_group": "vending_ammo", "lootable": false } }, + "vendingmachines": { "V": { "item_group": "vending_drink", "lootable": false } }, "terrain": { ";": "t_sidewalk" }, "place_loot": [ { "group": "cash_register_random", "x": [ 4, 6 ], "y": 5 }, @@ -306,7 +306,7 @@ ], "palettes": [ "gun_store_palette" ], "terrain": { ";": "t_sidewalk" }, - "vendingmachines": { "V": { "item_group": "vending_ammo", "lootable": true } }, + "vendingmachines": { "V": { "item_group": "vending_drink", "lootable": true } }, "nested": { "#": { "chunks": [ [ "general_graffiti", 15 ], [ "null", 75 ] ] }, "m": { "chunks": [ [ "destroyed_furniture", 40 ], [ "null", 80 ] ] }, diff --git a/data/json/materials.json b/data/json/materials.json index c5e9b013b70a5..9e4eea6d9676d 100644 --- a/data/json/materials.json +++ b/data/json/materials.json @@ -1178,11 +1178,11 @@ "latent_heat": 247, "conductive": true, "chip_resist": 15, - "repaired_with": "scrap", + "repaired_with": "scrap_cast_iron", "dmg_adj": [ "marked", "dented", "smashed", "shattered" ], "bash_dmg_verb": "dented", "cut_dmg_verb": "scratched", - "burn_products": [ [ "scrap", 0.5 ] ], + "burn_products": [ [ "scrap_cast_iron", 0.5 ] ], "resist": { "bash": 4, "cut": 4, "acid": 5, "heat": 3, "bullet": 2 }, "repair_difficulty": 2 }, diff --git a/data/json/mutations/mutations.json b/data/json/mutations/mutations.json index 71a24a85d6dcc..2a3eabbb17489 100644 --- a/data/json/mutations/mutations.json +++ b/data/json/mutations/mutations.json @@ -1130,7 +1130,7 @@ "sleepiness": true, "kcal": true, "thirst": true, - "enchantments": [ { "values": [ { "value": "MOVE_COST", "multiply": -0.1 }, { "value": "BONUS_DODGE", "add": 2 } ] } ] + "enchantments": [ { "values": [ { "value": "MOVE_COST", "multiply": -0.1 }, { "value": "DODGE_CHANCE", "add": 2 } ] } ] }, { "type": "mutation", @@ -4705,7 +4705,7 @@ "restricts_gear": [ "leg_hip_l", "leg_hip_r" ], "allowed_items": [ "ALLOWS_TAIL" ], "allow_soft_gear": true, - "enchantments": [ { "values": [ { "value": "BONUS_DODGE", "add": 2 } ] } ] + "enchantments": [ { "values": [ { "value": "DODGE_CHANCE", "add": 2 } ] } ] }, { "type": "mutation", @@ -4721,7 +4721,7 @@ "restricts_gear": [ "leg_hip_l", "leg_hip_r" ], "allowed_items": [ "ALLOWS_TAIL" ], "allow_soft_gear": true, - "enchantments": [ { "values": [ { "value": "BONUS_DODGE", "add": 1 } ] } ] + "enchantments": [ { "values": [ { "value": "DODGE_CHANCE", "add": 1 } ] } ] }, { "type": "mutation", @@ -4737,7 +4737,7 @@ "restricts_gear": [ "leg_hip_l", "leg_hip_r" ], "allowed_items": [ "ALLOWS_TAIL" ], "allow_soft_gear": true, - "enchantments": [ { "values": [ { "value": "BONUS_DODGE", "add": 2 } ] } ] + "enchantments": [ { "values": [ { "value": "DODGE_CHANCE", "add": 2 } ] } ] }, { "type": "mutation", @@ -4760,7 +4760,7 @@ "chance": 20, "base_damage": { "damage_type": "bash", "amount": 8 } }, - "enchantments": [ { "values": [ { "value": "BONUS_DODGE", "add": 1 } ] } ] + "enchantments": [ { "values": [ { "value": "DODGE_CHANCE", "add": 1 } ] } ] }, { "type": "mutation", @@ -4799,7 +4799,7 @@ "restricts_gear": [ "leg_hip_l", "leg_hip_r" ], "allowed_items": [ "ALLOWS_TAIL" ], "allow_soft_gear": true, - "enchantments": [ { "values": [ { "value": "BONUS_DODGE", "add": 3 } ] } ] + "enchantments": [ { "values": [ { "value": "DODGE_CHANCE", "add": 3 } ] } ] }, { "type": "mutation", @@ -4815,7 +4815,7 @@ "allowed_items": [ "ALLOWS_TAIL" ], "allow_soft_gear": true, "social_modifiers": { "lie": -20, "persuade": 10 }, - "enchantments": [ { "values": [ { "value": "BONUS_DODGE", "add": 4 } ] } ] + "enchantments": [ { "values": [ { "value": "DODGE_CHANCE", "add": 4 } ] } ] }, { "type": "mutation", @@ -6129,7 +6129,7 @@ "enchantments": [ { "values": [ - { "value": "BONUS_DODGE", "add": 1 }, + { "value": "DODGE_CHANCE", "add": 1 }, { "value": "MAX_HP", "multiply": -0.05 }, { "value": "STOMACH_SIZE_MULTIPLIER", "multiply": -0.5 }, { "value": "CARRY_WEIGHT", "multiply": -0.2 } @@ -6153,7 +6153,7 @@ "enchantments": [ { "values": [ - { "value": "BONUS_DODGE", "add": 2 }, + { "value": "DODGE_CHANCE", "add": 2 }, { "value": "MAX_HP", "multiply": -0.3 }, { "value": "FOOTSTEP_NOISE", "multiply": -1 }, { "value": "CARRY_WEIGHT", "multiply": -0.5 }, @@ -6179,7 +6179,7 @@ "enchantments": [ { "values": [ - { "value": "BONUS_DODGE", "add": 2 }, + { "value": "DODGE_CHANCE", "add": 2 }, { "value": "MAX_HP", "multiply": -0.25 }, { "value": "FOOTSTEP_NOISE", "multiply": -1 }, { "value": "STOMACH_SIZE_MULTIPLIER", "multiply": -0.5 }, @@ -6404,7 +6404,7 @@ "category": [ "INSECT" ], "restricts_gear": [ "torso" ], "social_modifiers": { "lie": 15, "persuade": 5, "intimidate": -20 }, - "enchantments": [ { "values": [ { "value": "MOVE_COST", "multiply": -0.1 }, { "value": "BONUS_DODGE", "add": -4 } ] } ], + "enchantments": [ { "values": [ { "value": "MOVE_COST", "multiply": -0.1 }, { "value": "DODGE_CHANCE", "add": -4 } ] } ], "flags": [ "WINGS_1" ] }, { @@ -6742,7 +6742,7 @@ { "value": "ATTACK_SPEED", "multiply": 0.05 }, { "value": "MAX_HP", "add": 4 }, { "value": "MOVECOST_SWIM_MOD", "multiply": 0.2 }, - { "value": "BONUS_DODGE", "add": -1 }, + { "value": "DODGE_CHANCE", "add": -1 }, { "value": "CARRY_WEIGHT", "multiply": 0.15 } ] } @@ -9186,7 +9186,7 @@ "points": 2, "description": "You have fast reflexes, allowing you to dodge attacks more easily.", "starting_trait": true, - "enchantments": [ { "values": [ { "value": "BONUS_DODGE", "add": 3 } ] } ], + "enchantments": [ { "values": [ { "value": "DODGE_CHANCE", "add": 3 } ] } ], "category": [ "FELINE" ] }, { diff --git a/data/json/npcs/TALK_TEST.json b/data/json/npcs/TALK_TEST.json index cab58a8d623a1..c3ebc235753e6 100644 --- a/data/json/npcs/TALK_TEST.json +++ b/data/json/npcs/TALK_TEST.json @@ -1210,17 +1210,22 @@ { "text": "Sets Test Proficiency learning done to 12 hours total.", "topic": "TALK_DONE", - "effect": { "math": [ "u_proficiency('prof_test', 'format': 'time_spent')", "=", "time('12h')" ] } + "effect": { "math": [ "u_proficiency('prof_test', 'format': 'time_spent', 'direct': true)", "=", "time('12h')" ] } }, { "text": "Sets Test Proficiency learning done to -1.", "topic": "TALK_DONE", - "effect": { "math": [ "u_proficiency('prof_test', 'format': 'time_spent')", "=", "-1" ] } + "effect": { "math": [ "u_proficiency('prof_test', 'format': 'time_spent', 'direct': true)", "=", "-1" ] } }, { "text": "Sets Test Proficiency learning done to 24h.", "topic": "TALK_DONE", - "effect": { "math": [ "u_proficiency('prof_test', 'format': 'time_spent')", "=", "time('24h')" ] } + "effect": { "math": [ "u_proficiency('prof_test', 'format': 'time_spent', 'direct': true)", "=", "time('24h')" ] } + }, + { + "text": "Learns Test Proficiency for 1h", + "topic": "TALK_DONE", + "effect": { "math": [ "u_proficiency('prof_test', 'format': 'time_spent')", "+=", "time('1h')" ] } } ] }, diff --git a/data/json/recipes/chem/fuel.json b/data/json/recipes/chem/fuel.json index dc19ccd7487e5..c2342170e68a1 100644 --- a/data/json/recipes/chem/fuel.json +++ b/data/json/recipes/chem/fuel.json @@ -84,7 +84,7 @@ "//3": "about 15% of the total reaction becomes kerosene-like hydrocarbons and about 50% becomes diesel-like hydrocarbons. So it is intentional that this produces 3x the diesel as kerosene.", "//4": "Thus the whole recipe produces about 5 kg of diesel (6000 ml) and 1.5 liters of kerosene (1800 ml)", "//5": "These reactors operate at 10-15 KW power levels for long periods of time and each batch is processing a pretty large amount of material. Specific heats give us about 40 MJ just to get to temp (550c)", - "tools": [ [ [ "catalytic_cracking_reactor", 50000 ] ], [ [ "water", 40 ], [ "water_clean", 40 ] ] ], + "tools": [ [ [ "catalytic_cracking_reactor_tool", 50000 ] ], [ [ "water", 40 ], [ "water_clean", 40 ] ] ], "components": [ [ [ "chem_washing_soda", 40 ] ], [ diff --git a/data/json/zones.json b/data/json/zones.json index 45933f4aaa4da..35dd4e323da8b 100644 --- a/data/json/zones.json +++ b/data/json/zones.json @@ -46,7 +46,7 @@ "type": "LOOT_ZONE", "name": "Disassembly Work", "display_field": "fd_disassembly_work_zone", - "description": "Items in this zone are marked for disassembly" + "description": "Items in this zone are marked for disassembly." }, { "id": "FARM_PLOT", diff --git a/data/mods/Backrooms/itemgroups.json b/data/mods/Backrooms/itemgroups.json index 054cf08900411..815c6e4917a72 100644 --- a/data/mods/Backrooms/itemgroups.json +++ b/data/mods/Backrooms/itemgroups.json @@ -698,6 +698,19 @@ { "group": "wreckage", "count": [ 1, 3 ], "prob": 25 } ] }, + { + "type": "item_group", + "subtype": "collection", + "id": "vending_ammo", + "entries": [ + { "group": "ammo_pistol_common", "count-min": 3, "count-max": 8 }, + { "group": "ammo_rifle_common", "prob": 50, "count-min": 2, "count-max": 6 }, + { "group": "ammo_shotgun_common", "prob": 50, "count-min": 2, "count-max": 6 }, + { "group": "ammo_pistol_rare", "prob": 20, "count-min": 1, "count-max": 2 }, + { "group": "ammo_rifle_rare", "prob": 20, "count-min": 1, "count-max": 2 }, + { "group": "ammo_shotgun_rare", "prob": 20, "count-min": 1, "count-max": 2 } + ] + }, { "type": "item_group", "id": "backrooms_master_vending", diff --git a/data/mods/DinoMod/mutations/mutations.json b/data/mods/DinoMod/mutations/mutations.json index ff5b1658c04aa..cfb951aae1397 100644 --- a/data/mods/DinoMod/mutations/mutations.json +++ b/data/mods/DinoMod/mutations/mutations.json @@ -390,7 +390,7 @@ "base_damage": { "damage_type": "bash", "amount": 24 }, "strength_damage": { "damage_type": "stab", "amount": 2 } }, - "enchantments": [ { "values": [ { "value": "BONUS_DODGE", "add": 1 } ] } ] + "enchantments": [ { "values": [ { "value": "DODGE_CHANCE", "add": 1 } ] } ] }, { "type": "mutation", diff --git a/data/mods/Magiclysm/mutations/fantasy_species.json b/data/mods/Magiclysm/mutations/fantasy_species.json index 213ffba792489..15b9ea9862be7 100644 --- a/data/mods/Magiclysm/mutations/fantasy_species.json +++ b/data/mods/Magiclysm/mutations/fantasy_species.json @@ -502,7 +502,7 @@ "enchantments": [ { "values": [ - { "value": "BONUS_DODGE", "add": 2 }, + { "value": "DODGE_CHANCE", "add": 2 }, { "value": "MAX_HP", "multiply": -0.25 }, { "value": "STRENGTH", "add": -3 }, { "value": "DEXTERITY", "add": 2 }, diff --git a/data/mods/Magiclysm/mutations/mutations.json b/data/mods/Magiclysm/mutations/mutations.json index d5f0c4f864aee..f1c1d4eedea71 100644 --- a/data/mods/Magiclysm/mutations/mutations.json +++ b/data/mods/Magiclysm/mutations/mutations.json @@ -497,7 +497,7 @@ "prereqs": [ "WINGS_STUB" ], "category": [ "DRAGON_BLACK" ], "threshreq": [ "THRESH_DRAGON_BLACK" ], - "enchantments": [ { "values": [ { "value": "BONUS_DODGE", "add": -3 } ] } ], + "enchantments": [ { "values": [ { "value": "DODGE_CHANCE", "add": -3 } ] } ], "attacks": { "attack_text_u": "You bash %s with your powerful wings!", "attack_text_npc": "%1$s bashes %2$s with their powerful wings!", diff --git a/data/mods/MindOverMatter/PowerDescriptionSpoilers.md b/data/mods/MindOverMatter/PowerDescriptionSpoilers.md index 6b1d2645e8ede..f6861a414927c 100644 --- a/data/mods/MindOverMatter/PowerDescriptionSpoilers.md +++ b/data/mods/MindOverMatter/PowerDescriptionSpoilers.md @@ -1061,7 +1061,7 @@ Powers causing telepathic damage have a 5% chance to down the target, a 33% chan *Duration*: Instant
*Stamina Cost*: 7500, minus 170 per level to a minimum of 4600
*Channeling Time*: 150 moves, minus 5.5 moves per level to a minimum of 75
-*Effects*: Teleports a single monster somewhere *else*, removing them and anything they might drop. The monster must have HP lower than 15 to 350, plus 15 to 35 per power level, randomly determined when the power is used. Oubliette cannot currently affect NPCs.
+*Effects*: Teleports a single target somewhere *else*, removing them and anything they might drop. The target must have HP lower than 15 to 350, plus 15 to 35 per power level, randomly determined when the power is used. For this purpose, NPC health is calculated as the sum total of their limb health, divided by 3.
*Prerequisites*: Displacement 10, Farstep 6 *or* Transposition 8 *or * Spacial Vortex 8
## Gateway diff --git a/data/mods/MindOverMatter/effectoncondition/conditions_for_eocs.json b/data/mods/MindOverMatter/effectoncondition/conditions_for_eocs.json new file mode 100644 index 0000000000000..32ad3edbaaeae --- /dev/null +++ b/data/mods/MindOverMatter/effectoncondition/conditions_for_eocs.json @@ -0,0 +1,198 @@ +[ + { + "type": "effect_on_condition", + "id": "EOC_CONDITION_SPELLCASTING_FINISH_TRAIT_AND_SCHOOL_LIST", + "condition": { + "and": [ + { + "u_has_any_trait": [ + "BIOKINETIC", + "CLAIRSENTIENT", + "ELECTROKINETIC", + "PHOTOKINETIC", + "PYROKINETIC", + "TELEKINETIC", + "TELEPATH", + "TELEPORTER", + "VITAKINETIC" + ] + }, + { + "or": [ + { "compare_string": [ "BIOKINETIC", { "context_val": "school" } ] }, + { "compare_string": [ "CLAIRSENTIENT", { "context_val": "school" } ] }, + { "compare_string": [ "ELECTROKINETIC", { "context_val": "school" } ] }, + { "compare_string": [ "PHOTOKINETIC", { "context_val": "school" } ] }, + { "compare_string": [ "PYROKINETIC", { "context_val": "school" } ] }, + { "compare_string": [ "TELEKINETIC", { "context_val": "school" } ] }, + { "compare_string": [ "TELEPATH", { "context_val": "school" } ] }, + { "compare_string": [ "TELEPORTER", { "context_val": "school" } ] }, + { "compare_string": [ "VITAKINETIC", { "context_val": "school" } ] } + ] + } + ] + }, + "effect": [ ] + }, + { + "type": "effect_on_condition", + "id": "EOC_CONDITION_CAUGHT_IN_NETHER_WEATHER", + "condition": { + "or": [ { "is_weather": "distant_portal_storm" }, { "is_weather": "portal_storm" }, { "is_weather": "close_portal_storm" } ] + }, + "effect": [ ] + }, + { + "type": "effect_on_condition", + "id": "EOC_CONDITION_NEAR_NETHER_RELATED_LOCATION", + "condition": { + "or": [ + { "u_near_om_location": "unvitrified_farm_0", "range": 2 }, + { "u_near_om_location": "unvitrified_farm_1", "range": 2 }, + { "u_near_om_location": "unvitrified_farm_neg_1", "range": 2 }, + { "u_near_om_location": "unvitrified_farm_2", "range": 2 }, + { "u_near_om_location": "vitrified_farm_0", "range": 2 }, + { "u_near_om_location": "vitrified_farm_1", "range": 2 }, + { "u_near_om_location": "vitrified_farm_neg_1", "range": 2 }, + { "u_near_om_location": "vitrified_farm_2", "range": 2 }, + { "u_near_om_location": "microlab_portal_elevator_physics_glass", "range": 2 }, + { "u_near_om_location": "microlab_distorted_hallway", "range": 2 }, + { "u_near_om_location": "microlab_distorted", "range": 2 }, + { "u_near_om_location": "microlab_distorted_edge", "range": 2 }, + { "u_near_om_location": "microlab_portal_elevator_physics_glass", "range": 2 }, + { "u_near_om_location": "corpse_surface", "range": 0 }, + { "u_near_om_location": "corpse_bowels_neck_right", "range": 2 }, + { "u_near_om_location": "corpse_bowels_neck_left", "range": 2 }, + { "u_near_om_location": "corpse_bowels_neck_edge_center", "range": 2 }, + { "u_near_om_location": "corpse_bowels_rcorner", "range": 2 }, + { "u_near_om_location": "corpse_bowels_lcorner", "range": 2 }, + { "u_near_om_location": "corpse_bowels_empty_edge", "range": 2 }, + { "u_near_om_location": "corpse_bowels_mid", "range": 2 }, + { "u_near_om_location": "corpse_tentacle", "range": 2 }, + { "u_near_om_location": "corpse_tentacle_entry", "range": 2 }, + { "u_near_om_location": "corpse_tentacle_surface_entry", "range": 0 }, + { "u_near_om_location": "corpse_bowels_tentacle_edge", "range": 2 }, + { "u_near_om_location": "corpse_bowels_empty_edge", "range": 2 }, + { "u_near_om_location": "corpse_head", "range": 2 }, + { "u_near_om_location": "corpse_brain", "range": 2 }, + { "u_near_om_location": "corpse_under_brain", "range": 2 }, + { "u_near_om_location": "corpse_head_edge", "range": 2 }, + { "u_near_om_location": "corpse_head_fin", "range": 2 }, + { "u_near_om_location": "corpse_head_lcorner", "range": 2 }, + { "u_near_om_location": "corpse_head_rcorner", "range": 2 }, + { "u_near_om_location": "corpse_head_neck_l", "range": 2 }, + { "u_near_om_location": "corpse_head_neck_r", "range": 2 }, + { "u_near_om_location": "corpse_head_neck_center", "range": 2 }, + { "u_near_om_location": "corpse_head_neck_l_decap", "range": 2 }, + { "u_near_om_location": "corpse_head_neck_r", "range": 2 }, + { "u_near_om_location": "corpse_head_neck_r_decap", "range": 2 }, + { "u_near_om_location": "corpse_head_neck_center_decap", "range": 2 }, + { "u_near_om_location": "nether_crystal_field", "range": 1 }, + { "u_near_om_location": "psi_phavian_lab_blockB1", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_blockD1", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_blockB3", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_blockD3", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block2B1", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block2D1", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block2B3", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block2D3", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block3B1", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block3D1", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block3B3", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block3D3", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block4B1", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block4D1", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block4B3", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block4D3", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block5B1", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block5D1", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block5B3", "range": 2 }, + { "u_near_om_location": "psi_phavian_lab_block5D3", "range": 2 }, + { "u_near_om_location": "void_spider_lair_entrance", "range": 2 }, + { "u_near_om_location": "void_spider_lair_a1", "range": 2 }, + { "u_near_om_location": "void_spider_lair_a2", "range": 2 }, + { "u_near_om_location": "LIXA_surface_1b_north", "range": 2 }, + { "u_near_om_location": "LIXA_roof_1a_north", "range": 2 }, + { "u_near_om_location": "LIXA_stairshaft_1a_north", "range": 2 }, + { "u_near_om_location": "LIXA_stairshaft_2a_north", "range": 2 }, + { "u_near_om_location": "LIXA_device_2_north", "range": 2 }, + { "u_near_om_location": "LIXA_device_unfolded_noaccess_north", "range": 2 }, + { "u_near_om_location": "LIXA_entry_2_north", "range": 2 }, + { "u_near_om_location": "LIXA_road_north", "range": 2 }, + { "u_near_om_location": "LIXA_road_guard_north", "range": 2 } + ] + }, + "effect": [ ] + }, + { + "type": "effect_on_condition", + "id": "EOC_CONDITION_LIST_OF_POWERS_CANCELLED_BY_COMBAT", + "condition": { + "or": [ + { "u_has_trait": "CLAIR_SPEED_READ" }, + { "u_has_effect": "effect_clair_speed_reader" }, + { "u_has_effect": "effect_clair_see_auras" }, + { "u_has_effect": "effect_clair_craft_bonus" }, + { "u_has_effect": "effect_clair_perfect_shot" }, + { "u_has_effect": "effect_photokin_light_local" }, + { "u_has_item": "pyrokinetic_fire_tool" }, + { "u_has_item": "pyrokinetic_torch_weld" }, + { "u_has_effect": "effect_telekinetic_strength" }, + { "u_has_item": "telekin_lifting_jack_1" }, + { "u_has_item": "telekin_lifting_jack_2" }, + { "u_has_item": "telekin_lifting_jack_3" }, + { "u_has_item": "telekin_lifting_jack_4" }, + { "u_has_item": "telekin_lifting_jack_5" }, + { "u_has_item": "telekin_lifting_jack_6" }, + { "u_has_item": "telekin_lifting_jack_7" }, + { "u_has_item": "telekin_lifting_jack_8" }, + { "u_has_item": "telekin_lifting_jack_9" }, + { "u_has_item": "telekin_lifting_jack_10" }, + { "u_has_item": "telekin_lifting_jack_11" }, + { "u_has_item": "telekin_lifting_jack_12" }, + { "u_has_item": "telekin_lifting_jack_13" }, + { "u_has_item": "telekin_lifting_jack_14" }, + { "u_has_item": "telekin_lifting_jack_15" }, + { "u_has_item": "telekin_lifting_jack_16" }, + { "u_has_item": "telekin_lifting_jack_17" }, + { "u_has_item": "telekin_lifting_jack_18" }, + { "u_has_item": "telekin_lifting_jack_19" }, + { "u_has_item": "telekin_lifting_jack_20" }, + { "u_has_effect": "effect_telekinetic_levitation" }, + { "u_has_effect": "effect_telepathic_learning_bonus" }, + { "u_has_effect": "telepathic_ignorance_self" } + ] + }, + "effect": [ ] + }, + { + "type": "effect_on_condition", + "id": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE", + "condition": { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } }, + "effect": [ ] + }, + { + "type": "effect_on_condition", + "id": "EOC_PORTAL_STORM_CONDITION_FLAG_PORTAL_PROOF", + "condition": { + "and": [ + { "not": { "u_has_worn_with_flag": "PORTAL_PROOF" } }, + { + "not": { + "and": [ + { "u_has_effect": "effect_telepathic_psi_armor" }, + { + "math": [ + "u_spell_level('telepathic_shield')", + ">=", + "(u_vitamin('vitamin_psionic_drain') / 10) + (max(u_school_level('BIOKINETIC'), u_school_level('CLAIRSENTIENT'), u_school_level('ELECTROKINETIC'), u_school_level('PHOTOKINETIC'), u_school_level('PYROKINETIC'), u_school_level('TELEPATH'), u_school_level('TELEKINETIC'), u_school_level('TELEPORTER'), u_school_level('VITAKINETIC')) / 3) + (u_awakening_countup / 3)" + ] + } + ] + } + } + ] + }, + "effect": [ ] + } +] diff --git a/data/mods/MindOverMatter/effectoncondition/eoc_awakening.json b/data/mods/MindOverMatter/effectoncondition/eoc_awakening.json index f2b7894cc98db..e225b3b3de568 100644 --- a/data/mods/MindOverMatter/effectoncondition/eoc_awakening.json +++ b/data/mods/MindOverMatter/effectoncondition/eoc_awakening.json @@ -27,7 +27,7 @@ { "type": "effect_on_condition", "id": "EOC_BIOKIN_MATRIX_AWAKENING_2", - "condition": { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } }, + "condition": { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" }, "effect": [ { "run_eocs": "EOC_BIOKIN_MATRIX_AWAKENING_SUCCESS" } ], "false_effect": [ { "run_eocs": "EOC_BIOKIN_MATRIX_AWAKENING_FAILURE" } ] }, @@ -88,7 +88,7 @@ { "type": "effect_on_condition", "id": "EOC_CLAIR_MATRIX_AWAKENING_2", - "condition": { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } }, + "condition": { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" }, "effect": [ { "run_eocs": "EOC_CLAIR_MATRIX_AWAKENING_SUCCESS" } ], "false_effect": [ { "run_eocs": "EOC_CLAIR_MATRIX_AWAKENING_FAILURE" } ] }, @@ -149,7 +149,7 @@ { "type": "effect_on_condition", "id": "EOC_ELECTRO_MATRIX_AWAKENING_2", - "condition": { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } }, + "condition": { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" }, "effect": [ { "run_eocs": "EOC_ELECTRO_MATRIX_AWAKENING_SUCCESS" } ], "false_effect": [ { "run_eocs": "EOC_ELECTRO_MATRIX_AWAKENING_FAILURE" } ] }, @@ -210,7 +210,7 @@ { "type": "effect_on_condition", "id": "EOC_PHOTOKIN_MATRIX_AWAKENING_2", - "condition": { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } }, + "condition": { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" }, "effect": [ { "run_eocs": "EOC_PHOTOKIN_MATRIX_AWAKENING_SUCCESS" } ], "false_effect": [ { "run_eocs": "EOC_PHOTOKIN_MATRIX_AWAKENING_FAILURE" } ] }, @@ -273,7 +273,7 @@ { "type": "effect_on_condition", "id": "EOC_PYROKIN_MATRIX_AWAKENING_2", - "condition": { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } }, + "condition": { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" }, "effect": [ { "run_eocs": "EOC_PYROKIN_MATRIX_AWAKENING_SUCCESS" } ], "false_effect": [ { "run_eocs": "EOC_PYROKIN_MATRIX_AWAKENING_FAILURE" } ] }, @@ -335,7 +335,7 @@ { "type": "effect_on_condition", "id": "EOC_TELEKIN_MATRIX_AWAKENING_2", - "condition": { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } }, + "condition": { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" }, "effect": [ { "run_eocs": "EOC_TELEKIN_MATRIX_AWAKENING_SUCCESS" } ], "false_effect": [ { "run_eocs": "EOC_TELEKIN_MATRIX_AWAKENING_FAILURE" } ] }, @@ -396,7 +396,7 @@ { "type": "effect_on_condition", "id": "EOC_TEEP_MATRIX_AWAKENING_2", - "condition": { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } }, + "condition": { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" }, "effect": [ { "run_eocs": "EOC_TEEP_MATRIX_AWAKENING_SUCCESS" } ], "false_effect": [ { "run_eocs": "EOC_TEEP_MATRIX_AWAKENING_FAILURE" } ] }, @@ -457,7 +457,7 @@ { "type": "effect_on_condition", "id": "EOC_TELEPORT_MATRIX_AWAKENING_2", - "condition": { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } }, + "condition": { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" }, "effect": [ { "run_eocs": "EOC_TELEPORT_MATRIX_AWAKENING_SUCCESS" } ], "false_effect": [ { "run_eocs": "EOC_TELEPORT_MATRIX_AWAKENING_FAILURE" } ] }, @@ -520,7 +520,7 @@ { "type": "effect_on_condition", "id": "EOC_VITAKIN_MATRIX_AWAKENING_2", - "condition": { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } }, + "condition": { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" }, "effect": [ { "run_eocs": "EOC_VITAKIN_MATRIX_AWAKENING_SUCCESS" } ], "false_effect": [ { "run_eocs": "EOC_VITAKIN_MATRIX_AWAKENING_FAILURE" } ] }, @@ -604,7 +604,7 @@ "and": [ "u_is_outside", { "is_weather": "distant_portal_storm" }, - { "not": { "u_has_worn_with_flag": "PORTAL_PROOF" } }, + { "test_eoc": "EOC_PORTAL_STORM_CONDITION_FLAG_PORTAL_PROOF" }, { "not": { "u_has_effect": "sleep" } } ] }, @@ -636,7 +636,7 @@ "and": [ "u_is_outside", { "is_weather": "portal_storm" }, - { "not": { "u_has_worn_with_flag": "PORTAL_PROOF" } }, + { "test_eoc": "EOC_PORTAL_STORM_CONDITION_FLAG_PORTAL_PROOF" }, { "not": { "u_has_effect": "sleep" } } ] }, @@ -668,7 +668,7 @@ "and": [ "u_is_outside", { "is_weather": "close_portal_storm" }, - { "not": { "u_has_worn_with_flag": "PORTAL_PROOF" } }, + { "test_eoc": "EOC_PORTAL_STORM_CONDITION_FLAG_PORTAL_PROOF" }, { "not": { "u_has_effect": "sleep" } } ] }, @@ -703,7 +703,7 @@ "and": [ { "not": { "u_has_trait": "BIOKINETIC" } }, { "not": { "u_has_effect": "psionic_awakened" } }, - { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } } + { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" } ] }, "effect": [ @@ -736,7 +736,7 @@ "and": [ { "not": { "u_has_trait": "CLAIRSENTIENT" } }, { "not": { "u_has_effect": "psionic_awakened" } }, - { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } } + { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" } ] }, "effect": [ @@ -769,7 +769,7 @@ "and": [ { "not": { "u_has_trait": "ELECTROKINETIC" } }, { "not": { "u_has_effect": "psionic_awakened" } }, - { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } } + { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" } ] }, "effect": [ @@ -801,7 +801,7 @@ "and": [ { "not": { "u_has_trait": "PHOTOKINETIC" } }, { "not": { "u_has_effect": "psionic_awakened" } }, - { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } } + { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" } ] }, "effect": [ @@ -836,7 +836,7 @@ "and": [ { "not": { "u_has_trait": "PYROKINETIC" } }, { "not": { "u_has_effect": "psionic_awakened" } }, - { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } } + { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" } ] }, "effect": [ @@ -869,7 +869,7 @@ "and": [ { "not": { "u_has_trait": "TELEKINETIC" } }, { "not": { "u_has_effect": "psionic_awakened" } }, - { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } } + { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" } ] }, "effect": [ @@ -901,7 +901,7 @@ "and": [ { "not": { "u_has_trait": "TELEPATH" } }, { "not": { "u_has_effect": "psionic_awakened" } }, - { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } } + { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" } ] }, "effect": [ @@ -934,7 +934,7 @@ "and": [ { "not": { "u_has_trait": "TELEPORTER" } }, { "not": { "u_has_effect": "psionic_awakened" } }, - { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } } + { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" } ] }, "effect": [ @@ -966,7 +966,7 @@ "and": [ { "not": { "u_has_trait": "VITAKINETIC" } }, { "not": { "u_has_effect": "psionic_awakened" } }, - { "x_in_y_chance": { "x": { "math": [ "100 - u_awakening_reducer" ] }, "y": 100 } } + { "test_eoc": "EOC_CONDITION_AWAKENING_X_IN_Y_CHANCE" } ] }, "effect": [ diff --git a/data/mods/MindOverMatter/effectoncondition/eoc_misc.json b/data/mods/MindOverMatter/effectoncondition/eoc_misc.json index 46719a620c99a..48177d540379a 100644 --- a/data/mods/MindOverMatter/effectoncondition/eoc_misc.json +++ b/data/mods/MindOverMatter/effectoncondition/eoc_misc.json @@ -1,28 +1,4 @@ [ - { - "type": "effect_on_condition", - "id": "EOC_PORTAL_STORM_CONDITION_FLAG_PORTAL_PROOF", - "condition": { - "and": [ - { "not": { "u_has_worn_with_flag": "PORTAL_PROOF" } }, - { - "not": { - "and": [ - { "u_has_effect": "effect_telepathic_psi_armor" }, - { - "math": [ - "u_spell_level('telepathic_shield')", - ">=", - "(u_vitamin('vitamin_psionic_drain') / 10) + (max(u_school_level('BIOKINETIC'), u_school_level('CLAIRSENTIENT'), u_school_level('ELECTROKINETIC'), u_school_level('PHOTOKINETIC'), u_school_level('PYROKINETIC'), u_school_level('TELEPATH'), u_school_level('TELEKINETIC'), u_school_level('TELEPORTER'), u_school_level('VITAKINETIC')) / 3) + (u_awakening_countup / 3)" - ] - } - ] - } - } - ] - }, - "effect": [ ] - }, { "type": "effect_on_condition", "id": "EOC_RESET_TELEPATHIC_STEALING_TIMER", diff --git a/data/mods/MindOverMatter/effectoncondition/eoc_nether_attunement_events.json b/data/mods/MindOverMatter/effectoncondition/eoc_nether_attunement_events.json index 341bc743751a5..be278e0647ae9 100644 --- a/data/mods/MindOverMatter/effectoncondition/eoc_nether_attunement_events.json +++ b/data/mods/MindOverMatter/effectoncondition/eoc_nether_attunement_events.json @@ -4,36 +4,7 @@ "id": "EOC_NETHER_CONDUIT_VALUE_INCREASER", "eoc_type": "EVENT", "required_event": "spellcasting_finish", - "condition": { - "and": [ - { - "u_has_any_trait": [ - "BIOKINETIC", - "CLAIRSENTIENT", - "ELECTROKINETIC", - "PHOTOKINETIC", - "PYROKINETIC", - "TELEKINETIC", - "TELEPATH", - "TELEPORTER", - "VITAKINETIC" - ] - }, - { - "or": [ - { "compare_string": [ "BIOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "CLAIRSENTIENT", { "context_val": "school" } ] }, - { "compare_string": [ "ELECTROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PHOTOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PYROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPATH", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPORTER", { "context_val": "school" } ] }, - { "compare_string": [ "VITAKINETIC", { "context_val": "school" } ] } - ] - } - ] - }, + "condition": { "test_eoc": "EOC_CONDITION_SPELLCASTING_FINISH_TRAIT_AND_SCHOOL_LIST" }, "effect": [ { "run_eocs": [ @@ -51,42 +22,13 @@ "id": "EOC_PSIONICS_GAIN_NETHER_ATTUNEMENT", "eoc_type": "EVENT", "required_event": "spellcasting_finish", - "condition": { - "and": [ - { - "u_has_any_trait": [ - "BIOKINETIC", - "CLAIRSENTIENT", - "ELECTROKINETIC", - "PHOTOKINETIC", - "PYROKINETIC", - "TELEKINETIC", - "TELEPATH", - "TELEPORTER", - "VITAKINETIC" - ] - }, - { - "or": [ - { "compare_string": [ "BIOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "CLAIRSENTIENT", { "context_val": "school" } ] }, - { "compare_string": [ "ELECTROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PHOTOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PYROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPATH", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPORTER", { "context_val": "school" } ] }, - { "compare_string": [ "VITAKINETIC", { "context_val": "school" } ] } - ] - } - ] - }, + "condition": { "test_eoc": "EOC_CONDITION_SPELLCASTING_FINISH_TRAIT_AND_SCHOOL_LIST" }, "effect": [ { "math": [ "u_latest_channeled_power_difficulty", "=", "_difficulty" ] }, { "run_eocs": [ { - "id": "EOC_PSIONICS_GAIN_NETHER_ATTUNEMENT_2", + "id": "EOC_PSIONICS_GAIN_NETHER_ATTUNEMENT_SCALING_CHECK", "condition": { "math": [ "u_vitamin('vitamin_psionic_drain')", "<", "15" ] }, "effect": [ { @@ -175,6 +117,94 @@ } ] }, + { + "type": "effect_on_condition", + "id": "EOC_PSIONICS_GAIN_NETHER_ATTUNEMENT_2", + "//": "This is the EoC called by concentration checks. Name is to avoid JSON churn", + "condition": { "math": [ "u_vitamin('vitamin_psionic_drain')", "<", "15" ] }, + "effect": [ + { + "run_eocs": [ + { + "id": "EOC_RAISE_ATTUNEMENT_BELOW_THRESHOLD_CHECKER_MAINTENANCE", + "condition": { + "x_in_y_chance": { + "x": { + "math": [ + "(u_latest_channeled_power_difficulty * u_latest_channeled_power_difficulty) + (u_nether_conduit_repeated_channeling_value / 3) + (u_vitamin('vitamin_maintained_powers') * 3)" + ] + }, + "y": 100 + } + }, + "effect": [ { "run_eocs": "EOC_RAISE_ATTUNEMENT_BELOW_THRESHOLD_MAINTENANCE" } ] + } + ] + } + ], + "false_effect": [ + { + "run_eocs": [ + { + "id": "EOC_RAISE_ATTUNEMENT_ABOVE_THRESHOLD_CHECKER_MAINTENANCE", + "condition": { + "x_in_y_chance": { + "x": { + "math": [ + "(u_latest_channeled_power_difficulty * u_latest_channeled_power_difficulty) + u_nether_conduit_repeated_channeling_value + (u_vitamin('vitamin_maintained_powers') * 3)" + ] + }, + "y": 100 + } + }, + "effect": [ { "run_eocs": "EOC_RAISE_ATTUNEMENT_ABOVE_THRESHOLD_MAINTENANCE" } ] + } + ] + } + ] + }, + { + "type": "effect_on_condition", + "id": "EOC_RAISE_ATTUNEMENT_BELOW_THRESHOLD_MAINTENANCE", + "condition": { "u_has_effect": "effect_noetic_resilience" }, + "effect": [ + { "u_message": "As you concentrate on your powers, you feel a strange tingling sensation.", "type": "mixed" }, + { + "math": [ "u_vitamin('vitamin_psionic_drain')", "+=", "rand(1) + (rand(u_vitamin('vitamin_maintained_powers')) / 2)" ] + } + ], + "false_effect": [ + { "u_message": "As you concentrate on your powers, you feel a strange tingling sensation.", "type": "mixed" }, + { + "math": [ "u_vitamin('vitamin_psionic_drain')", "+=", "rand(3) + (rand(u_vitamin('vitamin_maintained_powers')) / 2)" ] + } + ] + }, + { + "type": "effect_on_condition", + "id": "EOC_RAISE_ATTUNEMENT_ABOVE_THRESHOLD_MAINTENANCE", + "condition": { "u_has_effect": "effect_noetic_resilience" }, + "effect": [ + { "u_message": "As you concentrate on your powers, you feel a strange tingling sensation.", "type": "mixed" }, + { + "math": [ + "u_vitamin('vitamin_psionic_drain')", + "+=", + "rand((u_latest_channeled_power_difficulty) / 2) + rand(u_vitamin('vitamin_maintained_powers'))" + ] + } + ], + "false_effect": [ + { "u_message": "As you concentrate on your powers, you feel a strange tingling sensation.", "type": "mixed" }, + { + "math": [ + "u_vitamin('vitamin_psionic_drain')", + "+=", + "(rand(u_latest_channeled_power_difficulty) * u_nether_attunement_power_scaling) + rand(u_vitamin('vitamin_maintained_powers'))" + ] + } + ] + }, { "type": "effect_on_condition", "id": "EOC_NETHER_CONDUIT_VALUE_DECREASER", @@ -217,32 +247,7 @@ "required_event": "spellcasting_finish", "condition": { "and": [ - { - "u_has_any_trait": [ - "BIOKINETIC", - "CLAIRSENTIENT", - "ELECTROKINETIC", - "PHOTOKINETIC", - "PYROKINETIC", - "TELEKINETIC", - "TELEPATH", - "TELEPORTER", - "VITAKINETIC" - ] - }, - { - "or": [ - { "compare_string": [ "BIOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "CLAIRSENTIENT", { "context_val": "school" } ] }, - { "compare_string": [ "ELECTROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PHOTOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PYROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPATH", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPORTER", { "context_val": "school" } ] }, - { "compare_string": [ "VITAKINETIC", { "context_val": "school" } ] } - ] - }, + { "test_eoc": "EOC_CONDITION_SPELLCASTING_FINISH_TRAIT_AND_SCHOOL_LIST" }, { "math": [ "u_vitamin('vitamin_psionic_drain')", ">=", "15" ] } ] }, @@ -1067,32 +1072,7 @@ "required_event": "spellcasting_finish", "condition": { "and": [ - { - "u_has_any_trait": [ - "BIOKINETIC", - "CLAIRSENTIENT", - "ELECTROKINETIC", - "PHOTOKINETIC", - "PYROKINETIC", - "TELEKINETIC", - "TELEPATH", - "TELEPORTER", - "VITAKINETIC" - ] - }, - { - "or": [ - { "compare_string": [ "BIOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "CLAIRSENTIENT", { "context_val": "school" } ] }, - { "compare_string": [ "ELECTROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PHOTOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PYROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPATH", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPORTER", { "context_val": "school" } ] }, - { "compare_string": [ "VITAKINETIC", { "context_val": "school" } ] } - ] - }, + { "test_eoc": "EOC_CONDITION_SPELLCASTING_FINISH_TRAIT_AND_SCHOOL_LIST" }, { "u_has_effect": "effect_nether_attunement_feedback" }, { "x_in_y_chance": { "x": { "math": [ "u_vitamin('vitamin_psionic_drain')" ] }, "y": 250 } } ] @@ -1144,101 +1124,11 @@ "required_event": "spellcasting_finish", "condition": { "and": [ - { - "u_has_any_trait": [ - "BIOKINETIC", - "CLAIRSENTIENT", - "ELECTROKINETIC", - "PHOTOKINETIC", - "PYROKINETIC", - "TELEKINETIC", - "TELEPATH", - "TELEPORTER", - "VITAKINETIC" - ] - }, - { - "or": [ - { "compare_string": [ "BIOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "CLAIRSENTIENT", { "context_val": "school" } ] }, - { "compare_string": [ "ELECTROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PHOTOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PYROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPATH", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPORTER", { "context_val": "school" } ] }, - { "compare_string": [ "VITAKINETIC", { "context_val": "school" } ] } - ] - }, + { "test_eoc": "EOC_CONDITION_SPELLCASTING_FINISH_TRAIT_AND_SCHOOL_LIST" }, { "or": [ - { "is_weather": "distant_portal_storm" }, - { "is_weather": "portal_storm" }, - { "is_weather": "close_portal_storm" }, - { "u_near_om_location": "unvitrified_farm_0", "range": 2 }, - { "u_near_om_location": "unvitrified_farm_1", "range": 2 }, - { "u_near_om_location": "unvitrified_farm_neg_1", "range": 2 }, - { "u_near_om_location": "unvitrified_farm_2", "range": 2 }, - { "u_near_om_location": "vitrified_farm_0", "range": 2 }, - { "u_near_om_location": "vitrified_farm_1", "range": 2 }, - { "u_near_om_location": "vitrified_farm_neg_1", "range": 2 }, - { "u_near_om_location": "vitrified_farm_2", "range": 2 }, - { "u_near_om_location": "microlab_portal_elevator_physics_glass", "range": 2 }, - { "u_near_om_location": "microlab_distorted_hallway", "range": 2 }, - { "u_near_om_location": "microlab_distorted", "range": 2 }, - { "u_near_om_location": "microlab_distorted_edge", "range": 2 }, - { "u_near_om_location": "microlab_portal_elevator_physics_glass", "range": 2 }, - { "u_near_om_location": "corpse_surface", "range": 0 }, - { "u_near_om_location": "corpse_bowels_neck_right", "range": 2 }, - { "u_near_om_location": "corpse_bowels_neck_left", "range": 2 }, - { "u_near_om_location": "corpse_bowels_neck_edge_center", "range": 2 }, - { "u_near_om_location": "corpse_bowels_rcorner", "range": 2 }, - { "u_near_om_location": "corpse_bowels_lcorner", "range": 2 }, - { "u_near_om_location": "corpse_bowels_empty_edge", "range": 2 }, - { "u_near_om_location": "corpse_bowels_mid", "range": 2 }, - { "u_near_om_location": "corpse_tentacle", "range": 2 }, - { "u_near_om_location": "corpse_tentacle_entry", "range": 2 }, - { "u_near_om_location": "corpse_tentacle_surface_entry", "range": 0 }, - { "u_near_om_location": "corpse_bowels_tentacle_edge", "range": 2 }, - { "u_near_om_location": "corpse_bowels_empty_edge", "range": 2 }, - { "u_near_om_location": "corpse_head", "range": 2 }, - { "u_near_om_location": "corpse_brain", "range": 2 }, - { "u_near_om_location": "corpse_under_brain", "range": 2 }, - { "u_near_om_location": "corpse_head_edge", "range": 2 }, - { "u_near_om_location": "corpse_head_fin", "range": 2 }, - { "u_near_om_location": "corpse_head_lcorner", "range": 2 }, - { "u_near_om_location": "corpse_head_rcorner", "range": 2 }, - { "u_near_om_location": "corpse_head_neck_l", "range": 2 }, - { "u_near_om_location": "corpse_head_neck_r", "range": 2 }, - { "u_near_om_location": "corpse_head_neck_center", "range": 2 }, - { "u_near_om_location": "corpse_head_neck_l_decap", "range": 2 }, - { "u_near_om_location": "corpse_head_neck_r", "range": 2 }, - { "u_near_om_location": "corpse_head_neck_r_decap", "range": 2 }, - { "u_near_om_location": "corpse_head_neck_center_decap", "range": 2 }, - { "u_near_om_location": "nether_crystal_field", "range": 1 }, - { "u_near_om_location": "psi_phavian_lab_blockB1", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_blockD1", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_blockB3", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_blockD3", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block2B1", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block2D1", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block2B3", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block2D3", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block3B1", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block3D1", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block3B3", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block3D3", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block4B1", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block4D1", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block4B3", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block4D3", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block5B1", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block5D1", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block5B3", "range": 2 }, - { "u_near_om_location": "psi_phavian_lab_block5D3", "range": 2 }, - { "u_near_om_location": "void_spider_lair_entrance", "range": 2 }, - { "u_near_om_location": "void_spider_lair_a1", "range": 2 }, - { "u_near_om_location": "void_spider_lair_a2", "range": 2 } + { "test_eoc": "EOC_CONDITION_CAUGHT_IN_NETHER_WEATHER" }, + { "test_eoc": "EOC_CONDITION_NEAR_NETHER_RELATED_LOCATION" } ] } ] diff --git a/data/mods/MindOverMatter/effectoncondition/eoc_on_power_use_events.json b/data/mods/MindOverMatter/effectoncondition/eoc_on_power_use_events.json index 0d62a98a3df9a..a10765731ce87 100644 --- a/data/mods/MindOverMatter/effectoncondition/eoc_on_power_use_events.json +++ b/data/mods/MindOverMatter/effectoncondition/eoc_on_power_use_events.json @@ -29,41 +29,7 @@ "id": "EOC_MELEE_MONSTER_CANCEL_TOGGLES", "eoc_type": "EVENT", "required_event": "character_melee_attacks_monster", - "condition": { - "or": [ - { "u_has_trait": "CLAIR_SPEED_READ" }, - { "u_has_effect": "effect_clair_speed_reader" }, - { "u_has_effect": "effect_clair_see_auras" }, - { "u_has_effect": "effect_clair_craft_bonus" }, - { "u_has_effect": "effect_photokin_light_local" }, - { "u_has_item": "pyrokinetic_fire_tool" }, - { "u_has_item": "pyrokinetic_torch_weld" }, - { "u_has_effect": "effect_telekinetic_strength" }, - { "u_has_item": "telekin_lifting_jack_1" }, - { "u_has_item": "telekin_lifting_jack_2" }, - { "u_has_item": "telekin_lifting_jack_3" }, - { "u_has_item": "telekin_lifting_jack_4" }, - { "u_has_item": "telekin_lifting_jack_5" }, - { "u_has_item": "telekin_lifting_jack_6" }, - { "u_has_item": "telekin_lifting_jack_7" }, - { "u_has_item": "telekin_lifting_jack_8" }, - { "u_has_item": "telekin_lifting_jack_9" }, - { "u_has_item": "telekin_lifting_jack_10" }, - { "u_has_item": "telekin_lifting_jack_11" }, - { "u_has_item": "telekin_lifting_jack_12" }, - { "u_has_item": "telekin_lifting_jack_13" }, - { "u_has_item": "telekin_lifting_jack_14" }, - { "u_has_item": "telekin_lifting_jack_15" }, - { "u_has_item": "telekin_lifting_jack_16" }, - { "u_has_item": "telekin_lifting_jack_17" }, - { "u_has_item": "telekin_lifting_jack_18" }, - { "u_has_item": "telekin_lifting_jack_19" }, - { "u_has_item": "telekin_lifting_jack_20" }, - { "u_has_effect": "effect_telekinetic_levitation" }, - { "u_has_effect": "effect_telepathic_learning_bonus" }, - { "u_has_effect": "telepathic_ignorance_self" } - ] - }, + "condition": { "test_eoc": "EOC_CONDITION_LIST_OF_POWERS_CANCELLED_BY_COMBAT" }, "effect": [ { "run_eocs": [ "EOC_POWER_TOGGLE_REMOVE_EFFECTS" ] }, { "npc_lose_effect": "telepathic_ignorance" } ] }, { @@ -71,41 +37,7 @@ "id": "EOC_MELEE_CHARACTER_CANCEL_TOGGLES", "eoc_type": "EVENT", "required_event": "character_melee_attacks_character", - "condition": { - "or": [ - { "u_has_trait": "CLAIR_SPEED_READ" }, - { "u_has_effect": "effect_clair_speed_reader" }, - { "u_has_effect": "effect_clair_see_auras" }, - { "u_has_effect": "effect_clair_craft_bonus" }, - { "u_has_effect": "effect_photokin_light_local" }, - { "u_has_item": "pyrokinetic_fire_tool" }, - { "u_has_item": "pyrokinetic_torch_weld" }, - { "u_has_effect": "effect_telekinetic_strength" }, - { "u_has_item": "telekin_lifting_jack_1" }, - { "u_has_item": "telekin_lifting_jack_2" }, - { "u_has_item": "telekin_lifting_jack_3" }, - { "u_has_item": "telekin_lifting_jack_4" }, - { "u_has_item": "telekin_lifting_jack_5" }, - { "u_has_item": "telekin_lifting_jack_6" }, - { "u_has_item": "telekin_lifting_jack_7" }, - { "u_has_item": "telekin_lifting_jack_8" }, - { "u_has_item": "telekin_lifting_jack_9" }, - { "u_has_item": "telekin_lifting_jack_10" }, - { "u_has_item": "telekin_lifting_jack_11" }, - { "u_has_item": "telekin_lifting_jack_12" }, - { "u_has_item": "telekin_lifting_jack_13" }, - { "u_has_item": "telekin_lifting_jack_14" }, - { "u_has_item": "telekin_lifting_jack_15" }, - { "u_has_item": "telekin_lifting_jack_16" }, - { "u_has_item": "telekin_lifting_jack_17" }, - { "u_has_item": "telekin_lifting_jack_18" }, - { "u_has_item": "telekin_lifting_jack_19" }, - { "u_has_item": "telekin_lifting_jack_20" }, - { "u_has_effect": "effect_telekinetic_levitation" }, - { "u_has_effect": "effect_telepathic_learning_bonus" }, - { "u_has_effect": "telepathic_ignorance_self" } - ] - }, + "condition": { "test_eoc": "EOC_CONDITION_LIST_OF_POWERS_CANCELLED_BY_COMBAT" }, "effect": [ { "run_eocs": [ "EOC_POWER_TOGGLE_REMOVE_EFFECTS" ] }, { "npc_lose_effect": "telepathic_ignorance" } ] }, { @@ -113,42 +45,7 @@ "id": "EOC_RANGED_MONSTER_CANCEL_TOGGLES", "eoc_type": "EVENT", "required_event": "character_ranged_attacks_monster", - "condition": { - "or": [ - { "u_has_trait": "CLAIR_SPEED_READ" }, - { "u_has_effect": "effect_clair_speed_reader" }, - { "u_has_effect": "effect_clair_see_auras" }, - { "u_has_effect": "effect_clair_craft_bonus" }, - { "u_has_effect": "effect_clair_perfect_shot" }, - { "u_has_effect": "effect_photokin_light_local" }, - { "u_has_item": "pyrokinetic_fire_tool" }, - { "u_has_item": "pyrokinetic_torch_weld" }, - { "u_has_effect": "effect_telekinetic_strength" }, - { "u_has_item": "telekin_lifting_jack_1" }, - { "u_has_item": "telekin_lifting_jack_2" }, - { "u_has_item": "telekin_lifting_jack_3" }, - { "u_has_item": "telekin_lifting_jack_4" }, - { "u_has_item": "telekin_lifting_jack_5" }, - { "u_has_item": "telekin_lifting_jack_6" }, - { "u_has_item": "telekin_lifting_jack_7" }, - { "u_has_item": "telekin_lifting_jack_8" }, - { "u_has_item": "telekin_lifting_jack_9" }, - { "u_has_item": "telekin_lifting_jack_10" }, - { "u_has_item": "telekin_lifting_jack_11" }, - { "u_has_item": "telekin_lifting_jack_12" }, - { "u_has_item": "telekin_lifting_jack_13" }, - { "u_has_item": "telekin_lifting_jack_14" }, - { "u_has_item": "telekin_lifting_jack_15" }, - { "u_has_item": "telekin_lifting_jack_16" }, - { "u_has_item": "telekin_lifting_jack_17" }, - { "u_has_item": "telekin_lifting_jack_18" }, - { "u_has_item": "telekin_lifting_jack_19" }, - { "u_has_item": "telekin_lifting_jack_20" }, - { "u_has_effect": "effect_telekinetic_levitation" }, - { "u_has_effect": "effect_telepathic_learning_bonus" }, - { "u_has_effect": "telepathic_ignorance_self" } - ] - }, + "condition": { "test_eoc": "EOC_CONDITION_LIST_OF_POWERS_CANCELLED_BY_COMBAT" }, "effect": [ { "run_eocs": [ "EOC_POWER_TOGGLE_REMOVE_EFFECTS" ] }, { "npc_lose_effect": "telepathic_ignorance" } ] }, { @@ -156,42 +53,7 @@ "id": "EOC_RANGED_CHARACTER_CANCEL_TOGGLES", "eoc_type": "EVENT", "required_event": "character_ranged_attacks_character", - "condition": { - "or": [ - { "u_has_trait": "CLAIR_SPEED_READ" }, - { "u_has_effect": "effect_clair_speed_reader" }, - { "u_has_effect": "effect_clair_see_auras" }, - { "u_has_effect": "effect_clair_craft_bonus" }, - { "u_has_effect": "effect_clair_perfect_shot" }, - { "u_has_effect": "effect_photokin_light_local" }, - { "u_has_item": "pyrokinetic_fire_tool" }, - { "u_has_item": "pyrokinetic_torch_weld" }, - { "u_has_effect": "effect_telekinetic_strength" }, - { "u_has_item": "telekin_lifting_jack_1" }, - { "u_has_item": "telekin_lifting_jack_2" }, - { "u_has_item": "telekin_lifting_jack_3" }, - { "u_has_item": "telekin_lifting_jack_4" }, - { "u_has_item": "telekin_lifting_jack_5" }, - { "u_has_item": "telekin_lifting_jack_6" }, - { "u_has_item": "telekin_lifting_jack_7" }, - { "u_has_item": "telekin_lifting_jack_8" }, - { "u_has_item": "telekin_lifting_jack_9" }, - { "u_has_item": "telekin_lifting_jack_10" }, - { "u_has_item": "telekin_lifting_jack_11" }, - { "u_has_item": "telekin_lifting_jack_12" }, - { "u_has_item": "telekin_lifting_jack_13" }, - { "u_has_item": "telekin_lifting_jack_14" }, - { "u_has_item": "telekin_lifting_jack_15" }, - { "u_has_item": "telekin_lifting_jack_16" }, - { "u_has_item": "telekin_lifting_jack_17" }, - { "u_has_item": "telekin_lifting_jack_18" }, - { "u_has_item": "telekin_lifting_jack_19" }, - { "u_has_item": "telekin_lifting_jack_20" }, - { "u_has_effect": "effect_telekinetic_levitation" }, - { "u_has_effect": "effect_telepathic_learning_bonus" }, - { "u_has_effect": "telepathic_ignorance_self" } - ] - }, + "condition": { "test_eoc": "EOC_CONDITION_LIST_OF_POWERS_CANCELLED_BY_COMBAT" }, "effect": [ { "run_eocs": [ "EOC_POWER_TOGGLE_REMOVE_EFFECTS" ] }, { "npc_lose_effect": "telepathic_ignorance" } ] }, { @@ -201,73 +63,9 @@ "required_event": "spellcasting_finish", "condition": { "and": [ - { - "or": [ - { "u_has_trait": "CLAIR_SPEED_READ" }, - { "u_has_effect": "effect_clair_speed_reader" }, - { "u_has_effect": "effect_clair_see_auras" }, - { "u_has_effect": "effect_clair_craft_bonus" }, - { "u_has_effect": "effect_clair_perfect_shot" }, - { "u_has_effect": "effect_photokin_light_local" }, - { "u_has_item": "pyrokinetic_fire_tool" }, - { "u_has_item": "pyrokinetic_torch_weld" }, - { "u_has_effect": "effect_telekinetic_strength" }, - { "u_has_item": "telekin_lifting_jack_1" }, - { "u_has_item": "telekin_lifting_jack_2" }, - { "u_has_item": "telekin_lifting_jack_3" }, - { "u_has_item": "telekin_lifting_jack_4" }, - { "u_has_item": "telekin_lifting_jack_5" }, - { "u_has_item": "telekin_lifting_jack_6" }, - { "u_has_item": "telekin_lifting_jack_7" }, - { "u_has_item": "telekin_lifting_jack_8" }, - { "u_has_item": "telekin_lifting_jack_9" }, - { "u_has_item": "telekin_lifting_jack_10" }, - { "u_has_item": "telekin_lifting_jack_11" }, - { "u_has_item": "telekin_lifting_jack_12" }, - { "u_has_item": "telekin_lifting_jack_13" }, - { "u_has_item": "telekin_lifting_jack_14" }, - { "u_has_item": "telekin_lifting_jack_15" }, - { "u_has_item": "telekin_lifting_jack_16" }, - { "u_has_item": "telekin_lifting_jack_17" }, - { "u_has_item": "telekin_lifting_jack_18" }, - { "u_has_item": "telekin_lifting_jack_19" }, - { "u_has_item": "telekin_lifting_jack_20" }, - { "u_has_effect": "effect_telekinetic_levitation" }, - { "u_has_effect": "effect_telepathic_learning_bonus" }, - { "u_has_effect": "telepathic_ignorance_self" } - ] - }, { "math": [ "_damage", ">=", "1" ] }, - { - "and": [ - { - "u_has_any_trait": [ - "BIOKINETIC", - "CLAIRSENTIENT", - "ELECTROKINETIC", - "PHOTOKINETIC", - "PYROKINETIC", - "TELEKINETIC", - "TELEPATH", - "TELEPORTER", - "VITAKINETIC" - ] - }, - { - "or": [ - { "compare_string": [ "BIOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "CLAIRSENTIENT", { "context_val": "school" } ] }, - { "compare_string": [ "ELECTROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PHOTOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PYROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPATH", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPORTER", { "context_val": "school" } ] }, - { "compare_string": [ "VITAKINETIC", { "context_val": "school" } ] } - ] - } - ] - } + { "test_eoc": "EOC_CONDITION_LIST_OF_POWERS_CANCELLED_BY_COMBAT" }, + { "test_eoc": "EOC_CONDITION_SPELLCASTING_FINISH_TRAIT_AND_SCHOOL_LIST" } ] }, "effect": [ { "run_eocs": [ "EOC_POWER_TOGGLE_REMOVE_EFFECTS" ] } ] @@ -348,9 +146,7 @@ "or": [ { "math": [ "u_vitamin('vitamin_psionic_drain')", ">=", "200" ] }, { "math": [ "_success", "==", "false" ] }, - { "is_weather": "distant_portal_storm" }, - { "is_weather": "portal_storm" }, - { "is_weather": "close_portal_storm" } + { "test_eoc": "EOC_CONDITION_CAUGHT_IN_NETHER_WEATHER" } ] }, { @@ -389,9 +185,7 @@ "or": [ { "math": [ "u_vitamin('vitamin_psionic_drain')", ">=", "200" ] }, { "math": [ "_success", "==", "false" ] }, - { "is_weather": "distant_portal_storm" }, - { "is_weather": "portal_storm" }, - { "is_weather": "close_portal_storm" } + { "test_eoc": "EOC_CONDITION_CAUGHT_IN_NETHER_WEATHER" } ] }, { @@ -434,9 +228,7 @@ "or": [ { "math": [ "u_vitamin('vitamin_psionic_drain')", ">=", "200" ] }, { "math": [ "_success", "==", "false" ] }, - { "is_weather": "distant_portal_storm" }, - { "is_weather": "portal_storm" }, - { "is_weather": "close_portal_storm" } + { "test_eoc": "EOC_CONDITION_CAUGHT_IN_NETHER_WEATHER" } ] }, { @@ -476,9 +268,7 @@ "or": [ { "math": [ "u_vitamin('vitamin_psionic_drain')", ">=", "200" ] }, { "math": [ "_success", "==", "false" ] }, - { "is_weather": "distant_portal_storm" }, - { "is_weather": "portal_storm" }, - { "is_weather": "close_portal_storm" } + { "test_eoc": "EOC_CONDITION_CAUGHT_IN_NETHER_WEATHER" } ] }, { @@ -521,9 +311,7 @@ "or": [ { "math": [ "u_vitamin('vitamin_psionic_drain')", ">=", "200" ] }, { "math": [ "_success", "==", "false" ] }, - { "is_weather": "distant_portal_storm" }, - { "is_weather": "portal_storm" }, - { "is_weather": "close_portal_storm" } + { "test_eoc": "EOC_CONDITION_CAUGHT_IN_NETHER_WEATHER" } ] }, { @@ -562,9 +350,7 @@ "or": [ { "math": [ "u_vitamin('vitamin_psionic_drain')", ">=", "200" ] }, { "math": [ "_success", "==", "false" ] }, - { "is_weather": "distant_portal_storm" }, - { "is_weather": "portal_storm" }, - { "is_weather": "close_portal_storm" } + { "test_eoc": "EOC_CONDITION_CAUGHT_IN_NETHER_WEATHER" } ] }, { @@ -603,9 +389,7 @@ "or": [ { "math": [ "u_vitamin('vitamin_psionic_drain')", ">=", "200" ] }, { "math": [ "_success", "==", "false" ] }, - { "is_weather": "distant_portal_storm" }, - { "is_weather": "portal_storm" }, - { "is_weather": "close_portal_storm" } + { "test_eoc": "EOC_CONDITION_CAUGHT_IN_NETHER_WEATHER" } ] }, { @@ -648,9 +432,7 @@ "or": [ { "math": [ "u_vitamin('vitamin_psionic_drain')", ">=", "200" ] }, { "math": [ "_success", "==", "false" ] }, - { "is_weather": "distant_portal_storm" }, - { "is_weather": "portal_storm" }, - { "is_weather": "close_portal_storm" } + { "test_eoc": "EOC_CONDITION_CAUGHT_IN_NETHER_WEATHER" } ] }, { @@ -686,7 +468,11 @@ { "u_has_trait": "VITAKINETIC" }, { "compare_string": [ "VITAKINETIC", { "context_val": "school" } ] }, { - "or": [ { "math": [ "u_vitamin('vitamin_psionic_drain')", ">=", "200" ] }, { "math": [ "_success", "==", "false" ] } ] + "or": [ + { "math": [ "u_vitamin('vitamin_psionic_drain')", ">=", "200" ] }, + { "math": [ "_success", "==", "false" ] }, + { "test_eoc": "EOC_CONDITION_CAUGHT_IN_NETHER_WEATHER" } + ] }, { "x_in_y_chance": { @@ -728,36 +514,7 @@ "id": "EOC_PSIONICS_KCAL_COST", "eoc_type": "EVENT", "required_event": "spellcasting_finish", - "condition": { - "and": [ - { - "u_has_any_trait": [ - "BIOKINETIC", - "CLAIRSENTIENT", - "ELECTROKINETIC", - "PHOTOKINETIC", - "PYROKINETIC", - "TELEKINETIC", - "TELEPATH", - "TELEPORTER", - "VITAKINETIC" - ] - }, - { - "or": [ - { "compare_string": [ "BIOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "CLAIRSENTIENT", { "context_val": "school" } ] }, - { "compare_string": [ "ELECTROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PHOTOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PYROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPATH", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPORTER", { "context_val": "school" } ] }, - { "compare_string": [ "VITAKINETIC", { "context_val": "school" } ] } - ] - } - ] - }, + "condition": { "test_eoc": "EOC_CONDITION_SPELLCASTING_FINISH_TRAIT_AND_SCHOOL_LIST" }, "effect": [ { "math": [ "u_val('stored_kcal')", "-=", "psionics_kcal_cost(_difficulty)" ] } ] }, { @@ -905,32 +662,7 @@ "required_event": "spellcasting_finish", "condition": { "and": [ - { - "u_has_any_trait": [ - "BIOKINETIC", - "CLAIRSENTIENT", - "ELECTROKINETIC", - "PHOTOKINETIC", - "PYROKINETIC", - "TELEKINETIC", - "TELEPATH", - "TELEPORTER", - "VITAKINETIC" - ] - }, - { - "or": [ - { "compare_string": [ "BIOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "CLAIRSENTIENT", { "context_val": "school" } ] }, - { "compare_string": [ "ELECTROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PHOTOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PYROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPATH", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPORTER", { "context_val": "school" } ] }, - { "compare_string": [ "VITAKINETIC", { "context_val": "school" } ] } - ] - }, + { "test_eoc": "EOC_CONDITION_SPELLCASTING_FINISH_TRAIT_AND_SCHOOL_LIST" }, { "math": [ "u_vitamin('vitamin_maintained_powers')", ">=", "( u_val('intelligence') / 4) + (u_bonus_concentration_powers)" ] } @@ -945,32 +677,7 @@ "required_event": "spellcasting_finish", "condition": { "and": [ - { - "u_has_any_trait": [ - "BIOKINETIC", - "CLAIRSENTIENT", - "ELECTROKINETIC", - "PHOTOKINETIC", - "PYROKINETIC", - "TELEKINETIC", - "TELEPATH", - "TELEPORTER", - "VITAKINETIC" - ] - }, - { - "or": [ - { "compare_string": [ "BIOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "CLAIRSENTIENT", { "context_val": "school" } ] }, - { "compare_string": [ "ELECTROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PHOTOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PYROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPATH", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPORTER", { "context_val": "school" } ] }, - { "compare_string": [ "VITAKINETIC", { "context_val": "school" } ] } - ] - }, + { "test_eoc": "EOC_CONDITION_SPELLCASTING_FINISH_TRAIT_AND_SCHOOL_LIST" }, { "math": [ "u_val('focus')", ">=", "15" ] } ] }, diff --git a/data/mods/MindOverMatter/effectoncondition/eoc_power_effects.json b/data/mods/MindOverMatter/effectoncondition/eoc_power_effects.json index 8ba59b53f691e..a99c924f393b8 100644 --- a/data/mods/MindOverMatter/effectoncondition/eoc_power_effects.json +++ b/data/mods/MindOverMatter/effectoncondition/eoc_power_effects.json @@ -115,44 +115,6 @@ { "math": [ "u_spellcasting_adjustment('concentration', 'flag_whitelist': 'PSIONIC' )", "=", "-1" ] } ] }, - { - "type": "effect_on_condition", - "id": "EOC_PSI_EXTENDED_CHANNELING_ATTUNEMENT", - "eoc_type": "EVENT", - "required_event": "spellcasting_finish", - "condition": { - "and": [ - { - "u_has_any_trait": [ - "BIOKINETIC", - "CLAIRSENTIENT", - "ELECTROKINETIC", - "PHOTOKINETIC", - "PYROKINETIC", - "TELEKINETIC", - "TELEPATH", - "TELEPORTER", - "VITAKINETIC" - ] - }, - { - "or": [ - { "compare_string": [ "BIOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "CLAIRSENTIENT", { "context_val": "school" } ] }, - { "compare_string": [ "ELECTROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PHOTOKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "PYROKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEKINETIC", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPATH", { "context_val": "school" } ] }, - { "compare_string": [ "TELEPORTER", { "context_val": "school" } ] }, - { "compare_string": [ "VITAKINETIC", { "context_val": "school" } ] } - ] - }, - { "u_has_trait": "PSI_EXTENDED_CHANNELING_ON" } - ] - }, - "effect": [ { "u_cast_spell": { "id": "psionic_drained_difficulty_five", "hit_self": true } } ] - }, { "type": "effect_on_condition", "id": "EOC_NETHER_ATTUNEMENT_BOOST", diff --git a/data/mods/MindOverMatter/effects/effects_items.json b/data/mods/MindOverMatter/effects/effects_items.json index d73acad128879..2c718384bd4b7 100644 --- a/data/mods/MindOverMatter/effects/effects_items.json +++ b/data/mods/MindOverMatter/effects/effects_items.json @@ -39,5 +39,13 @@ "desc": [ "" ], "removes_effects": [ "psi_blind", "psi_deaf", "effect_telepathic_primal_terror", "psi_dazed" ], "flags": [ "PSYSHIELD_PROTECT" ] + }, + { + "id": "effect_shield_belt_telekin_protection", + "type": "effect_type", + "//": "Blank to hide effect", + "name": [ "" ], + "desc": [ "" ], + "flags": [ "TELEKIN_SHIELD" ] } ] diff --git a/data/mods/MindOverMatter/itemgroups/recipes.json b/data/mods/MindOverMatter/itemgroups/recipes.json index f51cd192bf2ec..214f8d19ef6d4 100644 --- a/data/mods/MindOverMatter/itemgroups/recipes.json +++ b/data/mods/MindOverMatter/itemgroups/recipes.json @@ -5,6 +5,7 @@ "id": "psionic_recipes_beginner", "items": [ [ "schematics_matrix_crystal_ground", 3 ], + [ "manual_psionic_ritual", 2 ], [ "schematics_reactant_liquid_base", 3 ], [ "schematics_matrix_channeling", 2 ], [ "schematics_matrix_aligning", 1 ] diff --git a/data/mods/MindOverMatter/items/armor/belt.json b/data/mods/MindOverMatter/items/armor/belt.json index 394e82d181022..bc1d7aa432a1c 100644 --- a/data/mods/MindOverMatter/items/armor/belt.json +++ b/data/mods/MindOverMatter/items/armor/belt.json @@ -36,7 +36,22 @@ "volume_encumber_modifier": 0.35 } ], - "relic_data": { "charge_info": { "recharge_type": "periodic", "time": "60 s", "regenerate_ammo": true } }, + "relic_data": { + "passive_effects": [ + { + "has": "WORN", + "condition": "ACTIVE", + "ench_effects": [ { "effect": "effect_shield_belt_telekin_protection", "intensity": 1 } ], + "values": [ + { "value": "ARMOR_CUT", "add": -15 }, + { "value": "ARMOR_BASH", "add": -8 }, + { "value": "ARMOR_STAB", "add": -20 }, + { "value": "ARMOR_BULLET", "add": -40 } + ] + } + ], + "charge_info": { "recharge_type": "periodic", "time": "60 s", "regenerate_ammo": true } + }, "//": "Recharge time is 60 seconds due to bug #48019, making it actually 30 seconds. Reduce to 30 seconds if that ever gets fixed." }, { @@ -60,7 +75,8 @@ "passive_effects": [ { "has": "WORN", - "condition": "ALWAYS", + "condition": "ACTIVE", + "ench_effects": [ { "effect": "effect_shield_belt_telekin_protection", "intensity": 1 } ], "values": [ { "value": "ARMOR_CUT", "add": -15 }, { "value": "ARMOR_BASH", "add": -8 }, diff --git a/data/mods/MindOverMatter/items/books.json b/data/mods/MindOverMatter/items/books.json index 84849ef3ad633..bdd24d889a84d 100644 --- a/data/mods/MindOverMatter/items/books.json +++ b/data/mods/MindOverMatter/items/books.json @@ -127,6 +127,23 @@ "time": "35 m", "fun": -2 }, + { + "id": "manual_psionic_ritual", + "type": "BOOK", + "category": "manuals", + "name": { + "str": "Training Manual: Method of Loci and Dimensional Metaphysics", + "str_pl": "copies of Training Manual: Method of Loci and Dimensional Metaphysics" + }, + "description": "A formal report on a series of training procedures to allow the practitioner to hold images and ideas in their head for long periods of time without being distracted or losing their train of thought. The report concludes, \"While the human mind is not adept at holding static images or scenes in place, some minor variation can be allowed for without suffering any adverse effects from the flow of Netherum energy. Method of Loci allows the mathematician to maintain their thoughts within this area of variation while still exerting effective control over the mathematics.\"", + "copy-from": "recipe_lab_elec", + "skill": "metaphysics", + "required_level": 4, + "max_level": 4, + "intelligence": 12, + "time": "35 m", + "fun": -2 + }, { "id": "phavian_psionic_martial_power_book", "type": "BOOK", diff --git a/data/mods/MindOverMatter/monsters/feral_lab_psychics.json b/data/mods/MindOverMatter/monsters/feral_lab_psychics.json index 417e12879a937..e44d6d1e9dc7b 100644 --- a/data/mods/MindOverMatter/monsters/feral_lab_psychics.json +++ b/data/mods/MindOverMatter/monsters/feral_lab_psychics.json @@ -8,7 +8,7 @@ "default_faction": "science", "looks_like": "chud", "bodytype": "human", - "species": [ "FERAL" ], + "species": [ "FERAL", "TELEKIN_PUSHPULL_NULL" ], "volume": "62500 ml", "weight": "81500 g", "hp": 85, @@ -83,7 +83,7 @@ "uncanny_dodgeable": true, "blockable": false, "effects_require_dmg": false, - "condition": { "not": { "u_has_effect": "effect_psi_null" } }, + "condition": { "and": [ { "not": { "u_has_effect": "effect_psi_null" } }, { "not": { "npc_has_flag": "TELEKIN_SHIELD" } } ] }, "hit_dmg_u": "%1$s stares at you and a powerful force hurls you through the air!", "hit_dmg_npc": "%1$s stares at and a powerful force hurls them through the air!", "miss_msg_u": "%s stares at you, and you feel a crushing pressure for a moment before the feeling vanishes!", diff --git a/data/mods/MindOverMatter/monsters/feral_psychics.json b/data/mods/MindOverMatter/monsters/feral_psychics.json index b3de6b0538c3a..acd8b8813e6f1 100644 --- a/data/mods/MindOverMatter/monsters/feral_psychics.json +++ b/data/mods/MindOverMatter/monsters/feral_psychics.json @@ -1129,7 +1129,7 @@ "default_faction": "zombie", "looks_like": "chud", "bodytype": "human", - "species": [ "FERAL" ], + "species": [ "FERAL", "TELEKIN_PUSHPULL_NULL" ], "volume": "62500 ml", "weight": "81500 g", "hp": 84, @@ -1166,7 +1166,7 @@ "type": "spell", "spell_data": { "id": "telekinetic_pull_monster", "min_level": 2 }, "cooldown": 15, - "condition": { "not": { "u_has_effect": "effect_psi_null" } }, + "condition": { "and": [ { "not": { "u_has_effect": "effect_psi_null" } }, { "not": { "npc_has_flag": "TELEKIN_SHIELD" } } ] }, "monster_message": "%1$s stares at %3$s and %3$s is lifted up and pulled towards them!" }, { @@ -1195,7 +1195,7 @@ "uncanny_dodgeable": true, "blockable": false, "effects_require_dmg": false, - "condition": { "not": { "u_has_effect": "effect_psi_null" } }, + "condition": { "and": [ { "not": { "u_has_effect": "effect_psi_null" } }, { "not": { "npc_has_flag": "TELEKIN_SHIELD" } } ] }, "hit_dmg_u": "%1$s stares at you and a powerful force hurls you through the air!", "hit_dmg_npc": "%1$s stares at and a powerful force hurls them through the air!", "miss_msg_u": "%s stares at you, and you feel a crushing pressure for a moment before the feeling vanishes!", @@ -1227,7 +1227,7 @@ "default_faction": "zombie", "looks_like": "chud", "bodytype": "human", - "species": [ "FERAL" ], + "species": [ "FERAL", "TELEKIN_PUSHPULL_NULL" ], "volume": "62500 ml", "weight": "81500 g", "hp": 84, @@ -1263,7 +1263,7 @@ "type": "spell", "spell_data": { "id": "telekinetic_pull_monster", "min_level": 3 }, "cooldown": 10, - "condition": { "not": { "u_has_effect": "effect_psi_null" } }, + "condition": { "and": [ { "not": { "u_has_effect": "effect_psi_null" } }, { "not": { "npc_has_flag": "TELEKIN_SHIELD" } } ] }, "monster_message": "%1$s stares at %3$s and %3$s is lifted up and pulled towards them!" }, { @@ -1296,7 +1296,7 @@ "dodgeable": false, "uncanny_dodgeable": true, "blockable": false, - "condition": { "not": { "u_has_effect": "effect_psi_null" } }, + "condition": { "and": [ { "not": { "u_has_effect": "effect_psi_null" } }, { "not": { "npc_has_flag": "TELEKIN_SHIELD" } } ] }, "hit_dmg_u": "%1$s stares at you and a powerful force hurls you through the air!", "hit_dmg_npc": "%1$s stares at and a powerful force hurls them through the air!", "miss_msg_u": "%s stares at you, and you feel a crushing pressure for a moment before the feeling vanishes!", diff --git a/data/mods/MindOverMatter/monsters/species_new.json b/data/mods/MindOverMatter/monsters/species_new.json index c4242fe355b53..753e7c2786934 100644 --- a/data/mods/MindOverMatter/monsters/species_new.json +++ b/data/mods/MindOverMatter/monsters/species_new.json @@ -5,6 +5,12 @@ "description": "a being immune to psionics", "//": "This is an extra species to attach to any monster that is supposed to be immune to psionics--it will prevent them from being targeted by psionic powers. If the monster is supposed to be fully immune, they will still need appropriate monster flags or armor against psionic damage types to prevent them from being caught in the AoE of powers targeted elsewhere." }, + { + "type": "SPECIES", + "id": "TELEKIN_PUSHPULL_NULL", + "description": "a being immune to being thrown telekinetically", + "//": "This is an extra species to attach to any monster that is supposed to be immune to telekinetic push or pull. Immunity to telekinetic damage is handled by flags." + }, { "type": "SPECIES", "id": "YRAX_CONSTRUCT", diff --git a/data/mods/MindOverMatter/powers/telekinesis.json b/data/mods/MindOverMatter/powers/telekinesis.json index 83b9f4a086ece..68170fb5f3fe6 100644 --- a/data/mods/MindOverMatter/powers/telekinesis.json +++ b/data/mods/MindOverMatter/powers/telekinesis.json @@ -38,7 +38,7 @@ "base_casting_time": 50, "final_casting_time": 10, "casting_time_increment": -4, - "ignored_monster_species": [ "PSI_NULL" ] + "ignored_monster_species": [ "PSI_NULL", "TELEKIN_PUSHPULL_NULL" ] }, { "id": "telekinetic_push", @@ -79,7 +79,7 @@ "base_casting_time": 50, "final_casting_time": 10, "casting_time_increment": -4, - "ignored_monster_species": [ "PSI_NULL" ] + "ignored_monster_species": [ "PSI_NULL", "TELEKIN_PUSHPULL_NULL" ] }, { "id": "telekinetic_noise", @@ -91,7 +91,7 @@ "valid_targets": [ "ground" ], "spell_class": "TELEKINETIC", "skill": "metaphysics", - "flags": [ "PSIONIC", "CONCENTRATE", "RANDOM_DAMAGE", "NO_HANDS", "NO_LEGS", "NO_EXPLOSION_SFX" ], + "flags": [ "PSIONIC", "CONCENTRATE", "RANDOM_DAMAGE", "NO_PROJECTILE", "NO_HANDS", "NO_LEGS", "NO_EXPLOSION_SFX" ], "difficulty": 2, "max_level": { "math": [ "int_to_level(1)" ] }, "effect": "noise", @@ -172,7 +172,7 @@ "base_casting_time": 75, "final_casting_time": 30, "casting_time_increment": -3, - "ignored_monster_species": [ "PSI_NULL" ] + "ignored_monster_species": [ "PSI_NULL", "TELEKIN_PUSHPULL_NULL" ] }, { "id": "telekinetic_momentum", @@ -313,7 +313,7 @@ }, "min_range": 1, "max_range": 1, - "ignored_monster_species": [ "PSI_NULL" ] + "ignored_monster_species": [ "PSI_NULL", "TELEKIN_PUSHPULL_NULL" ] }, { "id": "telekinetic_strength", diff --git a/data/mods/MindOverMatter/powers/teleportation.json b/data/mods/MindOverMatter/powers/teleportation.json index 4d9c20c927d9a..92e43f10f5acb 100644 --- a/data/mods/MindOverMatter/powers/teleportation.json +++ b/data/mods/MindOverMatter/powers/teleportation.json @@ -535,7 +535,7 @@ "type": "SPELL", "name": "[Ψ]Oubliette", "description": "Teleport the target through the nether to some other dimension. They are technically not dead, but they are no longer your concern. Oubliette will occasionally fail when used against very powerful enemies, or succeed but cause damage to the teleporter.", - "message": "With a tremendous mental exertion, you hurl your target to another dimension!", + "message": "", "teachable": false, "valid_targets": [ "hostile" ], "spell_class": "TELEPORTER", @@ -543,7 +543,8 @@ "flags": [ "PSIONIC", "CONCENTRATE", "SILENT", "RANDOM_DAMAGE", "NO_HANDS", "NO_LEGS", "NO_EXPLOSION_SFX" ], "difficulty": 7, "max_level": { "math": [ "int_to_level(1)" ] }, - "effect": "banishment", + "effect": "effect_on_condition", + "effect_str": "EOC_TELEPORTER_OUBLIETTE_HANDLING", "shape": "blast", "min_damage": { "math": [ @@ -570,6 +571,24 @@ "casting_time_increment": -5.5, "ignored_monster_species": [ "PSI_NULL" ] }, + { + "id": "teleport_banish_self_target", + "type": "SPELL", + "name": "Oubliette Self", + "description": "This is the banishment that the target casts on themselves.", + "valid_targets": [ "self" ], + "skill": "metaphysics", + "flags": [ "PSIONC", "SILENT", "RANDOM_DAMAGE" ], + "effect": "banishment", + "shape": "blast", + "spell_class": "TELEPORTER", + "teachable": false, + "min_damage": { "math": [ "u_psi_teleporter_damage" ] }, + "max_damage": { "math": [ "u_psi_teleporter_damage" ] }, + "min_range": 0, + "max_range": 0, + "ignored_monster_species": [ "PSI_NULL" ] + }, { "id": "teleport_gateway", "type": "SPELL", diff --git a/data/mods/MindOverMatter/powers/teleportation_eoc.json b/data/mods/MindOverMatter/powers/teleportation_eoc.json index 86576288e7f42..847ecb97d6879 100644 --- a/data/mods/MindOverMatter/powers/teleportation_eoc.json +++ b/data/mods/MindOverMatter/powers/teleportation_eoc.json @@ -36,6 +36,70 @@ } ] }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORTER_OUBLIETTE_HANDLING", + "condition": { + "and": [ + { "not": { "u_has_flag": "TELESTOP" } }, + { "not": { "u_has_flag": "TELEPORT_IMMUNE" } }, + { "not": { "u_has_worn_with_flag": "DIMENSIONAL_ANCHOR" } } + ] + }, + "effect": [ { "run_eocs": "EOC_TELEPORTER_OUBLIETTE_HANDLING_2" } ], + "false_effect": [ { "npc_message": "Your target wavers for a moment, but nothing happens." } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORTER_OUBLIETTE_HANDLING_2", + "condition": { "not": "u_is_npc" }, + "effect": [ + { + "math": [ + "u_psi_teleporter_damage", + "=", + "rng(((15 + (n_spell_level('teleport_banish') * 15)) * ( ( n_val('intelligence') + 10) / 20 ) * n_nether_attunement_power_scaling),((350 + (n_spell_level('teleport_banish') * 35)) * ( ( n_val('intelligence') + 10) / 20 ) * n_nether_attunement_power_scaling))" + ] + }, + { "math": [ "u_health_comparison", "=", "u_hp('ALL')" ] }, + { + "if": { "math": [ "u_psi_teleporter_damage", ">", "u_health_comparison" ] }, + "then": [ + { "u_cast_spell": { "id": "teleport_banish_self_target", "message": "" } }, + { "npc_message": "With a tremendous mental exertion, you hurl your target to another dimension!" } + ] + } + ], + "false_effect": [ + { + "math": [ + "u_psi_teleporter_damage", + "=", + "rng(((15 + (n_spell_level('teleport_banish') * 15)) * ( ( n_val('intelligence') + 10) / 20 ) * n_nether_attunement_power_scaling),((350 + (n_spell_level('teleport_banish') * 35)) * ( ( n_val('intelligence') + 10) / 20 ) * n_nether_attunement_power_scaling))" + ] + }, + { + "math": [ + "u_health_comparison", + "=", + "(u_hp('arm_l') + u_hp('arm_r') + u_hp('leg_l') + u_hp('leg_r') + u_hp('torso') + u_hp('head')) / 3" + ] + }, + { + "if": { "math": [ "u_psi_teleporter_damage", ">", "u_health_comparison" ] }, + "then": [ + "u_die", + { "npc_message": "With a tremendous mental exertion, you hurl your target to another dimension!" }, + { + "u_map_run_item_eocs": "all", + "min_radius": 0, + "max_radius": 0, + "true_eocs": [ { "id": "EOC_TELEPORTER_OUBLIETTE_HANDLING_DELETE_NPC_ITEMS", "effect": [ "npc_die" ] } ] + } + ] + } + ] + }, { "type": "effect_on_condition", "id": "EOC_TELEPORT_SUMMON", diff --git a/data/mods/MindOverMatter/recipes/psionics_practice.json b/data/mods/MindOverMatter/recipes/psionics_practice.json index 26074e923b64d..8b31f8aac4698 100644 --- a/data/mods/MindOverMatter/recipes/psionics_practice.json +++ b/data/mods/MindOverMatter/recipes/psionics_practice.json @@ -90,6 +90,20 @@ "byproducts": [ [ "matrix_crystal_drained_dust", 10 ] ], "book_learn": [ [ "manual_psionics_advan", 3 ], [ "schematics_matrix_channeling", 3 ], [ "schematics_matrix_aligning", 3 ] ] }, + { + "id": "prac_psionics_prof_ritual", + "type": "practice", + "activity_level": "LIGHT_EXERCISE", + "category": "CC_PRACTICE", + "subcategory": "CSC_PRACTICE_METAPHYSICS", + "name": "thought-form exercises", + "description": "Practice holding mental images and scenes in your mind for an extended period without your mind wandering.", + "skill_used": "metaphysics", + "practice_data": { "min_difficulty": 4, "max_difficulty": 4, "skill_limit": 4 }, + "proficiencies": [ { "proficiency": "prof_psionic_ritual", "time_multiplier": 1, "skill_penalty": 0 } ], + "time": "1 h", + "book_learn": [ [ "manual_psionic_ritual", 4 ] ] + }, { "id": "prac_concentration_basic", "type": "practice", diff --git a/data/mods/MindOverMatter/recipes/research.json b/data/mods/MindOverMatter/recipes/research.json index c05857f1aff32..c54fcd3c6bf4a 100644 --- a/data/mods/MindOverMatter/recipes/research.json +++ b/data/mods/MindOverMatter/recipes/research.json @@ -201,6 +201,7 @@ "type": "good" }, { "u_add_trait": "PSI_EXTENDED_CHANNELING" }, + { "u_forget_recipe": "psi_research_extended_channeling" }, { "run_eocs": "EOC_PSI_PRACTICE_FOCUS_MOD" } ], "false_effect": [ diff --git a/data/mods/TEST_DATA/EOC.json b/data/mods/TEST_DATA/EOC.json index 024d6fb9c319f..fdb4692462f8f 100644 --- a/data/mods/TEST_DATA/EOC.json +++ b/data/mods/TEST_DATA/EOC.json @@ -338,15 +338,15 @@ "effect": [ { "set_string_var": "prof_test", "target_var": { "global_val": "prof_id" } }, { "math": [ "key_total_time_required", "=", "u_proficiency(prof_id, 'format': 'total_time_required')" ] }, - { "math": [ "u_proficiency(prof_id)", "=", "50" ] }, + { "math": [ "u_proficiency(prof_id, 'direct': true)", "=", "50" ] }, { "math": [ "key_time_spent_50", "=", "u_proficiency(prof_id)" ] }, - { "math": [ "u_proficiency(prof_id, 'format': 'percent')", "=", "50" ] }, + { "math": [ "u_proficiency(prof_id, 'format': 'percent', 'direct': true)", "=", "50" ] }, { "math": [ "key_percent_50", "=", "u_proficiency(prof_id, 'format': 'percent')" ] }, { "math": [ "key_percent_50_turn", "=", "u_proficiency(prof_id)" ] }, - { "math": [ "u_proficiency(prof_id, 'format': 'permille')", "=", "50" ] }, + { "math": [ "u_proficiency(prof_id, 'format': 'permille', 'direct': true)", "=", "50" ] }, { "math": [ "key_permille_50", "=", "u_proficiency(prof_id, 'format': 'permille')" ] }, { "math": [ "key_permille_50_turn", "=", "u_proficiency(prof_id)" ] }, - { "math": [ "u_proficiency(prof_id, 'format': 'time_left')", "=", "50" ] }, + { "math": [ "u_proficiency(prof_id, 'format': 'time_left', 'direct': true)", "=", "50" ] }, { "math": [ "key_time_left_50", "=", "u_proficiency(prof_id, 'format': 'time_left')" ] }, { "math": [ "key_time_left_50_turn", "=", "u_proficiency(prof_id)" ] } ] diff --git a/data/mods/TEST_DATA/mutations.json b/data/mods/TEST_DATA/mutations.json index 8e69486e732e9..9f567335e8871 100644 --- a/data/mods/TEST_DATA/mutations.json +++ b/data/mods/TEST_DATA/mutations.json @@ -8,6 +8,7 @@ "dummy": true, "category": [ "HUMAN" ], "cancels": [ + "TEST_CONSISTENCY_CHECK", "TEST_ENCH_MUTATION", "TEST_GOOD1", "TEST_GOOD2", @@ -37,6 +38,15 @@ "enchantments": [ "TEST_ENCH" ], "category": [ "CEPHALOPOD" ] }, + { + "type": "mutation", + "id": "TEST_CONSISTENCY_CHECK", + "name": "Dummy Test Trait", + "points": 0, + "description": "Test trait to trip the consistency check: it shouldn't cause a load error since it overwrites a basegame trait.", + "prereqs": [ "WINGS_STUB" ], + "category": [ "INST_TEST" ] + }, { "type": "mutation", "id": "TEST_TRIGGER", diff --git a/doc/EFFECT_ON_CONDITION.md b/doc/EFFECT_ON_CONDITION.md index 5a1634d242b6b..7b3d446299004 100644 --- a/doc/EFFECT_ON_CONDITION.md +++ b/doc/EFFECT_ON_CONDITION.md @@ -2044,7 +2044,7 @@ Run EOCs on items in your or NPC's inventory | Syntax | Optionality | Value | Info | | --- | --- | --- | --- | | "u_run_inv_eocs" / "npc_run_inv_eocs" | **mandatory** | string or [variable object](#variable-object) | way the item would be picked;
values can be:
`all` - all items that match the conditions are picked;
`random` - from all items that match the conditions, one picked;
`manual` - menu is open with all items that can be picked, and you can choose one;
`manual_mult` - same as `manual`, but multiple items can be picked | -| "search_data" | optional | `search_data` | sets the condition for the target item; lack of search_data means any item can be picked; conditions can be:
`id` - id of a specific item;
`category` - category of an item (case sensitive, should always be in lower case);
`flags`- flag or flags the item has
`excluded_flags`- flag or flags the item doesn't have
`material` - material of an item;
`worn_only` - if true, return only items, that are worn;
`wielded_only` - if true, return only wielded items | +| "search_data" | optional | `search_data` | sets the condition for the target item; lack of search_data means any item can be picked; conditions can be:
`id` - id of a specific item;
`category` - category of an item (case sensitive, should always be in lower case);
`flags`- flag or flags the item has
`excluded_flags`- flag or flags the item doesn't have
`material` - material of an item;
`worn_only` - if true, return only items, that are worn;
`wielded_only` - if true, return only wielded items;
`calories` - minimum amount of kcal of an item | | "title" | optional | string or [variable object](#variable-object) | name of the menu, that would be shown, if `manual` or `manual_mult` is used | | "true_eocs" / "false_eocs" | optional | string, [variable object](##variable-object), inline EoC, or range of all of them | if item was picked successfully, all EoCs from `true_eocs` are run, otherwise all EoCs from `false_eocs` are run; picked item is returned as npc; for example, `n_hp()` return hp of an item | diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index b6d6e89c8d2df..e0801c2d682c6 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -2972,7 +2972,7 @@ See [MUTATIONS.md](MUTATIONS.md) "always_invisible": true, // Super well hidden traps the player can never detect "funnel_radius": 200, // millimeters. The higher the more rain it will capture. "comfort": 0, // Same property affecting furniture and terrain - "floor_bedding_warmth": -500, // Same property affecting furniture and terrain + "floor_bedding_warmth": -500, // Same property affecting furniture and terrain. Also affects how comfortable a resting place this is(affects healing). Vanilla values should not exceed 1000. "spell_data": { "id": "bear_trap" }, // data required for trapfunc::spell() "trigger_weight": "200 g", // If an item with this weight or more is thrown onto the trap, it triggers. Defaults to 500 grams. "drops": [ "beartrap" ], // ID of item spawned when disassembled @@ -3201,7 +3201,7 @@ These values apply to crafting tasks performed at the WORKBENCH. #### The following optional fields are specific to SEATs. ```c++ "comfort": 3, // (Optional, default=0). Sleeping comfort as for terrain/furniture. -"floor_bedding_warmth": 300, // (Optional, default=0). Bonus warmth as for terrain/furniture. +"floor_bedding_warmth": 300, // (Optional, default=0). Bonus warmth as for terrain/furniture. Also affects how comfortable a resting place this is(affects healing). Vanilla values should not exceed 1000. "bonus_fire_warmth_feet": 200,// (Optional, default=0). Bonus fire warmth as for terrain/furniture. ``` @@ -5438,7 +5438,7 @@ How comfortable this terrain/furniture is. Impact ability to fall asleep on it. #### `floor_bedding_warmth` -Bonus warmth offered by this terrain/furniture when used to sleep. +Bonus warmth offered by this terrain/furniture when used to sleep. Also affects how comfortable a resting place this is(affects healing). Vanilla values should not exceed 1000. #### `bonus_fire_warmth_feet` diff --git a/doc/MAGIC.md b/doc/MAGIC.md index 138388d7f25d7..fb994f6d2b7e1 100644 --- a/doc/MAGIC.md +++ b/doc/MAGIC.md @@ -807,7 +807,7 @@ Character status value | Description `BLEED_STOP_BONUS` | Affects the `bleed` level when applying medicine. `BODYTEMP_SLEEP` | Amount of warmth (in celcius) added to you when you sleep. Default is 0, so better to use `add` `BONUS_BLOCK` | Affects the number of blocks you can perform. -`BONUS_DODGE` | Affects the number of dodges you can perform. +`BONUS_DODGE` | Affects the number of dodges you can perform. Do not confuse with `DODGE_CHANCE` `CARDIO_MULTIPLIER` | Affects total cardio fitness by this amount. Since it's a percent, using `multiply` is recommended. `CARRY_WEIGHT` | Affect the summary weight player can carry. `"add": 1000` adds 1 kg of weight to carry. `CASTING_TIME_MULTIPLIER` | Same as mutation `casting_time_multiplier` field, changes your casting speed. Since it's a percent, using `multiply` is recommended. `"multiply": 2"` triples the casting speed @@ -818,6 +818,7 @@ Character status value | Description `CRAFTING_SPEED_MULTIPLIER` | Changes your crafting speed. Since it's a percent, using `multiply` is recommended. Positive values decrease crafting time, negative values increase it. `DEXTERITY` | Affects the dexterity stat. `DISINFECTANT_BONUS` | Affects the `disinfectant_power` you have when applying medicine. +`DODGE_CHANCE` | Modifies the probability to dodge an attack. Default is 0, so better to use `add` `EFFECTIVE_HEALTH_MOD` | If this is anything other than zero (which it defaults to) you will use it instead of your actual health mod. `EXTRA_ACID` | EXTRA_TYPE increases received damage of the selected type. `EXTRA_BASH` | diff --git a/doc/NPCs.md b/doc/NPCs.md index 78648d101b69f..b163f4f59dde5 100644 --- a/doc/NPCs.md +++ b/doc/NPCs.md @@ -1352,7 +1352,7 @@ _some functions support array arguments or kwargs, denoted with square brackets | moon_phase() | ✅ | ❌ | N/A
(global) | Returns current phase of the Moon.
MOON_NEW = 0,
WAXING_CRESCENT = 1,
HALF_MOON_WAXING = 2,
WAXING_GIBBOUS = 3,
FULL = 4,
WANING_GIBBOUS = 5,
HALF_MOON_WANING = 6,
WANING_CRESCENT = 7 | | num_input(`s`/`v`,`d`/`v`) | ✅ | ❌ | N/A
(global) | Prompt the player for a number.
Arguments are Prompt text, Default Value:
`"math": [ "u_value_to_set", "=", "num_input('Playstyle Perks Cost?', 4)" ]`| | pain() | ✅ | ✅ | u, n | Return or set pain
Example:
`{ "math": [ "n_pain()", "=", "u_pain() + 9000" ] }`| -| proficiency(`s`/`v`) | ✅ | ✅ | u, n | Return or set proficiency
Argument is proficiency ID.

Optional kwargs:
`format`: `s` - `percent` return or set how many percent done the learning is. `permille` does likewise for permille. `time_spent` return or set total time spent. `time_left` return or set the remaining time. `total_time_required` return total time required to train a given proficiency (read only).

Example:
`{ "math": [ "u_proficiency('prof_intro_chemistry', 'format': 'percent')", "=", "50" ] }`| +| proficiency(`s`/`v`) | ✅ | ✅ | u, n | Return or set proficiency
Argument is proficiency ID.

Optional kwargs:
`format`: `s` - `percent` return or set how many percent done the learning is. `permille` does likewise for permille. `time_spent` return or set total time spent. `time_left` return or set the remaining time. `total_time_required` return total time required to train a given proficiency (read only).
`direct`: `true`/`false`/`d` - false (default) perform the adjustment by practicing the proficiency for the given amount of time. This will likely result in different values than specified. `true` perform the adjustment directly, bypassing other factors that may affect it.

Example:
`{ "math": [ "u_proficiency('prof_intro_chemistry', 'format': 'percent')", "=", "50" ] }`| | school_level(`s`/`v`) | ✅ | ❌ | u, n | Return the highest level of spells known of that school.
Argument is school ID.

Example:
`"condition": { "math": [ "u_school_level('MAGUS')", ">=", "3"] }`| | school_level_adjustment(`s`/`v`) | ✅ | ✅ | u, n | Return or set temporary caster level adjustment. Only useable by EoCs that trigger on the event `opens_spellbook`. Old values will be reset to 0 before the event triggers. To avoid overwriting values from other EoCs, it is recommended to adjust the values here with `+=` or `-=` instead of setting it to an absolute value.
Argument is school ID.

Example:
`{ "math": [ "u_school_level_adjustment('MAGUS')", "+=", "3"] }`| | skill(`s`/`v`) | ✅ | ✅ | u, n | Return or set skill level

Example:
`"condition": { "math": [ "u_skill('driving')", ">=", "5"] }`
`"condition": { "math": [ "u_skill(someskill)", ">=", "5"] }`| diff --git a/src/action.cpp b/src/action.cpp index a1516d987dddf..55193407acfb4 100644 --- a/src/action.cpp +++ b/src/action.cpp @@ -10,7 +10,7 @@ #include #include "avatar.h" -#include "cached_options.h" +#include "cached_options.h" // IWYU pragma: keep #include "cata_utility.h" #include "character.h" #include "creature.h" @@ -18,9 +18,12 @@ #include "debug.h" #include "flag.h" #include "game.h" +#include "game_constants.h" #include "input_context.h" +#include "input_enums.h" #include "inventory.h" #include "item.h" +#include "item_location.h" #include "map.h" #include "map_iterator.h" #include "mapdata.h" diff --git a/src/action.h b/src/action.h index e81798c888c5c..19d62f8e19000 100644 --- a/src/action.h +++ b/src/action.h @@ -13,6 +13,7 @@ struct input_event; struct point; +struct tripoint; /** * Enumerates all discrete actions that can be performed by player diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index 0612addfdf72b..caa71439eb60a 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -1167,14 +1167,16 @@ static bool butchery_drops_harvest( item *corpse_item, const mtype &mt, Characte const int item_charges = monster_weight_remaining / to_gram( item::find_type( leftover_id )->weight ); if( item_charges > 0 ) { - item ruined_parts( leftover_id, calendar::turn, item_charges ); + item ruined_parts( leftover_id, calendar::turn ); ruined_parts.set_mtype( &mt ); ruined_parts.set_item_temperature( corpse_item->temperature ); ruined_parts.set_rot( corpse_item->get_rot() ); if( !you.backlog.empty() && you.backlog.front().id() == ACT_MULTIPLE_BUTCHER ) { ruined_parts.set_var( "activity_var", you.name ); } - here.add_item_or_charges( you.pos(), ruined_parts ); + for( int i = 0; i < item_charges; ++i ) { + here.add_item_or_charges( you.pos(), ruined_parts ); + } } } diff --git a/src/avatar.cpp b/src/avatar.cpp index 393449ea5396c..337f136d50060 100644 --- a/src/avatar.cpp +++ b/src/avatar.cpp @@ -2,9 +2,9 @@ #include #include -#include #include -#include +#include +#include #include #include #include @@ -15,18 +15,17 @@ #include #include "action.h" -#include "activity_type.h" #include "activity_actor_definitions.h" -#include "bionics.h" #include "bodypart.h" #include "calendar.h" #include "cata_assert.h" +#include "cata_utility.h" #include "catacharset.h" #include "character.h" #include "character_id.h" #include "character_martial_arts.h" -#include "clzones.h" #include "color.h" +#include "creature.h" #include "cursesdef.h" #include "debug.h" #include "diary.h" @@ -36,19 +35,22 @@ #include "event_bus.h" #include "faction.h" #include "field_type.h" +#include "flexbuffer_json-inl.h" +#include "flexbuffer_json.h" #include "game.h" #include "game_constants.h" +#include "game_inventory.h" #include "help.h" #include "inventory.h" #include "item.h" #include "item_location.h" #include "itype.h" #include "iuse.h" -#include "kill_tracker.h" -#include "make_static.h" -#include "magic_enchantment.h" +#include "json.h" +#include "line.h" #include "map.h" #include "map_memory.h" +#include "mapdata.h" #include "martialarts.h" #include "messages.h" #include "mission.h" @@ -57,15 +59,14 @@ #include "move_mode.h" #include "mutation.h" #include "npc.h" -#include "options.h" #include "output.h" #include "overmap.h" #include "overmapbuffer.h" #include "pathfinding.h" #include "pimpl.h" -#include "player_activity.h" #include "profession.h" #include "ranged.h" +#include "recipe.h" #include "ret_val.h" #include "rng.h" #include "scenario.h" @@ -74,8 +75,8 @@ #include "string_formatter.h" #include "talker.h" #include "talker_avatar.h" -#include "translations.h" #include "timed_event.h" +#include "translations.h" #include "trap.h" #include "type_id.h" #include "ui.h" @@ -85,6 +86,8 @@ #include "vehicle.h" #include "vpart_position.h" +class monfaction; + static const bionic_id bio_cloak( "bio_cloak" ); static const bionic_id bio_soporific( "bio_soporific" ); diff --git a/src/avatar.h b/src/avatar.h index e110a6de2ed15..5d3f78b53018a 100644 --- a/src/avatar.h +++ b/src/avatar.h @@ -2,25 +2,30 @@ #ifndef CATA_SRC_AVATAR_H #define CATA_SRC_AVATAR_H -#include -#include +#include #include #include #include +#include #include +#include #include +#include #include +#include "bodypart.h" #include "calendar.h" #include "character.h" +#include "character_id.h" #include "coordinates.h" #include "enums.h" #include "game_constants.h" +#include "item.h" #include "magic_teleporter_list.h" #include "mdarray.h" -#include "memory_fast.h" #include "point.h" #include "type_id.h" +#include "units.h" class advanced_inv_area; class advanced_inv_listitem; @@ -28,30 +33,27 @@ class advanced_inventory_pane; class cata_path; class diary; class faction; -class item; class item_location; class JsonObject; class JsonOut; +class map_memory; +class memorized_tile; class mission; class monster; class nc_color; class npc; class talker; struct bionic; +struct mtype; namespace catacurses { class window; } // namespace catacurses -enum class character_type : int; -class map_memory; -class memorized_tile; - namespace debug_menu { class mission_debug; } // namespace debug_menu -struct mtype; enum class pool_type; // Monster visible in different directions (safe mode & compass) diff --git a/src/cata_imgui.cpp b/src/cata_imgui.cpp index efd34887a4ace..42228fbf5f8cd 100644 --- a/src/cata_imgui.cpp +++ b/src/cata_imgui.cpp @@ -10,6 +10,7 @@ #include "input.h" #include "output.h" #include "ui_manager.h" +#include "input_context.h" static ImGuiKey cata_key_to_imgui( int cata_key ); @@ -461,6 +462,13 @@ class cataimgui::window_impl } }; +class cataimgui::filter_box_impl +{ + public: + std::array text; + ImGuiID id; +}; + cataimgui::window::window( int window_flags ) { p_impl = nullptr; @@ -599,3 +607,51 @@ cataimgui::bounds cataimgui::window::get_bounds() { return { -1.f, -1.f, -1.f, -1.f }; } + +void cataimgui::window::draw_filter( const input_context &ctxt, bool filtering_active ) +{ + if( !filter_impl ) { + filter_impl = std::make_unique(); + filter_impl->id = 0; + filter_impl->text[0] = '\0'; + } + + if( !filtering_active ) { + action_button( "FILTER", ctxt.get_button_text( "FILTER" ) ); + ImGui::SameLine(); + action_button( "RESET_FILTER", ctxt.get_button_text( "RESET_FILTER" ) ); + ImGui::SameLine(); + } else { + action_button( "QUIT", ctxt.get_button_text( "QUIT", _( "Cancel" ) ) ); + ImGui::SameLine(); + action_button( "TEXT.CONFIRM", ctxt.get_button_text( "TEXT.CONFIRM", _( "OK" ) ) ); + ImGui::SameLine(); + } + ImGui::BeginDisabled( !filtering_active ); + ImGui::InputText( "##FILTERBOX", filter_impl->text.data(), + filter_impl->text.size() ); + ImGui::EndDisabled(); + if( !filter_impl->id ) { + filter_impl->id = GImGui->LastItemData.ID; + } +} + +std::string cataimgui::window::get_filter() +{ + if( filter_impl ) { + return std::string( filter_impl->text.data() ); + } else { + return std::string(); + } +} + +void cataimgui::window::clear_filter() +{ + if( filter_impl && filter_impl->id != 0 ) { + ImGuiInputTextState *input_state = ImGui::GetInputTextState( filter_impl->id ); + if( input_state ) { + input_state->ClearText(); + filter_impl->text[0] = '\0'; + } + } +} diff --git a/src/cata_imgui.h b/src/cata_imgui.h index 4f9707993d804..50db9dbe4e519 100644 --- a/src/cata_imgui.h +++ b/src/cata_imgui.h @@ -18,6 +18,7 @@ struct item_info_data; struct point; class ImVec2; class Font; +class input_context; namespace cataimgui { @@ -78,6 +79,7 @@ void imvec2_to_point( ImVec2 *src, point *dest ); class window { std::unique_ptr p_impl; + std::unique_ptr filter_impl; bounds cached_bounds; protected: explicit window( int window_flags = 0 ); @@ -102,6 +104,8 @@ class window size_t get_text_height( const char *text ); size_t str_width_to_pixels( size_t len ); size_t str_height_to_pixels( size_t len ); + std::string get_filter(); + void clear_filter(); void mark_resized(); protected: @@ -112,6 +116,7 @@ class window std::string button_action; virtual bounds get_bounds(); virtual void draw_controls() = 0; + void draw_filter( const input_context &ctxt, bool filtering_active ); }; #if !(defined(TILES) || defined(WIN32)) diff --git a/src/character.cpp b/src/character.cpp index 887c229660fbb..8a8c39b848f7d 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -99,6 +99,7 @@ #include "trap.h" #include "ui.h" #include "ui_manager.h" +#include "uistate.h" #include "units.h" #include "value_ptr.h" #include "veh_type.h" @@ -3770,6 +3771,8 @@ void Character::reset_stats() update_mental_focus(); } + mod_dodge_bonus( enchantment_cache->modify_value( enchant_vals::mod::DODGE_CHANCE, 0 ) ); + /** @EFFECT_STR_MAX above 15 decreases Dodge bonus by 1 (NEGATIVE) */ if( str_max >= 16 ) { mod_dodge_bonus( -1 ); // Penalty if we're huge @@ -6143,6 +6146,7 @@ float Character::rest_quality() const map &here = get_map(); const tripoint your_pos = pos(); float rest = 0.0f; + const float ur_act_level = instantaneous_activity_level(); // Negative morales are penalties int cold_penalty = -has_morale( morale_cold ); int heat_penalty = -has_morale( morale_hot ); @@ -6160,7 +6164,7 @@ float Character::rest_quality() const } const optional_vpart_position veh_part = here.veh_at( your_pos ); bool has_vehicle_seat = !!veh_part.part_with_feature( "SEAT", true ); - if( activity_level() <= LIGHT_EXERCISE ) { + if( ur_act_level <= LIGHT_EXERCISE ) { rest += 0.1f; if( here.has_flag_ter_or_furn( "CAN_SIT", your_pos.xy() ) || has_vehicle_seat ) { // If not performing any real exercise (not even moving around), chairs allow you to rest a little bit. @@ -6169,20 +6173,21 @@ float Character::rest_quality() const // Any comfortable bed can substitute for a chair, but only if you don't have one. rest += 0.2f * ( units::to_celsius_delta( floor_bedding_warmth( your_pos ) ) / 2.0f ); } - if( activity_level() <= NO_EXERCISE ) { + if( ur_act_level <= NO_EXERCISE ) { rest += 0.2f; } } // These stack! - if( activity_level() >= BRISK_EXERCISE ) { + if( ur_act_level >= BRISK_EXERCISE ) { rest -= 0.1f; } - if( activity_level() >= ACTIVE_EXERCISE ) { + if( ur_act_level >= ACTIVE_EXERCISE ) { rest -= 0.2f; } - if( activity_level() >= EXTRA_EXERCISE ) { + if( ur_act_level >= EXTRA_EXERCISE ) { rest -= 0.3f; } + add_msg_debug( debugmode::DF_CHAR_HEALTH, "%s resting quality: %.6f", get_name(), rest ); return rest; } @@ -6321,7 +6326,8 @@ float Character::healing_rate_medicine( float at_rest_quality, const bodypart_id rate_medicine = enchantment_cache->modify_value( enchant_vals::mod::REGEN_HP, rate_medicine ); - rate_medicine *= 1.0f + clamp( at_rest_quality, 0.0f, 1.0f ); + // Sufficiently negative rest quality can completely eliminate your healing, but never turn it negative. + rate_medicine *= 1.0f + std::max( at_rest_quality, -1.0f ); // increase healing if character has both effects if( has_effect( effect_bandaged ) && has_effect( effect_disinfected ) ) { @@ -12838,7 +12844,8 @@ void Character::process_items() // Load all items that use the UPS and have their own battery to their minimal functional charge, // The tool is not really useful if its charges are below charges_to_use std::vector inv_use_ups = cache_get_items_with( flag_USE_UPS, []( item & it ) { - return !!it.ammo_data(); + return ( it.ammo_capacity( ammo_battery ) > it.ammo_remaining() || + ( it.type->battery && it.type->battery->max_capacity > it.energy_remaining( nullptr ) ) ); } ); if( !inv_use_ups.empty() ) { const units::energy available_charges = available_ups(); diff --git a/src/character_proficiency.cpp b/src/character_proficiency.cpp index 76121e0681702..152092e44e035 100644 --- a/src/character_proficiency.cpp +++ b/src/character_proficiency.cpp @@ -108,7 +108,7 @@ void Character::set_proficiency_practice( const proficiency_id &id, const time_d return; } - _proficiencies->practice( id, amount, 0.f, std::nullopt ); + _proficiencies->set_time_practiced( id, amount ); } std::vector Character::proficiencies_offered_to( const Character *guy ) const diff --git a/src/clzones.h b/src/clzones.h index 3c6c62ac5ba18..fb31b1d93a498 100644 --- a/src/clzones.h +++ b/src/clzones.h @@ -67,7 +67,7 @@ class zone_type static void reset(); void load( const JsonObject &jo, std::string_view ); /** - * All spells in the game. + * All zone types in the game. */ static const std::vector &get_all(); bool is_valid() const; diff --git a/src/diary.cpp b/src/diary.cpp index ecaae3f8f6bbd..1b96298bc04af 100644 --- a/src/diary.cpp +++ b/src/diary.cpp @@ -1,26 +1,40 @@ #include "diary.h" #include +#include #include -#include -#include #include #include #include "avatar.h" #include "bionics.h" #include "calendar.h" +#include "cata_path.h" #include "cata_utility.h" +#include "catacharset.h" +#include "color.h" #include "filesystem.h" +#include "flexbuffer_json-inl.h" +#include "flexbuffer_json.h" #include "game.h" +#include "json.h" +#include "json_error.h" +#include "kill_tracker.h" +#include "magic.h" #include "mission.h" #include "mtype.h" #include "mutation.h" +#include "npc.h" #include "output.h" #include "path_info.h" +#include "pimpl.h" +#include "proficiency.h" #include "skill.h" #include "string_formatter.h" +#include "translation.h" +#include "translations.h" #include "type_id.h" +#include "weather.h" diary_page::diary_page() = default; diff --git a/src/diary.h b/src/diary.h index 78db08e40652e..af82337b35cd7 100644 --- a/src/diary.h +++ b/src/diary.h @@ -2,21 +2,26 @@ #ifndef CATA_SRC_DIARY_H #define CATA_SRC_DIARY_H +#include +#include +#include +#include #include -#include #include -#include "achievement.h" -#include "character.h" -#include "kill_tracker.h" -#include "skill.h" -#include "stats_tracker.h" -#include "ui.h" +#include "calendar.h" +#include "mutation.h" +#include "type_id.h" #include "units.h" -enum class time_accuracy; +class JsonOut; class JsonValue; +namespace catacurses +{ +class window; +} // namespace catacurses + /// /// diary page, to save current character progression /// @@ -63,8 +68,9 @@ struct diary_page { }; /// -/// diary is connected to the player avatar. -/// the player is able to add new pages every page saves the current character progression and shows the improvements compared to the previous pages +/// Diary is connected to the player avatar. +/// The player is able to add new pages. +/// Every page saves the current character progression and shows the improvements compared to the previous pages. /// The player is also able to add a Text in every page. /// class diary diff --git a/src/diary_ui.cpp b/src/diary_ui.cpp index 888b6c90bb02d..ec26a4cbdb883 100644 --- a/src/diary_ui.cpp +++ b/src/diary_ui.cpp @@ -1,11 +1,13 @@ #include "game.h" // IWYU pragma: associated #include +#include #include #include #include #include +#include "catacharset.h" #include "color.h" #include "cursesdef.h" #include "diary.h" diff --git a/src/game.cpp b/src/game.cpp index 27bb3aac8a642..42667b5e2696c 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1,6 +1,5 @@ #include "game.h" -#include #include #include #include @@ -12,10 +11,13 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include #include @@ -45,21 +47,25 @@ #include "avatar_action.h" #include "basecamp.h" #include "bionics.h" +#include "body_part_set.h" #include "bodygraph.h" #include "bodypart.h" #include "butchery_requirements.h" #include "cached_options.h" +#include "cata_path.h" #include "cata_scope_helpers.h" #include "cata_utility.h" #include "cata_variant.h" #include "catacharset.h" #include "character.h" +#include "character_attire.h" #include "character_martial_arts.h" #include "city.h" #include "climbing.h" #include "clzones.h" #include "colony.h" #include "color.h" +#include "computer.h" #include "computer_session.h" #include "construction.h" #include "construction_group.h" @@ -72,10 +78,12 @@ #include "damage.h" #include "debug.h" #include "dependency_tree.h" +#include "dialogue.h" #include "dialogue_chatbin.h" #include "diary.h" #include "distraction_manager.h" #include "editmap.h" +#include "effect.h" #include "effect_on_condition.h" #include "enums.h" #include "event.h" @@ -86,6 +94,8 @@ #include "field_type.h" #include "filesystem.h" #include "flag.h" +#include "flexbuffer_json-inl.h" +#include "flexbuffer_json.h" #include "game_constants.h" #include "game_inventory.h" #include "game_ui.h" @@ -93,11 +103,11 @@ #include "gates.h" #include "get_version.h" #include "harvest.h" -#include "help.h" #include "iexamine.h" #include "init.h" #include "input.h" #include "input_context.h" +#include "input_enums.h" #include "inventory.h" #include "item.h" #include "item_category.h" @@ -116,8 +126,9 @@ #include "line.h" #include "live_view.h" #include "loading_ui.h" -#include "main_menu.h" #include "magic.h" +#include "magic_enchantment.h" +#include "main_menu.h" #include "make_static.h" #include "map.h" #include "map_item_stack.h" @@ -126,17 +137,20 @@ #include "mapbuffer.h" #include "mapdata.h" #include "mapsharing.h" +#include "maptile_fwd.h" #include "memorial_logger.h" #include "messages.h" #include "mission.h" #include "mod_manager.h" #include "monexamine.h" +#include "mongroup.h" +#include "monster.h" #include "monstergenerator.h" #include "move_mode.h" #include "mtype.h" #include "npc.h" -#include "npctrade.h" #include "npc_class.h" +#include "npctrade.h" #include "omdata.h" #include "options.h" #include "output.h" @@ -144,7 +158,6 @@ #include "overmap_ui.h" #include "overmapbuffer.h" #include "panels.h" -#include "past_games_info.h" #include "past_achievements_info.h" #include "path_info.h" #include "pathfinding.h" @@ -152,6 +165,7 @@ #include "player_activity.h" #include "popup.h" #include "profession.h" +#include "proficiency.h" #include "recipe.h" #include "recipe_dictionary.h" #include "ret_val.h" @@ -170,6 +184,8 @@ #include "text_snippets.h" #include "tileray.h" #include "timed_event.h" +#include "translation.h" +#include "translation_cache.h" #include "translations.h" #include "trap.h" #include "ui.h" @@ -182,8 +198,11 @@ #include "veh_type.h" #include "vehicle.h" #include "viewer.h" +#include "visitable.h" #include "vpart_position.h" #include "vpart_range.h" +#include "wcwidth.h" +#include "weakpoint.h" #include "weather.h" #include "weather_type.h" #include "worldfactory.h" diff --git a/src/game.h b/src/game.h index 2b65c5aac5d72..dba3999e6476e 100644 --- a/src/game.h +++ b/src/game.h @@ -7,12 +7,12 @@ #include #include #include -#include +#include #include -#include -#include #include #include +#include +#include #include #include #include @@ -20,6 +20,7 @@ #include "calendar.h" #include "character.h" #include "character_id.h" +#include "color.h" #include "coordinates.h" #include "creature.h" #include "cursesdef.h" @@ -28,23 +29,12 @@ #include "global_vars.h" #include "item_location.h" #include "memory_fast.h" -#include "monster.h" #include "pimpl.h" #include "point.h" #include "type_id.h" -#include "uistate.h" #include "units_fwd.h" #include "weather.h" -class Character; -class creature_tracker; -class JsonValue; -class item; -class location; -class eoc_events; -class spell_events; -class viewer; - constexpr int DEFAULT_TILESET_ZOOM = 16; // The reference to the one and only game instance. @@ -76,32 +66,40 @@ enum safe_mode_type { enum action_id : int; +class JsonValue; class achievements_tracker; class avatar; +class cata_path; +class creature_tracker; +class eoc_events; class event_bus; class faction_manager; +class field_entry; +class item; class kill_tracker; +class live_view; +class loading_ui; class map; class map_item_stack; class memorial_logger; +class monster; class npc; +class npc_template; +class overmap; class save_t; class scenario; -class stats_tracker; -class vehicle; -struct WORLD; -struct special_game; -template -class tripoint_range; -class exosuit_interact; -class live_view; -class loading_ui; -class overmap; class scent_map; +class spell_events; class static_popup; +class stats_tracker; class timed_event_manager; class ui_adaptor; +class uilist; +class vehicle; +class viewer; +struct special_game; struct visibility_variables; +template class tripoint_range; using item_filter = std::function; using item_location_filter = std::function; diff --git a/src/handle_action.cpp b/src/handle_action.cpp index 3cc0cc11d2695..95fa7ed406152 100644 --- a/src/handle_action.cpp +++ b/src/handle_action.cpp @@ -1,9 +1,9 @@ #include "game.h" // IWYU pragma: associated -#include #include #include #include +#include #include #include #include @@ -24,6 +24,7 @@ #include "calendar.h" #include "catacharset.h" #include "character.h" +#include "character_attire.h" #include "character_martial_arts.h" #include "clzones.h" #include "color.h" @@ -49,6 +50,8 @@ #include "gun_mode.h" #include "help.h" #include "input_context.h" +#include "input_enums.h" +#include "inventory_ui.h" #include "item.h" #include "item_group.h" #include "itype.h" @@ -61,11 +64,13 @@ #include "map_iterator.h" #include "mapdata.h" #include "mapsharing.h" +#include "mdarray.h" #include "messages.h" #include "monster.h" #include "move_mode.h" #include "mtype.h" #include "mutation.h" +#include "npc.h" #include "options.h" #include "output.h" #include "overmap_ui.h" @@ -77,10 +82,13 @@ #include "safemode_ui.h" #include "sounds.h" #include "string_formatter.h" +#include "string_input_popup.h" #include "timed_event.h" +#include "translation.h" #include "translations.h" #include "ui.h" #include "ui_manager.h" +#include "uistate.h" #include "units.h" #include "value_ptr.h" #include "veh_type.h" diff --git a/src/input_context.cpp b/src/input_context.cpp index 7569703ba4758..ce36e2caf2220 100644 --- a/src/input_context.cpp +++ b/src/input_context.cpp @@ -35,7 +35,7 @@ #include "imgui/imgui.h" enum class kb_menu_status { - remove, reset, add, add_global, execute, show + remove, reset, add, add_global, execute, show, filter }; class keybindings_ui : public cataimgui::window @@ -48,7 +48,6 @@ class keybindings_ui : public cataimgui::window const nc_color unbound_key = c_light_red; const nc_color h_unbound_key = h_light_red; input_context *ctxt; - char filter_text_impl[255]; // NOLINT(modernize-avoid-c-arrays) public: // current status: adding/removing/reseting/executing/showing keybindings kb_menu_status status = kb_menu_status::show, last_status = kb_menu_status::execute; @@ -61,7 +60,7 @@ class keybindings_ui : public cataimgui::window std::string hotkeys; int highlight_row_index = -1; size_t scroll_offset = 0; - std::string filter_text; + //std::string filter_text; keybindings_ui( bool permit_execute_action, input_context *parent ); void init(); @@ -321,6 +320,44 @@ std::string input_context::get_desc( const std::string &action_descriptor, return rval; } + +std::string input_context::get_button_text( const std::string &action_descriptor ) const +{ + std::string action_name = get_action_name( action_descriptor ); + if( action_name.empty() ) { + action_name = action_descriptor; + } + return get_button_text( action_descriptor, action_name ); +} + +std::string input_context::get_button_text( const std::string &action_descriptor, + const std::string &action_text ) const +{ + if( action_descriptor == "ANY_INPUT" ) { + return ""; // what sort of crazy button would this be? + } + + bool is_local = false; + const std::vector &events = inp_mngr.get_input_for_action( action_descriptor, + category, &is_local ); + if( events.empty() ) { + return action_text; + } + + std::vector inputs_to_show; + for( const input_event &event : events ) { + if( is_event_type_enabled( event.type ) ) { + inputs_to_show.push_back( event ); + } + } + + if( inputs_to_show.empty() ) { + return action_text; + } else { + return string_format( "[%s] %s", inputs_to_show[0].long_description(), action_text ); + } +} + std::string input_context::get_desc( const std::string &action_descriptor, const std::string &text, @@ -608,7 +645,6 @@ static const std::map fallback_keys = { keybindings_ui::keybindings_ui( bool permit_execute_action, input_context *parent ) : cataimgui::window( "KEYBINDINGS", ImGuiWindowFlags_NoNav ) { - filter_text_impl[0] = '\0'; this->ctxt = parent; legend.push_back( colorize( _( "Unbound keys" ), unbound_key ) ); @@ -655,23 +691,24 @@ void keybindings_ui::draw_controls() ImGui::SetCursorPosX( str_width_to_pixels( width ) - ( get_text_width( button_text_no_color ) + ( ImGui::GetStyle().FramePadding.x * 2 ) + ImGui::GetStyle().ItemSpacing.x ) ); + ImGui::BeginDisabled( status == kb_menu_status::filter ); action_button( buttons[legend_idx].first, button_text_no_color ); + ImGui::EndDisabled(); } for( ; legend_idx < legend.size(); legend_idx++ ) { draw_colored_text( legend[legend_idx], c_white ); } - if( last_status != status && status == kb_menu_status::show ) { - ImGui::SetKeyboardFocusHere( 0 ); + draw_filter( *ctxt, status == kb_menu_status::filter ); + if( last_status != status && status == kb_menu_status::filter ) { + ImGui::SetKeyboardFocusHere( -1 ); } - strncpy( filter_text_impl, filter_text.c_str(), filter_text.length() ); - ImGui::InputText( "##NOLABEL", filter_text_impl, std::extent_v< decltype( filter_text_impl )>, - status == kb_menu_status::show ? ImGuiInputTextFlags_None : ImGuiInputTextFlags_ReadOnly ); - filter_text.assign( filter_text_impl ); ImGui::Separator(); + + if( last_status != status && status == kb_menu_status::show ) { + ImGui::SetNextWindowFocus(); + } if( ImGui::BeginTable( "KB_KEYS", 2, ImGuiTableFlags_ScrollY ) ) { - if( last_status != status && status != kb_menu_status::show ) { - ImGui::SetKeyboardFocusHere( 0 ); - } + ImGui::TableSetupColumn( "Action Name", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_NoSort ); float keys_col_width = str_width_to_pixels( width ) - str_width_to_pixels( TERMX >= 100 ? 62 : 52 ); @@ -1299,10 +1336,13 @@ action_id input_context::display_menu_imgui( const bool permit_execute_action ) ctxt.register_action( "ADD_LOCAL" ); ctxt.register_action( "ADD_GLOBAL" ); ctxt.register_action( "TEXT.CLEAR" ); + ctxt.register_action( "TEXT.CONFIRM" ); ctxt.register_action( "PAGE_UP" ); ctxt.register_action( "PAGE_DOWN" ); ctxt.register_action( "END" ); ctxt.register_action( "HOME" ); + ctxt.register_action( "FILTER" ); + ctxt.register_action( "RESET_FILTER" ); ctxt.register_action( "TEXT.INPUT_FROM_FILE" ); if( permit_execute_action ) { ctxt.register_action( "EXECUTE" ); @@ -1357,13 +1397,19 @@ action_id input_context::display_menu_imgui( const bool permit_execute_action ) } kb_menu.filtered_registered_actions = filter_strings_by_phrase( org_registered_actions, - kb_menu.filter_text ); + kb_menu.get_filter() ); // In addition to the modifiable hotkeys, we also check for hardcoded // keys, e.g. '+', '-', '=', '.' in order to prevent the user from // entering an unrecoverable state. - if( action == "ADD_LOCAL" - || raw_input_char == fallback_keys.at( fallback_action::add_local ) ) { + if( kb_menu.status == kb_menu_status::filter ) { + if( action == "QUIT" ) { + kb_menu.clear_filter( ); + kb_menu.status = kb_menu_status::show; + } else if( action == "TEXT.CONFIRM" ) { + kb_menu.status = kb_menu_status::show; + } + } else if( action == "ADD_LOCAL" ) { if( !kb_menu.filtered_registered_actions.empty() ) { kb_menu.status = kb_menu_status::add; } @@ -1391,19 +1437,21 @@ action_id input_context::display_menu_imgui( const bool permit_execute_action ) } else if( action == "PAGE_UP" || action == "PAGE_DOWN" || action == "HOME" || action == "END" ) { continue; // do nothing - on tiles version for some reason this counts as pressing various alphabet keys } else if( action == "TEXT.CLEAR" ) { - kb_menu.filter_text.assign( "" ); + kb_menu.clear_filter(); kb_menu.filtered_registered_actions = filter_strings_by_phrase( org_registered_actions, "" ); } else if( !kb_menu.get_is_open() ) { break; + } else if( action == "FILTER" ) { + kb_menu.status = kb_menu_status::filter; + } else if( action == "RESET_FILTER" ) { + kb_menu.clear_filter(); } else if( action == "QUIT" ) { if( kb_menu.status != kb_menu_status::show ) { kb_menu.status = kb_menu_status::show; } else { break; } - } else if( action == "TEXT.INPUT_FROM_FILE" ) { - kb_menu.filter_text += get_input_string_from_file(); } else if( action == "HELP_KEYBINDINGS" ) { // update available hotkeys in case they've changed kb_menu.hotkeys = ctxt.get_available_single_char_hotkeys( display_help_hotkeys ); diff --git a/src/input_context.h b/src/input_context.h index b88624b4519c1..544104496bb95 100644 --- a/src/input_context.h +++ b/src/input_context.h @@ -222,6 +222,27 @@ class input_context unsigned int max_limit = 0, const input_event_filter &evt_filter = allow_all_keys ) const; + /** + * Get a description for the action parameter along with a printable hotkey + * for the description in the format [%s] %s + * + * @param action_descriptor The action descriptor for which to return + * a description of the bound keys. + */ + std::string get_button_text( const std::string &action_descriptor ) const; + + /** + * Get a description for the action parameter along with a printable hotkey + * for the description in the format [%s] %s + * + * @param action_descriptor The action descriptor for which to return + * a description of the bound keys. + * + * @param action_text The human readable description of the action. + */ + std::string get_button_text( const std::string &action_descriptor, + const std::string &action_text ) const; + /** * Get a description based on `text`. If a bound key for `action_descriptor` * satisfying `evt_filter` is contained in `text`, surround the key with diff --git a/src/item.cpp b/src/item.cpp index aa0b135f107a6..3b0b1dfbc7047 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -312,7 +312,11 @@ item::item( const itype *type, time_point turn, int qty ) : type( type ), bday( } if( qty >= 0 ) { - charges = qty; + if( type->can_have_charges() ) { + charges = qty; + } else if( qty > 1 ) { + debugmsg( "Tried to set charges for item %s that could not have them!", tname() ); + } } else { if( type->tool && type->tool->rand_charges.size() > 1 ) { const int charge_roll = rng( 1, type->tool->rand_charges.size() - 1 ); diff --git a/src/magic_enchantment.cpp b/src/magic_enchantment.cpp index 24005ad1a702f..c73c98728a234 100644 --- a/src/magic_enchantment.cpp +++ b/src/magic_enchantment.cpp @@ -87,6 +87,7 @@ namespace io case enchant_vals::mod::PAIN_PENALTY_MOD_SPEED: return "PAIN_PENALTY_MOD_SPEED"; case enchant_vals::mod::MELEE_DAMAGE: return "MELEE_DAMAGE"; case enchant_vals::mod::RANGED_DAMAGE: return "RANGED_DAMAGE"; + case enchant_vals::mod::DODGE_CHANCE: return "DODGE_CHANCE"; case enchant_vals::mod::BONUS_BLOCK: return "BONUS_BLOCK"; case enchant_vals::mod::BONUS_DODGE: return "BONUS_DODGE"; case enchant_vals::mod::ATTACK_NOISE: return "ATTACK_NOISE"; diff --git a/src/magic_enchantment.h b/src/magic_enchantment.h index 8d2e46e52b2d6..71ce85a7b4b30 100644 --- a/src/magic_enchantment.h +++ b/src/magic_enchantment.h @@ -62,6 +62,7 @@ enum class mod : int { PAIN_PENALTY_MOD_INT, PAIN_PENALTY_MOD_PER, PAIN_PENALTY_MOD_SPEED, + DODGE_CHANCE, BONUS_DODGE, BONUS_BLOCK, MELEE_DAMAGE, diff --git a/src/math_parser_diag.cpp b/src/math_parser_diag.cpp index ce2538a062838..146395375a472 100644 --- a/src/math_parser_diag.cpp +++ b/src/math_parser_diag.cpp @@ -66,6 +66,11 @@ bool is_beta( char scope ) } } +constexpr bool is_true( double dbl ) +{ + return dbl >= 1 || float_equals( dbl, 1 ); +} + template constexpr std::string_view _str_type_of() { @@ -1195,13 +1200,18 @@ std::function proficiency_ass( char scope, std::vector const ¶ms, diag_kwargs const &kwargs ) { diag_value fmt_val( std::string{"time_spent"} ); + diag_value direct_val( 0.0 ); if( kwargs.count( "format" ) != 0 ) { fmt_val = *kwargs.at( "format" ); } - return [prof_value = params[0], fmt_val, beta = is_beta( scope )]( dialogue const & d, + if( kwargs.count( "direct" ) != 0 ) { + direct_val = *kwargs.at( "direct" ); + } + return [prof_value = params[0], fmt_val, direct_val, beta = is_beta( scope )]( dialogue const & d, double val ) { proficiency_id prof( prof_value.str( d ) ); std::string const format = fmt_val.str( d ); + bool const direct = is_true( direct_val.dbl( d ) ); int to_write = 0; if( format == "percent" ) { to_write = to_turns( prof->time_to_learn() * val ) / 100; @@ -1215,7 +1225,17 @@ std::function proficiency_ass( char scope, } to_write = val; } - d.actor( beta )->set_proficiency_practiced_time( prof, to_write ); + int before = to_turns( d.actor( beta )->proficiency_practiced_time( prof ) ); + int learned = to_write - before; + if( !direct && learned < 0 ) { + debugmsg( "For proficiency %s in dialogue, trying to learn negative without direct", prof.str() ); + return 0; + } + if( !direct ) { + d.actor( beta )->train_proficiency_for( prof, learned ); + } else { + d.actor( beta )->set_proficiency_practiced_time( prof, to_write ); + } return 0; }; } diff --git a/src/math_parser_func.h b/src/math_parser_func.h index a205790f76b9c..6c3a6febaed6e 100644 --- a/src/math_parser_func.h +++ b/src/math_parser_func.h @@ -171,10 +171,12 @@ constexpr double e_v = 2.7182818284590452354; #endif } // namespace math_constants -constexpr std::array constants{ +constexpr std::array constants{ math_const{ "π", math_constants::pi_v }, math_const{ "pi", math_constants::pi_v }, math_const{ "e", math_constants::e_v }, + math_const{ "true", 1 }, + math_const{ "false", 0 }, }; std::vector tokenize( std::string_view str, std::string_view separators, diff --git a/src/mattack_actors.cpp b/src/mattack_actors.cpp index aac41cdfdee6b..a204e2581bc82 100644 --- a/src/mattack_actors.cpp +++ b/src/mattack_actors.cpp @@ -1273,7 +1273,6 @@ void gun_actor::shoot( monster &z, const tripoint &target, const gun_mode_id &mo } tmp.set_wielded_item( gun ); - tmp.i_add( item( "UPS_off", calendar::turn, 1000 ) ); add_msg_if_player_sees( z, m_warning, description.translated(), z.name(), tmp.get_wielded_item()->tname() ); diff --git a/src/mutation.cpp b/src/mutation.cpp index 377046d82dc8e..a53bf1a6589d1 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -41,6 +41,7 @@ #include "rng.h" #include "text_snippets.h" #include "translations.h" +#include "uistate.h" #include "units.h" static const activity_id ACT_PULL_CREATURE( "ACT_PULL_CREATURE" ); diff --git a/src/mutation_data.cpp b/src/mutation_data.cpp index 6fd87d3eb2309..a0c3d39a1a25e 100644 --- a/src/mutation_data.cpp +++ b/src/mutation_data.cpp @@ -650,6 +650,8 @@ void mutation_branch::check_consistency() { for( const mutation_branch &mdata : get_all() ) { const trait_id &mid = mdata.id; + const mod_id &trait_source = mdata.src.back().second; + const bool basegame_trait = trait_source.str() == "dda"; const std::optional &s_id = mdata.scent_typeid; const std::map &an_id = mdata.anger_relations; for( const auto &style : mdata.initial_ma_styles ) { @@ -676,10 +678,13 @@ void mutation_branch::check_consistency() if( s_id && !s_id.value().is_valid() ) { debugmsg( "mutation %s refers to undefined scent type %s", mid.c_str(), s_id.value().c_str() ); } + // Suppress these onload warnings for overlapping mods for( const trait_id &replacement : mdata.replacements ) { const mutation_branch &rdata = replacement.obj(); + bool suppressed = rdata.src.back().second != trait_source && !basegame_trait; for( const mutation_category_id &cat : rdata.category ) { - if( std::find( mdata.category.begin(), mdata.category.end(), cat ) == mdata.category.end() ) { + if( std::find( mdata.category.begin(), mdata.category.end(), cat ) == mdata.category.end() && + !suppressed ) { debugmsg( "mutation %s lacks category %s present in replacement mutation %s", mid.c_str(), cat.c_str(), replacement.c_str() ); } @@ -691,11 +696,12 @@ void mutation_branch::check_consistency() } const mutation_branch &adata = addition.obj(); bool found = false; + bool suppressed = adata.src.back().second != trait_source && !basegame_trait; for( const mutation_category_id &cat : adata.category ) { found = found || std::find( mdata.category.begin(), mdata.category.end(), cat ) != mdata.category.end(); } - if( !found ) { + if( !found && !suppressed ) { debugmsg( "categories in mutation %s don't match any category present in additive mutation %s", mid.c_str(), addition.c_str() ); } @@ -704,12 +710,14 @@ void mutation_branch::check_consistency() for( const mutation_category_id &cat_id : mdata.category ) { if( !mdata.prereqs.empty() ) { bool found = false; + bool suppressed = false; for( const trait_id &prereq_id : mdata.prereqs ) { const mutation_branch &prereq = prereq_id.obj(); + suppressed = suppressed || ( prereq.src.back().second != trait_source && !basegame_trait ); found = found || std::find( prereq.category.begin(), prereq.category.end(), cat_id ) != prereq.category.end(); } - if( !found ) { + if( !found && !suppressed ) { debugmsg( "mutation %s is in category %s but none of its slot 1 prereqs have this category", mid.c_str(), cat_id.c_str() ); } @@ -717,12 +725,14 @@ void mutation_branch::check_consistency() if( !mdata.prereqs2.empty() ) { bool found = false; + bool suppressed = false; for( const trait_id &prereq_id : mdata.prereqs2 ) { const mutation_branch &prereq = prereq_id.obj(); + suppressed = suppressed || ( prereq.src.back().second != trait_source && !basegame_trait ); found = found || std::find( prereq.category.begin(), prereq.category.end(), cat_id ) != prereq.category.end(); } - if( !found ) { + if( !found && !suppressed ) { debugmsg( "mutation %s is in category %s but none of its slot 2 prereqs have this category", mid.c_str(), cat_id.c_str() ); } diff --git a/src/npc.cpp b/src/npc.cpp index fd803fbe05367..693c3001b198b 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -1864,7 +1864,7 @@ ret_val npc::wants_to_buy( const item &it, int at_price ) const icg_entry const *bl = myclass->get_shopkeeper_blacklist().matches( it, *this ); if( bl != nullptr ) { - return ret_val::make_failure( bl->message ); + return ret_val::make_failure( bl->message.translated() ); } // TODO: Base on inventory diff --git a/src/npc_class.cpp b/src/npc_class.cpp index 8c8e204a34151..2065d07749125 100644 --- a/src/npc_class.cpp +++ b/src/npc_class.cpp @@ -252,7 +252,7 @@ std::string shopkeeper_item_group::get_refusal() const return _( " does not trust you enough" ); } - return refusal; + return refusal.translated(); } void shopkeeper_item_group::deserialize( const JsonObject &jo ) diff --git a/src/npc_class.h b/src/npc_class.h index 68678e09d1a09..af07c213fc984 100644 --- a/src/npc_class.h +++ b/src/npc_class.h @@ -51,7 +51,7 @@ struct shopkeeper_item_group { item_group_id id = item_group_id( "EMPTY_GROUP" ); int trust = 0; bool strict = false; - std::string refusal; + translation refusal; std::function condition; // Rigid shopkeeper groups will be processed a single time. Default groups are not rigid, and will be processed until the shopkeeper has no more room or remaining value to populate goods with. diff --git a/src/npctalk.cpp b/src/npctalk.cpp index 91aa41e118184..d7ca41245c45b 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -173,6 +173,7 @@ struct item_search_data { itype_id id; item_category_id category; material_id material; + int calories = 0; std::vector flags; std::vector excluded_flags; bool worn_only; @@ -182,6 +183,9 @@ struct item_search_data { id = itype_id( jo.get_string( "id", "" ) ); category = item_category_id( jo.get_string( "category", "" ) ); material = material_id( jo.get_string( "material", "" ) ); + if( jo.has_int( "calories" ) ) { + calories = jo.get_int( "calories" ); + } for( std::string flag : jo.get_string_array( "flags" ) ) { flags.emplace_back( flag ); } @@ -202,6 +206,13 @@ struct item_search_data { if( !material.is_empty() && loc->made_of( material ) == 0 ) { return false; } + if( calories > 0 ) { + // This is very stupid but we need a dummy to calculate nutrients + npc dummy; + if( dummy.compute_effective_nutrients( *loc.get_item() ).kcal() < calories ) { + return false; + } + } for( flag_id flag : flags ) { if( !loc->has_flag( flag ) ) { return false; diff --git a/src/player_activity.cpp b/src/player_activity.cpp index 1926578532c68..4ae013b40d217 100644 --- a/src/player_activity.cpp +++ b/src/player_activity.cpp @@ -24,6 +24,7 @@ #include "string_formatter.h" #include "translations.h" #include "ui.h" +#include "uistate.h" #include "units.h" #include "value_ptr.h" diff --git a/src/proficiency.cpp b/src/proficiency.cpp index 4ee1d692295f7..40f3f87a0e5ab 100644 --- a/src/proficiency.cpp +++ b/src/proficiency.cpp @@ -555,13 +555,6 @@ void proficiency_set::deserialize( const JsonObject &jsobj ) jsobj.read( "learning", learning ); } -void proficiency_set::deserialize_legacy( const JsonArray &jo ) -{ - for( const std::string prof : jo ) { - known.insert( proficiency_id( prof ) ); - } -} - void learning_proficiency::serialize( JsonOut &jsout ) const { jsout.start_object(); diff --git a/src/proficiency.h b/src/proficiency.h index be16a72da1cd6..666c425c2e41d 100644 --- a/src/proficiency.h +++ b/src/proficiency.h @@ -156,7 +156,6 @@ class proficiency_set void serialize( JsonOut &jsout ) const; void deserialize( const JsonObject &jsobj ); - void deserialize_legacy( const JsonArray &jo ); }; struct learning_proficiency { diff --git a/src/savegame_json.cpp b/src/savegame_json.cpp index abf608989cad4..a5e147cfc597a 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -735,12 +735,12 @@ void Character::load( const JsonObject &data ) data.read( "healthy_mod", daily_health ); data.read( "health_tally", health_tally ); - // Remove check after 0.F - if( savegame_loading_version >= 30 ) { - if( data.has_array( "proficiencies" ) ) { - _proficiencies->deserialize_legacy( data.get_array( "proficiencies" ) ); - } else { - data.read( "proficiencies", _proficiencies ); + data.read( "proficiencies", _proficiencies ); + + // If the proficiency XP required has changed such that a proficiency is now known + for( const proficiency_id &prof : _proficiencies->learning_profs() ) { + if( _proficiencies->pct_practiced_time( prof ) >= prof->time_to_learn() ) { + _proficiencies->learn( prof ); } } diff --git a/src/sdltiles.cpp b/src/sdltiles.cpp index 25b358f11ab8e..aaaf5b921f5a4 100644 --- a/src/sdltiles.cpp +++ b/src/sdltiles.cpp @@ -70,6 +70,7 @@ #include "sdl_gamepad.h" #include "sdlsound.h" #include "string_formatter.h" +#include "uistate.h" #include "ui_manager.h" #include "wcwidth.h" #include "cata_imgui.h" diff --git a/src/shop_cons_rate.h b/src/shop_cons_rate.h index 8eabd14743d96..daa3ec9ed71e7 100644 --- a/src/shop_cons_rate.h +++ b/src/shop_cons_rate.h @@ -17,7 +17,7 @@ struct icg_entry { itype_id itype; item_category_id category; item_group_id item_group; - std::string message; + translation message; std::function condition; diff --git a/src/suffer.cpp b/src/suffer.cpp index 4e15e345f65bf..ce6e3c60061da 100644 --- a/src/suffer.cpp +++ b/src/suffer.cpp @@ -59,6 +59,7 @@ #include "text_snippets.h" #include "translations.h" #include "type_id.h" +#include "uistate.h" #include "units.h" #include "weather.h" #include "weather_type.h" diff --git a/src/talker.h b/src/talker.h index 93c15a074b2f2..c251552a4d7c1 100644 --- a/src/talker.h +++ b/src/talker.h @@ -269,6 +269,7 @@ class talker return 0_seconds; } virtual void set_proficiency_practiced_time( const proficiency_id &, int ) {} + virtual void train_proficiency_for( const proficiency_id &, int ) {} virtual std::vector skills_offered_to( const talker & ) const { return {}; } diff --git a/src/talker_character.cpp b/src/talker_character.cpp index c03d4eb9afe7c..d6422a29619bd 100644 --- a/src/talker_character.cpp +++ b/src/talker_character.cpp @@ -417,6 +417,11 @@ void talker_character::set_proficiency_practiced_time( const proficiency_id &pro me_chr->set_proficiency_practiced_time( prof, turns ); } +void talker_character::train_proficiency_for( const proficiency_id &prof, int turns ) +{ + me_chr->practice_proficiency( prof, time_duration::from_seconds( turns ) ); +} + bool talker_character_const::has_effect( const efftype_id &effect_id, const bodypart_id &bp ) const { return me_chr_const->has_effect( effect_id, bp ); diff --git a/src/talker_character.h b/src/talker_character.h index 7d8aade527950..d6a9b30973d87 100644 --- a/src/talker_character.h +++ b/src/talker_character.h @@ -238,6 +238,7 @@ class talker_character: public talker_clonerIO; } -// Pass this to your backend rendering function! Valid after Render() and until the next call to NewFrame() +// Pass this to your backend rendering function! Valid after Render() and until the next call to NewFrame() ImDrawData* ImGui::GetDrawData() { ImGuiContext& g = *GImGui; diff --git a/src/third-party/imgui/imgui.h b/src/third-party/imgui/imgui.h index 89902850bfd59..bb05856a1c1b7 100644 --- a/src/third-party/imgui/imgui.h +++ b/src/third-party/imgui/imgui.h @@ -2008,6 +2008,8 @@ struct ImGuiIO IMGUI_API void AddInputCharacter(unsigned int c); // Queue a new character input IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue a new character input from a UTF-16 character, it can be a surrogate IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue a new characters input from a UTF-8 string + IMGUI_API void SetPreEditText(const char *str); + IMGUI_API void ClearPreEditText(); IMGUI_API void SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native_scancode, int native_legacy_index = -1); // [Optional] Specify index for legacy <1.87 IsKeyXXX() functions with native indices + specify native keycode, scancode. IMGUI_API void SetAppAcceptingEvents(bool accepting_events); // Set master flag for accepting key/mouse/text events (default to true). Useful if you have native dialog boxes that are interrupting your application loop/refresh, and you want to disable events being queued while your app is frozen. @@ -2088,6 +2090,7 @@ struct ImGuiIO bool BackendUsingLegacyNavInputArray; // 0: using AddKeyAnalogEvent(), 1: writing to legacy io.NavInputs[] directly ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16() ImVector InputQueueCharacters; // Queue of _characters_ input (obtained by platform backend). Fill using AddInputCharacter() helper. + char PreEditText[255]; IMGUI_API ImGuiIO(); }; diff --git a/src/third-party/imgui/imgui_impl_sdl2.cpp b/src/third-party/imgui/imgui_impl_sdl2.cpp index 0ab73ec3e82e7..57c773518ffe0 100644 --- a/src/third-party/imgui/imgui_impl_sdl2.cpp +++ b/src/third-party/imgui/imgui_impl_sdl2.cpp @@ -333,6 +333,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) } case SDL_TEXTINPUT: { + io.ClearPreEditText(); io.AddInputCharactersUTF8(event->text.text); return true; } @@ -345,6 +346,9 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions. return true; } + case SDL_WINDOWEVENT_FOCUS_LOST: + ImGui::GetIO().ClearPreEditText(); + return true; case SDL_WINDOWEVENT: { // - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right. @@ -358,14 +362,41 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) bd->MouseWindowID = event->window.windowID; bd->PendingMouseLeaveFrame = 0; } - if (window_event == SDL_WINDOWEVENT_LEAVE) + if( window_event == SDL_WINDOWEVENT_LEAVE ) { bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1; + ImGui::GetIO().ClearPreEditText(); + } if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED) io.AddFocusEvent(true); - else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) - io.AddFocusEvent(false); + else if( event->window.event == SDL_WINDOWEVENT_FOCUS_LOST ) { + io.AddFocusEvent( false ); + ImGui::GetIO().ClearPreEditText(); + } return true; } + case SDL_TEXTEDITING: { + if(strlen(event->edit.text) > 0) + { + ImGui::GetIO().SetPreEditText(event->edit.text); + } + else + { + io.ClearPreEditText(); + } + break; + } +#if defined(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT) + case SDL_TEXTEDITING_EXT: { + if( event->editExt.text != nullptr && strlen(event->editExt.text) > 0) + { + ImGui::GetIO().SetPreEditText( event->editExt.text ); + } + else { + ImGui::GetIO().ClearPreEditText(); + } + break; + } +#endif } return false; } diff --git a/src/third-party/imgui/imgui_widgets.cpp b/src/third-party/imgui/imgui_widgets.cpp index 6001204ae0fcb..2a1e88cac3579 100644 --- a/src/third-party/imgui/imgui_widgets.cpp +++ b/src/third-party/imgui/imgui_widgets.cpp @@ -5012,7 +5012,33 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) { ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text); - draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); + + if(GImGui->IO.PreEditText && !is_multiline) + { + const char *preEditTextEnd = GImGui->IO.PreEditText + strlen(GImGui->IO.PreEditText); + ImWchar wcharBuf[255] = { 0 }; + int wlen = ImTextStrFromUtf8(wcharBuf, 255, GImGui->IO.PreEditText, preEditTextEnd); + char tmpBuf[255] = "\0"; + + ImVec2 drawPosStart = draw_pos - draw_scroll; + size_t tmpBufLen = ImTextStrToUtf8( tmpBuf, 255, text_begin, text_begin + state->Stb.cursor ); + draw_window->DrawList->AddText(g.Font, g.FontSize, drawPosStart, col, tmpBuf, tmpBuf + tmpBufLen, 0.0f, &clip_rect); + drawPosStart.x += InputTextCalcTextSizeW(GImGui, text_begin, text_begin + state->Stb.cursor).x; + ImU32 bg_color = GetColorU32( ImGuiCol_TextSelectedBg, 1.f ); + ImVec2 highlightRectMax = drawPosStart; + highlightRectMax += InputTextCalcTextSizeW(GImGui, wcharBuf, wcharBuf + wlen); + draw_window->DrawList->AddRectFilled( drawPosStart, highlightRectMax, bg_color ); + draw_window->DrawList->AddText(g.Font, g.FontSize, drawPosStart, col, GImGui->IO.PreEditText, preEditTextEnd, 0.0f, &clip_rect); + if( buf_display_end != NULL && buf_display + tmpBufLen < buf_display_end ) + { + drawPosStart.x = highlightRectMax.x; + draw_window->DrawList->AddText(g.Font, g.FontSize, drawPosStart, col, buf_display + tmpBufLen, buf_display_end, 0.0f, &clip_rect); + } + } + else + { + draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); + } } // Draw blinking cursor diff --git a/src/weather.cpp b/src/weather.cpp index 9ce867de352ca..6886c7d62ee63 100644 --- a/src/weather.cpp +++ b/src/weather.cpp @@ -43,6 +43,7 @@ #include "string_formatter.h" #include "translations.h" #include "trap.h" +#include "uistate.h" #include "units.h" #include "weather_gen.h" diff --git a/tests/food_fun_for_test.cpp b/tests/food_fun_for_test.cpp index 1e94b4a5ac1d6..95b4c1271e8ee 100644 --- a/tests/food_fun_for_test.cpp +++ b/tests/food_fun_for_test.cpp @@ -367,7 +367,7 @@ TEST_CASE( "fun_for_food_eaten_too_often", "[fun_for][food][monotony]" ) std::pair actual_fun; // A big box of tasty toast-ems - item toastem( "toastem_test", calendar::turn, 10 ); + item toastem( "toastem_test", calendar::turn ); REQUIRE( toastem.is_comestible() ); // Base fun value and monotony penalty for toast-em diff --git a/tests/item_autopickup_test.cpp b/tests/item_autopickup_test.cpp index 57070f9403b71..29ce14eb00162 100644 --- a/tests/item_autopickup_test.cpp +++ b/tests/item_autopickup_test.cpp @@ -212,12 +212,12 @@ TEST_CASE( "auto_pickup_should_recognize_container_content", "[autopickup][item] REQUIRE( here.i_at( ground ).empty() ); // add random items to the tile on the ground - here.add_item( ground, item( itype_marble, calendar::turn, 10 ) ); - here.add_item( ground, item( itype_pebble, calendar::turn, 15 ) ); + here.add_item( ground, item( itype_marble, calendar::turn ) ); + here.add_item( ground, item( itype_pebble, calendar::turn ) ); - // codeine (20)(WL) + // codeine (WL) WHEN( "there is an item on the ground whitelisted in auto-pickup rules" ) { - unique_item item_codeine = unique_item( itype_codeine, 20 ); + unique_item item_codeine = unique_item( itype_codeine ); REQUIRE( item_codeine.spawn_item( ground ) ); add_autopickup_rule( item_codeine.get(), true ); @@ -226,9 +226,9 @@ TEST_CASE( "auto_pickup_should_recognize_container_content", "[autopickup][item] expect_to_find( backpack, { &item_codeine } ); } } - // plastic prescription bottle > (WL)aspirin (12) + // plastic prescription bottle > (WL)aspirin WHEN( "there is a container on the ground containing only items whitelisted in auto-pickup rules" ) { - unique_item item_aspirin = unique_item( itype_aspirin, 12 ); + unique_item item_aspirin = unique_item( itype_aspirin ); unique_item item_prescription_bottle = unique_item( itype_bottle_plastic_pill_prescription, { &item_aspirin @@ -244,10 +244,10 @@ TEST_CASE( "auto_pickup_should_recognize_container_content", "[autopickup][item] } ); } } - // plastic bag > paper (5), paper wrapper (WL) > chocolate candy (3) + // plastic bag > paper, paper wrapper (WL) > chocolate candy WHEN( "there is a container on the ground with a deeply nested item whitelisted in auto-pickup rules" ) { - const unique_item item_paper = unique_item( itype_paper, 5 ); - const unique_item item_chocolate_candy = unique_item( itype_candy2, 3 ); + const unique_item item_paper = unique_item( itype_paper ); + const unique_item item_chocolate_candy = unique_item( itype_candy2 ); const unique_item item_paper_wrapper = unique_item( itype_wrapper, { &item_chocolate_candy } ); @@ -387,8 +387,8 @@ TEST_CASE( "auto_pickup_should_consider_item_rigidness_and_seal", "[autopickup][ // small tin can (sealed) > canned tuna fish (WL), canned meat WHEN( "there is a sealed container on the ground containing items whitelisted in auto-pickup rules" ) { item item_medium_tin_can = item( itype_can_medium ); - unique_item item_canned_tuna = unique_item( itype_can_tuna, 1, true ); - unique_item item_canned_meat = unique_item( itype_meat_canned, 1, true ); + unique_item item_canned_tuna = unique_item( itype_can_tuna, true ); + unique_item item_canned_meat = unique_item( itype_meat_canned, true ); // insert items inside can and seal it item_medium_tin_can.force_insert_item( *item_canned_tuna.get(), pocket_type_container ); @@ -410,8 +410,8 @@ TEST_CASE( "auto_pickup_should_consider_item_rigidness_and_seal", "[autopickup][ WHEN( "there is a sealed container on the ground containing no whitelisted items" ) { item item_medium_tin_can = item( itype_can_medium ); item item_bottle_plastic = item( itype_bottle_plastic ); - unique_item item_canned_tuna = unique_item( itype_can_tuna, 1, true ); - unique_item item_canned_meat = unique_item( itype_meat_canned, 1, true ); + unique_item item_canned_tuna = unique_item( itype_can_tuna, true ); + unique_item item_canned_meat = unique_item( itype_meat_canned, true ); // insert items inside can and seal it item_medium_tin_can.force_insert_item( *item_canned_tuna.get(), pocket_type_container ); @@ -447,15 +447,16 @@ TEST_CASE( "auto_pickup_should_respect_volume_and_weight_limits", "[autopickup][ item &backpack = *backpack_iter; REQUIRE( they.has_item( backpack ) ); - // backpack > lump of steel (5)(WL), cigrarette (3)(WL), paper (10)(WL) + // backpack > lump of steel (WL), cigrarette (WL), paper (WL) GIVEN( "there is a container with some items that exceed volume or weight limit" ) { options_manager &options = get_options(); options_manager::cOpt &ap_weight_limit = options.get_option( "AUTO_PICKUP_WEIGHT_LIMIT" ); options_manager::cOpt &ap_volume_limit = options.get_option( "AUTO_PICKUP_VOLUME_LIMIT" ); + // Note: This relies on charge-spawning behavior for steel lumps unique_item item_lump_of_steel = unique_item( itype_steel_lump, 5 ); - unique_item item_cigarette = unique_item( itype_cig, 3 ); - unique_item item_paper = unique_item( itype_paper, 10 ); + unique_item item_cigarette = unique_item( itype_cig ); + unique_item item_paper = unique_item( itype_paper ); unique_item item_backpack = unique_item( itype_backpack, { &item_lump_of_steel, &item_cigarette, &item_paper } ); @@ -524,7 +525,7 @@ TEST_CASE( "auto_pickup_should_consider_item_ownership", "[autopickup][item]" ) REQUIRE( they.has_item( backpack ) ); // candy cigarette(WL) - // pack(WL) > cigarette (2)(WL), rolling paper (10)(WL) + // pack(WL) > cigarette (WL), rolling paper (WL) GIVEN( "there is a container with some items and an item outside it on the ground" ) { options_manager::cOpt &autopickup_owned = get_options().get_option( "AUTO_PICKUP_OWNED" ); // make sure the autopickup owned option is disabled @@ -532,8 +533,8 @@ TEST_CASE( "auto_pickup_should_consider_item_ownership", "[autopickup][item]" ) autopickup_owned.setValue( "false" ); } unique_item item_candy_cigarette = unique_item( itype_candycigarette ); - unique_item item_cigarette = unique_item( itype_cig, 2 ); - unique_item item_rolling_paper = unique_item( itype_rolling_paper, 10 ); + unique_item item_cigarette = unique_item( itype_cig ); + unique_item item_rolling_paper = unique_item( itype_rolling_paper ); unique_item item_pack = unique_item( itype_box_cigarette, { &item_cigarette, &item_rolling_paper } ); @@ -601,8 +602,8 @@ TEST_CASE( "auto_pickup_should_not_implicitly_pickup_corpses", "[autopickup][ite expect_to_find( *body_bag, {} ); } WHEN( "the corpse contains whitelisted items" ) { - unique_item item_cigarette = unique_item( itype_cig, 5 ); - unique_item item_rolling_paper = unique_item( itype_rolling_paper, 10 ); + unique_item item_cigarette = unique_item( itype_cig ); + unique_item item_rolling_paper = unique_item( itype_rolling_paper ); item *found = item_corpse.find_on_ground( ground ); found->force_insert_item( *item_cigarette.get(), pocket_type_container ); diff --git a/tests/npc_talk_test.cpp b/tests/npc_talk_test.cpp index 983a011b92ab5..5c581c9e77bc7 100644 --- a/tests/npc_talk_test.cpp +++ b/tests/npc_talk_test.cpp @@ -1266,7 +1266,7 @@ TEST_CASE( "npc_arithmetic", "[npc_talk]" ) Character &player_character = get_avatar(); d.add_topic( "TALK_TEST_ARITHMETIC" ); - gen_response_lines( d, 31 ); + gen_response_lines( d, 32 ); calendar::turn = calendar::turn_zero; REQUIRE( calendar::turn == time_point( 0 ) ); @@ -1468,6 +1468,8 @@ TEST_CASE( "npc_arithmetic", "[npc_talk]" ) // "Sets Test Proficiency learning done to 24h." effects = d.responses[30].success; effects.apply( d ); + add_msg( m_bad, "%s: %g", proficiency_prof_test.str(), + player_character.get_proficiency_practice( proficiency_prof_test ) ); CHECK( player_character.has_proficiency( proficiency_prof_test ) == true ); proficiencies_vector = player_character.learning_proficiencies(); CHECK( std::count( proficiencies_vector.begin(), @@ -1492,6 +1494,54 @@ TEST_CASE( "npc_arithmetic", "[npc_talk]" ) proficiencies_vector.end(), proficiency_prof_test ) == 0 ); + + // Proficency learning without 'direct': true is impacted by focus + const auto prof_xp = [&player_character]() { + return to_seconds( player_character.get_proficiency_practiced_time( proficiency_prof_test ) ); + }; + + // For 100 focus + player_character.set_focus( 100 ); + // No starting XP + REQUIRE( prof_xp() == 0 ); + + // "Learns Test Proficiency for 1h" + effects = d.responses[31].success; + effects.apply( d ); + + int amt_100 = prof_xp(); + CAPTURE( amt_100 ); + + CHECK( player_character.has_proficiency( proficiency_prof_test ) == false ); + proficiencies_vector = player_character.learning_proficiencies(); + CHECK( std::count( proficiencies_vector.begin(), + proficiencies_vector.end(), + proficiency_prof_test ) == 1 ); + + // Reset progress + player_character.set_proficiency_practice( proficiency_prof_test, 0_seconds ); + REQUIRE( prof_xp() == 0 ); + + // For 5 focus + player_character.set_focus( 5 ); + + // "Learns Test Proficiency for 1h" + effects = d.responses[31].success; + effects.apply( d ); + + int amt_5 = prof_xp(); + CAPTURE( amt_5 ); + + CHECK( player_character.has_proficiency( proficiency_prof_test ) == false ); + proficiencies_vector = player_character.learning_proficiencies(); + CHECK( std::count( proficiencies_vector.begin(), + proficiencies_vector.end(), + proficiency_prof_test ) == 1 ); + + // Simply check that they're less, don't need to get any fancier + CHECK( amt_5 < amt_100 ); + + // Teardown player_character.remove_value( var_name ); }